I was learning Laravel recently and happened to learn about the IOC container, but I found that there was less information on this aspect on the Internet, so I summarized my learning. The following article mainly introduces you to the IOC container in the Laravel learning tutorial. Friends in need can refer to the information. Let’s take a look together.
Preface
Laravel uses IoC (Inversion of Control, inversion of control, this is a design pattern, you can check the encyclopedia first) container this Powerful tools for managing class dependencies. Dependency injection (also a design pattern, generally used to implement IoC) is a method that does not require writing fixed code to handle dependencies between classes. Instead, these dependencies are injected at runtime, which allows greater flexibility when handling dependencies. flexibility.
Understanding the Laravel IoC container is necessary for building powerful applications and also helps the Laravel core itself. Not much to say below, let’s take a look at the detailed introduction.
Basic use case
Bind a type to a container
IoC containers have two ways to resolve dependencies: via Closure callback or automatic resolution. First, let's explore closure callbacks. First, you need to bind a "type" to the container:
App::bind('foo', function($app) { return new FooBar; });
Get a type from the container
$value = App::make('foo');
When the App::make
method is executed, the closure function is executed and the result is returned.
Bind a "shared" type to the container
Sometimes, you only want to process the type bound to the container once, and then get it from the container They should all be the same instance:
App::singleton('foo', function() { return new FooBar; });
Bind an existing type instance to the container
You can also use the instance method , bind an existing object interface to the container:
$foo = new Foo; App::instance('foo', $foo);
Where to register the binding
IoC binding, much like event handlers or route filtering, is usually done after "bootstrap code". In other words, they are executed when your application is ready to handle the request, that is, before a route or controller is actually executed. Like other boot code, the start file usually registers a method as an IoC binding. Alternatively, you can create a file app/ioc.php (the file name does not have to be the same) and include it in the start file.
If your application has a large number of IoC bindings, or you want to split the IoC bindings into different files according to different classifications, you can try binding in the service provider (see below)
Automatic parsing
Get a class
The IoC container is powerful enough in many scenarios No configuration is required to obtain the class. For example
class FooBar { public function __construct(Baz $baz) { $this->baz = $baz; } } $fooBar = App::make('FooBar');
Note: Although we have not registered the FooBar class in the container, the container can still obtain the class, even automatically Inject Baz dependency!
When a type is not bound to the container, the IoC container will use PHP's reflection tool to inspect the class and read the type hint of the constructor. Using this information, the container can automatically build class instances.
Bind an interface implementation
However, in some cases, a class may rely on an interface implementation rather than a "concrete class". When in this case, the App::bind
method must inform the container which interface implementation to inject:
App::bind('UserRepositoryInterface', 'DbUserRepository');
Now consider this controller:
class UserController extends BaseController { public function __construct(UserRepositoryInterface $users) { $this->users = $users; } }
Since we bound UserRepositoryInterface to a concrete class, DbUserRepository will be automatically injected into the controller when the controller is created.
Practical Use Cases
Laravel provides several ways to enhance application scalability and testability using IoC containers. A prime example is getting a controller. All controllers are obtained through the IoC container, which means that you can type-hint dependencies in the controller constructor and they will be injected automatically.
Type hints for controller dependencies
class OrderController extends BaseController { public function __construct(OrderRepository $orders) { $this->orders = $orders; } public function getIndex() { $all = $this->orders->all(); return View::make('orders', compact('all')); } }
In this example, OrderRepository will be automatically injected into the controller . This means that when unit tests simulate requests, the OrderRepository will be bound to the container and injected into the controller, allowing painless interaction with the database layer.
Other examples of IoC usage
Filters, composers, and event handlers can also be obtained from the IoC container. When registering them, simply give the class name they use:
Route::filter('foo', 'FooFilter'); View::composer('foo', 'FooComposer'); Event::listen('foo', 'FooHandler');
Service Provider
服务器提供器是将一组相关 IoC 注册到单一路径的有效方法。将它们看做是一种引导组件的方法。在服务器提供器里,你可以注册自定义的验证驱动器,使用 IoC 容器注册应用程序仓库类,甚至是自定义 Artisan 命令。
事实上,大多数核心 Laravel 组件包含服务提供器。应用程序所有注册在服务提供器的均列在 app/config/app.php 配置文件的 providers 数组中。
定义服务提供器
要创建服务提供器,只需继承 Illuminate\Support\ServiceProvider 类并且定义一个 register 方法:
use Illuminate\Support\ServiceProvider; class FooServiceProvider extends ServiceProvider { public function register() { $this->app->bind('foo', function() { return new Foo; }); } }
注意:在 register 方法,应用程序通过 $this->app 属性访问 IoC 容器。一旦你已经创建了提供器并且想将它注册到应用程序中, 只需简单的放入 app 配置文件里 providers 数组中。
运行时注册服务提供器
你也可以使用 App::register
方法在运行时注册服务提供器:
App::register('FooServiceProvider');
容器事件
注册获取事件监听者
容器在每次获取对象时都触发一个事件。你可以通过使用 resolving 方法来监听该事件:
App::resolvingAny(function($object) { // }); App::resolving('foo', function($foo) { // });
注意:获取到的对象将会传入回调函数中。
The above is the detailed content of Detailed explanation of the usage of IOC container in Laravel framework. For more information, please follow other related articles on the PHP Chinese website!