This article mainly introduces the PHP container pimple running flow analysis, has a certain reference value, now share to everyone, the need for friends can refer to
Need to have the knowledge point
Closed Package
Closures and anonymous functions are introduced in the PHP5.3.0.
Closures are functions that encapsulate the surrounding state when created. Even if the environment in which the closure is located does not exist, the state of encapsulation in the closure still exists.
In
theory, closures and anonymous functions are different concepts. But PHP sees it as the same concept.
In fact, closures and anonymous functions are objects disguised as functions. They are instances of the closure class.
Closures, like strings and integers, are equivalent types.
To create a closure:
<?php$closure = function ($name) { return ' Hello '. $name;}; echo $closure (' NESFO ');//hello nesfovar_dump (Method_exists ($closure, ' __invoke '));//true
The
reason we can invoke a
$closure
variable is because the value of the variable is a closure, and the closure object implements the
__invoke()
magic method. As long as the variable name is followed
()
, PHP will find and invoke the
__invoke()
method.
PHP closures are often used as callbacks to functions.
array_map()
, the preg_replace_callback()
method will use the callback function, which is the best time to use closures!
As an example:
<?php$numbersplusone = Array_map (function ($number) { return $number + 1;}, [1, 2, 3]);p Rint_r ($numbersPlusOne);
Get results:
[2, 3, 4]
Before a closure occurs, you can only create a named function by itself, and then use the name to refer to that function. In doing so, the code executes slightly more slowly and isolates the implementation of the callback from the usage scenario.
<?phpfunction Incrementnum ($number) { return $number + 1;} $numbersPlusOne = Array_map (' Incrementnum ', [1, 2, 3]);p Rint_r ($numbersPlusOne);
Spl
Arrayaccess
Implementing the Arrayaccess interface allows an object to operate like an array. The Arrayaccess interface contains four methods that must be implemented:
Interface Arrayaccess { //check if an offset location exists public mixed offsetexists (mixed $offset ); Gets the value of an offset position public mixed offsetget (mixed $offset ); Sets the value of an offset position public mixed Offsetset (mixed $offset ); Resets the value of an offset position public mixed Offsetunset (mixed $offset );}
Splobjectstorage
The Splobjectstorage class implements such a data structure as the object-key mapping (map) or the collection of objects (if the data corresponding to the object being the key is omitted). An instance of this class is much like an array, but the objects it holds are unique. Another feature of this class is that you can delete the specified object directly from it, without having to traverse or search the entire collection.
::class
Grammar
Because ::class
the representation is a string. ::class
The advantage is that the IDE can rename a class directly, and then the IDE automatically handles the relevant reference.
Also, when PHP executes the relevant code, it does not load the relevant class first.
Similarly, code automation check inspect can also correctly identify class.
Brief analysis of pimple container flow
Pimpl is a relatively popular container in the PHP community. Code is not many, see Https://github.com/silexphp/P ....
Our applications can be developed on the basis of pimple:
Namespace Easywechat\foundation;use pimple\container;class Application extends container{/** * Service Providers. * * @var Array */protected $providers = [Serviceproviders\serverserviceprovider::class, Ser Viceproviders\userserviceprovider::class]; /** * Application constructor. * * @param array $config */Public function __construct ($config) {parent::__construct (); $this [' config '] = function () use ($config) {return new config ($config); }; if ($this [' config '] [' Debug ']) {error_reporting (E_all); } $this->registerproviders (); }/** * Add a provider. * * @param string $provider * * @return Application */Public Function AddProvider ($provider) { Array_push ($this->providers, $provider); return $this; }/** * Set providers. * * @param array $providers */Public function SetprovideRS (array $providers) {$this->providers = []; foreach ($providers as $provider) {$this->addprovider ($provider); }}/** * Return all providers. * * @return Array */Public function getproviders () {return $this->providers; }/** * Magic get access. * * @param string $id * * @return Mixed */Public Function __get ($id) {return $this->offs Etget ($id); }/** * Magic set access. * * @param string $id * @param mixed $value */Public Function __set ($id, $value) {$this->of Fsetset ($id, $value); }}
How to use our app:
$app = new Application ([]); $user = $app->user;
Then we can use $user
the method of the object. We found that this attribute is not actually available $this->user
, but can be used directly. This is mainly the effect of these two methods:
Public Function Offsetset ($id, $value) {}public function offsetget ($id) {}
Below we will explain what pimple did in executing these two lines of code. But before explaining this, let's look at some of the core concepts of the container.
Service Provider
A service provider is a bridge between a connection container and a specific function implementation class. The service provider needs to implement the interface ServiceProviderInterface
:
Namespace pimple;/** * Pimple Service Provider interface. * * @author Fabien potencier * @author Dominik zogg */interface serviceproviderinterface{ /** * Registers services on the given container. * * This method is should only being used to configure services and parameters. * It should not get services. * * @param Container $pimple A Container Instance * * Public function Register (Container $pimple);}
All service providers must implement an interface register
method.
There are 2 service providers in our app by default:
protected $providers = [ serviceproviders\serverserviceprovider::class, serviceproviders\ Userserviceprovider::class];
Take Userserviceprovider as an example, we look at its code implementation:
namespace Easywechat\foundation\serviceproviders;use easywechat\user\user;use Pimple\container;use Pimple\ serviceproviderinterface;/** * Class Userserviceprovider. */class Userserviceprovider implements serviceproviderinterface{ /** * Registers services on the given Container. * * This method is should only being used to configure services and parameters. * It should not get services. * * @param Container $pimple A Container Instance * * Public function Register (Container $pimple) { $pimple [' user '] = function ($pimple) { return new user ($pimple [' Access_token ']); }}
We see that the registration method of the service provider adds properties to the container user
, but returns a closure instead of an object. I'll explain this later.
Service Registration
We used $this->registerProviders();
to register all service providers in the application constructor:
Private Function Registerproviders () { foreach ($this->providers as $provider) { $this->register (new $ Provider ());} }
Looking closely, we found that the service provider was instantiated here and called the container pimple register
method:
Public Function Register (serviceproviderinterface $provider, array $values = Array ()) { $provider->register ($ this); foreach ($values as $key = + $value) { $this [$key] = $value; } return $this;}
And here is the method of invoking the service provider register
, which we mentioned in the previous section: the registration method adds a property to the container, user
but returns a closure instead of an object.
When we add properties to the container pimple user
, we call the offsetSet($id, $value)
method: give the container the Pimple property values
, assign the keys
value separately:
$this->values[$id] = $value; $this->keys[$id] = true;
Here, we haven't instantiated a class that really provides real-world functionality EasyWeChat\User\Usr
. However, the registration of the service provider has been completed.
When we run to here:
$user = $app->user;
offsetGet($id)
the real class is called and instantiated:
$raw = $this->values[$id]; $val = $this->values[$id] = $raw ($this); $this->raw[$id] = $raw; $this->frozen[$id ] = True;return $val;
$raw
Get a closure:
$pimple [' user '] = function ($pimple) { return new user ($pimple [' Access_token ']);};
$raw($this)
Returns the instantiated object user. This means that only the actual invocation will instantiate the specific class. Later, we can pass $this['user']
or $this->user
invoke the method in the user class.
Of course, there are a lot of features in pimple that we should go into in-depth study, here do not do too much explanation.
The above is the whole content of this article, I hope that everyone's learning has helped, more relevant content please pay attention to topic.alibabacloud.com!