In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces "what is the concept of laravel service container". In daily operation, I believe many people have doubts about the concept of laravel service container. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "what is the concept of laravel service container?" Next, please follow the editor to study!
In laravel, the service container is a powerful tool for managing class dependencies and implementing dependency injection. When an application needs to use a service, the service container parses the service, automatically resolves the dependencies between services, and then gives it to the application to use.
The operating environment of this tutorial: windows7 system, Laravel6 version, Dell G3 computer.
What is a service container?
The Laravel service container is a powerful tool for managing class dependencies and implementing dependency injection. The term dependency injection looks fancy on the surface, but it actually refers to "injecting" class dependencies into a class through a constructor or, in some cases, a "setter" method.
The functional modules in Laravel, such as Route, Eloquent ORM, Request, Response and so on, are actually provided by core-independent class modules. From registration to instantiation, these classes are finally used by us, which are actually responsible for the service container of laravel.
There are two concepts in the service container: control inversion (IOC) and dependency injection (DI)
Dependency injection and control inversion are different descriptions of the same thing from different angles. Dependency injection is described from the perspective of the application, which relies on the container to create and inject the external resources it needs. The control inversion is described from the point of view of the container, the container controls the application, and the container injects the external resources needed by the application into the application in reverse.
In Laravel, the framework binds various services that come with it to the service container, and we can also bind custom services to the container. When an application needs to use a service, the service container parses the service, automatically resolves the dependencies between services, and then gives it to the application to use.
Let's take a look at how service binding and parsing are implemented in Laravel.
Service binding
Common methods of binding services to containers are instance, bind, singleton, and alias. Let's take a look at it separately.
Instance
When you bind an existing object to a service container, and then resolve the service by name, the container will always return an instance of the binding.
$api = new HelpSpot\ API (new HttpClient); $this- > app- > instance ('HelpSpot\ Api', $api)
Registers the object in the $instnces property of the service container
['HelpSpot\ Api' = > $api//$api is an object of the API class, abbreviated here]
Bind
Bind a service to a service container
There are three ways to bind:
1. Bind itself
$this- > app- > bind ('HelpSpot\ API', null)
two。 Bind closure
$this- > app- > bind ('HelpSpot\ API', function () {return new HelpSpot\ API ();}); / / closure directly provides class implementation $this- > app- > bind (' HelpSpot\ API', function ($app) {return new HelpSpot\ API ($app- > make ('HttpClient');}); / / closure returns classes that need dependency injection
3. Bind interface and implementation
$this- > app- > bind ('Illuminate\ Tests\ Container\ IContainerContractStub',' Illuminate\ Tests\ Container\ ContainerImplementationStub')
For the first case, inside the bind method, closures are generated for the service through getClosure () before binding to the service. Let's take a look at the source code of the bind method.
Public function bind ($abstract, $concrete = null, $shared = false) {$abstract = $this- > normalize ($abstract); $concrete = $this- > normalize ($concrete) / / if $abstract is an array like ['Illuminate/ServiceName' = >' service_alias'] / / extract alias "service_alias" and register in $aliases [] / Note: array alias binding is removed in 5.4.Please use the following alias method if (is_array ($abstract)) {list ($abstract, $alias) = $this- > extractAlias ($abstract); $this- > alias ($abstract, $alias) } $this- > dropStaleInstances ($abstract); if (is_null ($concrete)) {$concrete = $abstract;} / / if only $abstract is provided, generate the concrete closure if (! $concrete instanceof Closure) {$concrete = $this- > getClosure ($abstract, $concrete);} $this- > bindings [$abstract] = compact ('concrete',' shared'); if ($this- > resolved ($abstract)) {$this- > rebound ($abstract) }} protected function getClosure ($abstract, $concrete) {/ / $c is $container, the service container, which is passed to this variable return function ($c, $parameters = []) use ($abstract, $concrete) {$method = ($abstract = = $concrete) on callback? 'build':' make'; return $c-> $method ($concrete, $parameters);};}
Bind registers the service in the $bindings attribute of the service container like this:
$bindings = ['HelpSpot\ API' = > [/ / closure binding' concrete' = > function ($app, $paramters = []) {return $app- > build ('HelpSpot\ API') }, 'shared' = > false// if it is singleton binding, this value is true]' Illuminate\ Tests\ Container\ IContainerContractStub' = > [/ / API implementation binding 'concrete' = >' Illuminate\ Tests\ Container\ ContainerImplementationStub', 'shared' = > false]
Singleton
Public function singleton ($abstract, $concrete = null) {$this- > bind ($abstract, $concrete, true);}
The singleton method is a variant of the bind method, binding a class or interface that only needs to be parsed once to the container, and then the next call to the container the service will return the same instance
Alias
Register the service and service aliases with the container:
Public function alias ($abstract, $alias) {$this- > aliases [$alias] = $this- > normalize ($abstract);}
The alias method is useful in the bind method described above, which registers the correspondence between the service alias and the service class in the $aliases attribute of the service container.
For example:
$this- > app- > alias ('\ Illuminate\ ServiceName', 'service_alias')
After binding the service, you can use the
$this- > app- > make ('service_alias')
Parse out the service object so that you don't have to write longer class names when make, which greatly improves the experience of using the make method.
Service parsing
Make: parses the service object from the service container, and this method takes the class name or interface name you want to parse as parameters
/ * Resolve the given type from the container. * * @ param string $abstract * @ param array $parameters * @ return mixed * / public function make ($abstract, array $parameters = []) {/ / getAlias method assumes that $abstract is a bound alias, finds the mapped real type name from $aliases / / if there is no mapping, $abstract is the real type name, and returns $abstract as is $abstract = $this- > getAlias ($this- > normalize ($abstract)) / / if the service is bound through instance (), parse the returned service if (isset ($this- > instances [$abstract]) {return $this- > instances [$abstract]) {return $this- > instances [$abstract];} / / get the $concrete (implementation of the interface) $concrete = $this- > getConcrete ($abstract); if ($this- > isBuildable ($concrete, $abstract)) {$object = $this- > build ($concrete, $parameters) } else {/ / if the API implements this binding method, you need to make again after obtaining the implementation through the interface to / / meet the conditions of isBuildable ($abstract = $concrete) $object = $this- > make ($concrete, $parameters);} foreach ($this- > getExtenders ($abstract) as $extender) {$object = $extender ($object, $this) } / / if the service is registered as singleton, put the built service object in $instances, / / avoid rebuilding if ($this- > isShared ($abstract)) {$this- > instances [$abstract] = $object;} $this- > fireResolvingCallbacks ($abstract, $object); $this- > resolved [$abstract] = true; return $object;} protected function getConcrete ($abstract) {if (! Is_null ($concrete = $this- > getContextualConcrete ($abstract)) {return $concrete;} / / if the class implementation is not registered to the service container before $abstract, the service container will think that $abstract itself is the class implementation of the interface if (! Isset ($this- > bindings [$abstract]) {return $abstract;} return $this- > bindings [$abstract] ['concrete'];} protected function isBuildable ($concrete, $abstract) {return $concrete = = $abstract | | $concrete instanceof Closure;}
By combing through the make method, we find that the function of the build method is to build the parsed service object. Let's take a look at the specific process of building the object. (the reflection of the PHP class is used to implement the dependency injection of the service.)
Public function build ($concrete, array $parameters = []) {/ / if it is a closure, execute the closure directly and return (corresponding to the closure binding) if ($concrete instanceof Closure) {return $concrete ($this, $parameters);} / use reflection ReflectionClass to reverse engineer the implementation class $reflector = new ReflectionClass ($concrete) / / if it cannot be instantiated, it should be an interface or abstract class, or the constructor is private's 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; / get constructor $constructor = $reflector- > getConstructor () / / if the constructor is empty, new returns if (is_null ($constructor)) {array_pop ($this- > buildStack) {array_pop ($this- > buildStack); return new $concrete;} / / gets the dependency (formal parameter) of the constructor, and returns an array of ReflectionParameter objects representing each parameter $dependencies = $constructor- > getParameters () $parameters = $this- > keyParametersByArgument ($dependencies, $parameters); / / dependency needed to build the constructor $instances = $this- > getDependencies ($dependencies, $parameters); array_pop ($this- > buildStack); return $reflector- > newInstanceArgs ($instances);} / / get dependency protected function getDependencies (array $parameters, array $primitives = []) {$dependencies = []; foreach ($parameters as $parameter) {$dependency = $parameter- > getClass () / / A dependent value is provided in $primitives (that is, the $parameters parameter of the build method). / / $parameter- > name returns the parameter name if (array_key_exists ($parameter- > name, $primitives)) {$dependencies [] = $primitives [$parameter- > name] } elseif (is_null ($dependency)) {/ / parameter ReflectionClass is null, indicating that it is a basic type, such as' int','string' $dependencies [] = $this- > resolveNonClass ($parameter);} else {/ / parameter is an object of a class, then use resolveClass to parse the object out $dependencies [] = $this- > resolveClass ($parameter) }} return $dependencies } / / parse out the dependent class object protected function resolveClass (ReflectionParameter $parameter) {try {/ / $parameter- > getClass ()-> name returns the class name (the type declared by the parameter in typehint) / / and then recursively continue the make (other dependencies are found in the make Then the make dependency will continue / / until all the dependencies have been resolved, build will not end) return $this- > make ($parameter- > getClass ()-> name) } catch (BindingResolutionException $e) {if ($parameter- > isOptional ()) {return $parameter- > getDefaultValue ();} throw $e;}}
The service container is the core of laravel, which solves the interdependence between objects through dependency injection, and defines the specific behavior by controlling anti-transfer externalities (Route, Eloquent these are external modules, they define the code of conduct themselves, and these classes are responsible for the service container from registration to instantiation to you).
For a class to be extracted by a container, it must first be registered with the container. Since laravel calls this container a service container, if we need a service, we have to register and bind the service to the container, so what provides the service and binds the service to the container is the ServiceProvider. Service providers are mainly divided into two parts, register (registration) and boot (boot, initialization)
At this point, the study of "what is the concept of laravel service container" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.