Slide 1

Slide 1 text

Demystifying The Container Also known as the IOC container, DI container & Service container @introwit 1

Slide 2

Slide 2 text

"A deep understanding of the Laravel service container is essential to building a powerful, large application, as well as for contributing to the Laravel core itself." 1 Laravel documentation @introwit 2

Slide 3

Slide 3 text

Container @introwit 3

Slide 4

Slide 4 text

Storyline of this talk 4 Let's prepare some food ! 4 You enter the kitchen to see some spices are on the first shelf, some on second, etc " 4 Not enough funds to order from Uber Eats # Be the hero chef of your own story kitchen! @introwit 4

Slide 5

Slide 5 text

The Problem Spices are scattered. Have to reach out to different places again & again to get the spices. Put them back after the food is prepared. Repeat. It's not really in your control. The control is with the spices we are dependent on to prepare the food. @introwit 5

Slide 6

Slide 6 text

IOC Inversion Of Control You took all the spices and added them to a container with respective labels. Now you don't need to reach-out to or search at different places. You inverted the control. @introwit 6

Slide 7

Slide 7 text

DI Dependency Injection Now the need for all the things you are dependent upon can be fulfilled by that container. The container will inject the dependency in the food as per your needs. @introwit 7

Slide 8

Slide 8 text

"The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection." 1 Laravel documentation @introwit 8

Slide 9

Slide 9 text

MasterChef or a Laravel meet-up? @introwit 9

Slide 10

Slide 10 text

app() @introwit 10

Slide 11

Slide 11 text

But why isn't it called container()? Because the instances app() method generates are of the class called Application, and that class extends the Container class. @introwit 11

Slide 12

Slide 12 text

So to create an instance of the container: $container = app(); @introwit 12

Slide 13

Slide 13 text

Resolving & Binding @introwit 13

Slide 14

Slide 14 text

Resolving things out of the container $car = app()->make(Car::class); vs $car = new Car; @introwit 14

Slide 15

Slide 15 text

Resolving things out of the container $car = app()->make(Car::class); vs $car = new Car(Engine $engine); @introwit 15

Slide 16

Slide 16 text

Resolving things out of the container $car = app()->make(Car::class); vs $car = new Car(Engine $engine(Oil $oil)); @introwit 16

Slide 17

Slide 17 text

The magic called "Reflection" ! @introwit 17

Slide 18

Slide 18 text

Reflection It's the ability of a programme to inspect & describe itself. Remember get_class($data) or get_class_methods(Car::class)? PS: There are many more PHP Reflection functions available. @introwit 18

Slide 19

Slide 19 text

How Laravel Uses Reflection? app()->make(Car::class); -> Get the list of dependencies. (The class Car has a dependency called $engine) -> Use the typehint and instantiate the dependency and pass it. (Use the Engine typehint to reach the class) @introwit 19

Slide 20

Slide 20 text

What if no typehints are available? :( We can manually bind things into the container. So that when a typehint is unavailable, our code doesn't break and fallbacks to check if we have defined some bindings for the same. @introwit 20

Slide 21

Slide 21 text

Assume $engine wasn't typehinted. class Car { function __construct($engine) {} } app()->make(Car::class) would then fail since it wouldn't know what exactly $engine is? @introwit 21

Slide 22

Slide 22 text

Binding things into the container app()->bind(Car::class, function () { return new Car(new Engine); }); Now when we do app()->make(Car::class) or whenever Car::class is resolved out of the container, it would run the callback above and return what we define. @introwit 22

Slide 23

Slide 23 text

What else? @introwit 23

Slide 24

Slide 24 text

Contextual Binding $this->app->when(PhotoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('local'); }); $this->app->when([VideoController::class, UploadController::class]) ->needs(Filesystem::class) ->give(function () { return Storage::disk('s3'); }); @introwit 24

Slide 25

Slide 25 text

Container Events $this->app->resolving(function ($object, $app) { // Called when container resolves object of any type... }); $this->app->resolving(Storage::class, function ($api, $app) { // Called when container resolves object of "Storage" class... // Useful for things like setting up some props or credentials/authentication with the object }); @introwit 25

Slide 26

Slide 26 text

Few more container goodies 4 You can bind anything into the container, something as simple as a dynamic key-value pair: app()->bind('random-string', function ($app, $params) { return str_random($params['length']); }); // app()->makeWith('random-string', ['length' => 5]); 4 Easily Swap Implementations. @introwit 26

Slide 27

Slide 27 text

@introwit @introwit 27