🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### **Reflect Resolution** ### One of the most powerful features of the Laravel container is its ability to automatically resolve dependencies via reflection. Reflection is the ability to inspect a classes and methods. For example, the PHP ``ReflectionClass`` class allows you to inspect the method avaliable on a given class. The PHP method ``method_exists`` is also a form of reflection. To play with PHP's reflection class, try the followring code on one of your classes: ~~~ <?php <!-- lang: php --> $reflection = new ReflectionClass('StripeBiller'); var_dump($reflection->getMethods()); var_dump($reflection->getConstants()); ~~~ By leveraging this powerful feature of PHP, the Laravel IoC container can do some interesting things! For instance, consider the following class: ~~~ <!-- lang:php --> class UserController extends BaseController { public function __construct(StripBiller $biller) { $this->biller = $biller; } } ~~~ Note that the controller is type-hinting the StripBiller class. We are able to retrieve this type-hint using reflection. When the Laravel container does not have a resolver for a class explictity bound, it will try to resolve the class via reflection. The flow looks like this: 1. Do I have a resolver for ``StripBiller``? 2. No resolver? Reflect into ``StripBiller`` to determin if it has dependencies. 3. Resolve any dependencies needed by ``StripBiller`` (recursive). 4. Instantiate new ``StripBiller`` instance via ``ReflectionClass->newInstanceArgs()``. As you can see, the container is doing a lot of heavy lifting for you, which saves you from having to write resolves for every single one of your classes. This is one of the most powerful and unique features of the Laravel container, and having a strong grasp of this capability is very beneficial when building large Laravel applications. Now, let's modify our controller a bit. What if it looks like this? Assuming we have not explicitly bound a resolver for ``BillerInterface``, how will the container know what class to inject? Remember, interface can't be instantiated since they are just contracts. Without us giving the container any more information, it will be unable to instantiate this dependency. We need to specify a class that should be used as the default implementation of this interface, and we may do so via the ``bind`` method: ~~~ <?php <!-- lang:php --> App::bind('BillerInterface','StripBiller'); ~~~ Here, we are passing a string instead of a Closure, and this string tells the container to always use the ``StripBiller`` class anytime it needs an implementation of the ``BillerInterface`` interface. Again, we're gaining the ability to switch implementations of services with a simple one-line change to our container binding. For example, if we need to switch to Balanced Payments as our billing provider, we simply write a new ``BalancedBiller`` implementation of ``BillerInterface``, and change our container binding: ~~~ <?php <!-- lang:php --> App::bind('BillerInterface', 'BalancedBiller'); ~~~ Automatically, our new implementation will be used throughout out application! When binding implementations to interfaces, you may also use the singleton method so the container only instantiates one instance of the class per request cycle: ~~~ <?php <!-- lang:php --> App::singleton('BillerInterface', 'StripBiller'); ~~~ > > ### **Master The Container** ### > > Want to learn even more about the container? Read through its source! The container is only one class: ``Illuminate\Container\Container``. Read over the source code to gain a deeper understanding of how the container works under the hood. >