laravel里,当我们在controller 的构造方法,或者实例方法中用类型指定一个参数时,系统可以自动帮你把该参数的实例注入进去。
那么内部是如何实现的呢?
先列出几个技术点
1.类ReflectionClass
该类用于对指定类进行反射,提取类信息。
2.ReflectionClass.getConstructor
获取指定类的构造方法,返回ReflectionMethod
3.ReflectionMethod.getParameters
获取方法的参数信息
4.ReflectionClass.newInstanceArgs
创建类实例
当,laravel通过路由寻找到controller的类名时,会先创建实例,如果构造函数里包含指定了类型的参数,并且router设定里并没有传递时,
就会创建这个参数的实例,当然这个参数的构造方法如果还包含指定类型的参数时,还是会创建,一直递归到没有参数指定为止。
入口代码在类Illuminate\Container\Containerd的方法make里
public function make($abstract, array $parameters = []) { $abstract = $this->getAlias($this->normalize($abstract)); // If an instance of the type is currently being managed as a singleton we'll // just return an existing instance instead of instantiating new instances // so the developer can keep using the same objects instance every time. if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } $concrete = $this->getConcrete($abstract); // We're ready to instantiate an instance of the concrete type registered for // the binding. This will instantiate the types, as well as resolve any of // its "nested" dependencies recursively until all have gotten resolved. if ($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete, $parameters); } else { $object = $this->make($concrete, $parameters); } // If we defined any extenders for this type, we'll need to spin through them // and apply them to the object being built. This allows for the extension // of services, such as changing configuration or decorating the object. foreach ($this->getExtenders($abstract) as $extender) { $object = $extender($object, $this); } // If the requested type is registered as a singleton we'll want to cache off // the instances in "memory" so we can return it later without creating an // entirely new instance of an object on each subsequent request for it. if ($this->isShared($abstract)) { $this->instances[$abstract] = $object; } $this->fireResolvingCallbacks($abstract, $object); $this->resolved[$abstract] = true; return $object; }
这个地方的核心代码是在类Illuminate\Container\Containerd的方法build里
public function build($concrete, array $parameters = []) { // If the concrete type is actually a Closure, we will just execute it and // hand back the results of the functions, which allows functions to be // used as resolvers for more fine-tuned resolution of these objects. if ($concrete instanceof Closure) { return $concrete($this, $parameters); } $reflector = new ReflectionClass($concrete); // If the type is not instantiable, the developer is attempting to resolve // an abstract type such as an Interface of Abstract Class and there is // no binding registered for the abstractions so we need to bail out. if (! $reflector->isInstantiable()) { if (! empty($this->buildStack)) { $previous = implode(', ', $this->buildStack); $message = "Target [$concrete] is not instantiable while building [$previous]."; } else { $message = "Target [$concrete] is not instantiable."; } throw new BindingResolutionException($message); } $this->buildStack[] = $concrete; $constructor = $reflector->getConstructor(); // If there are no constructors, that means there are no dependencies then // we can just resolve the instances of the objects right away, without // resolving any other types or dependencies out of these containers. if (is_null($constructor)) { array_pop($this->buildStack); return new $concrete; } $dependencies = $constructor->getParameters(); // Once we have all the constructor's parameters we can create each of the // dependency instances and then use the reflection instances to make a // new instance of this class, injecting the created dependencies in. $parameters = $this->keyParametersByArgument( $dependencies, $parameters ); $instances = $this->getDependencies( $dependencies, $parameters ); array_pop($this->buildStack); return $reflector->newInstanceArgs($instances); }
相关推荐
在Laravel框架中,构造函数自动依赖注入是框架内部IoC容器的一个核心功能,它允许开发者在控制器、服务、模型等类的构造函数中声明依赖,而无需手动创建这些依赖的实例。 在Laravel中,自动依赖注入的关键在于类型...
在Laravel中,最常见的是构造函数注入,即在类的构造函数中声明依赖的类,然后服务容器会在创建类实例时自动注入这些依赖项。通过定义接口和实现类,Laravel的容器可以更灵活地控制依赖的解析过程。 3. 自动解析...
Java的依赖注入已经是一个很常见的概念了,Spring框架主要就是解决了这一点,在PHP的laravel框架中,也出现了依赖注入的方式。 依赖注入就控制反转的一种是实现方式,面向对象的特征的重要体现,那么依赖注入中什么...
在Laravel框架中,`laravel-loader`是一个关键组件,它涉及到框架的自动加载机制,这对于高效、整洁的代码组织至关重要。Laravel的自动加载功能是通过Composer来实现的,它使得我们可以方便地引入和使用类库,而无需...
1. **服务绑定**:Laravel 会自动将 Intercom 客户端注入到依赖于 `\PatricPoba\IntercomLaravel\Intercom` 类的任何类中。 2. **调用 API 方法**:例如,你可以使用 `user()` 方法创建或更新用户,`trackEvent()` ...
- **深入理解**:如果 URI 参数片段与控制器方法中的变量名匹配,并且变量被类型提示为 Eloquent 模型类,Laravel 将自动注入对应的模型实例。更多信息请参考 Laravel 5.2 文档中关于 HTTP 路由模型绑定的部分。 ##...
5. **依赖注入**:Laravel支持依赖注入,通过容器管理服务的创建和解析,使得代码更松耦合,易于测试和扩展。 6. **路由**:Laravel的路由系统允许开发者灵活地定义HTTP请求与控制器方法之间的映射。 7. **中间件*...
Service Providers是Laravel依赖注入容器的核心部分,允许开发者在应用程序启动时进行配置,并提供服务给整个应用。 例如,"Multipass-SDK-Laravel-master"这个压缩包可能包含一个Laravel SDK,用于处理Multipass...
4. **使用服务**: 在Laravel应用中,注入`XeroOAuth2\Client\Manager`实例,调用其提供的方法来执行API请求,如创建或更新数据。 5. **错误处理**: 服务提供商通常会封装API的错误响应,确保在应用中优雅地处理异常...
- **CSRF保护**:laravel自动为表单生成并验证CSRF令牌,防止跨站请求伪造。 - **SQL注入防护**:Eloquent ORM的查询构造器能有效防止SQL注入。 - **缓存**:laravel支持多种缓存驱动,如Redis、Memcached,可以...
1. **计数器服务提供者(ServiceProvider)**:这是Laravel中注册服务包的主要方式,使得`laravel-counter`可以注入到Laravel的依赖注入容器中,方便全局访问和使用。 2. **计数器迁移(Migrations)**:为了存储和...
3. **依赖注入**:在类的构造函数中声明依赖,让服务容器自动注入,这有助于保持代码的松耦合和易于测试。 通过理解和熟练掌握服务提供者和门面,开发者能够更高效地构建Laravel应用程序,充分利用框架提供的强大...
3. **服务提供者**:作为Laravel的服务提供者,`laravel-versioner` 可以无缝集成到Laravel的依赖注入系统中,方便在任何地方使用版本信息。 4. **Artisan命令**:它提供了Artisan命令行工具,允许开发者在终端中...
8. **依赖注入**:虽然Laravel的依赖注入主要基于配置,但注释可用于提供更明确的类型提示,特别是在处理第三方库时。 9. **日志和追踪**:通过注释记录代码执行过程中的重要步骤,有助于调试和性能分析。 10. **...
通过服务容器,Laravel可以自动处理对象的创建和依赖关系,使得代码更易于测试和解耦。服务容器提供了一个“绑定”(binding)机制,允许我们将类的实例或工厂方法与特定的标识(接口或类名)关联起来。 **二、...
1. **视图数据共享**:`laravel-share`允许开发者定义一组全局的数据,这些数据会在每次渲染视图时自动注入。这样,你不必在每个控制器方法中都添加`view()->share()`来共享数据,只需要在应用启动时配置一次即可。 ...
然后,根据提供的文档或服务提供者的自动发现机制,将其集成到Laravel应用中。 总结来说,"laravel-option"扩展为Laravel添加了更强大的选项管理和配置能力,它可能包括自定义的选项存储策略、API接口以及对服务...
Laravel的依赖注入系统会自动处理这一切,让你在需要使用HTTP客户端时,只需通过依赖注入就能得到一个实例。 `laravel-httplug`的主要优点在于其灵活性。你可以根据需求选择不同的HTTP客户端,比如Guzzle、Curl或者...