Heim >Backend-Entwicklung >PHP-Tutorial >Kurze Analyse des laufenden Pimple-Prozesses (PHP-Container)
Erforderliche Wissenspunkte
Abschluss
Abschlusspakete und anonym Funktionen wurden in PHP5.3.0
eingeführt.
Abschluss bezieht sich auf:
Eine Funktion, die beim Erstellen den umgebenden Zustand kapselt. Auch wenn die Umgebung, in der sich der Verschluss befindet, nicht mehr existiert, ist der im Verschluss eingekapselte Zustand weiterhin vorhanden.
Theoretisch sind Schließungen und anonyme Funktionen unterschiedliche Konzepte. Aber PHP behandelt es als dasselbe Konzept.
Tatsächlich sind Abschlüsse und anonyme Funktionen als Funktionen getarnte Objekte. Sie sind Instanzen der Klasse Closure
.
Abschlüsse sind wie Strings und Ganzzahlen erstklassige Werttypen.
Abschluss erstellen:
<?php $closure = function ($name) { return 'Hello ' . $name; }; echo $closure('nesfo');//Hello nesfo var_dump(method_exists($closure, '__invoke'));//true
Der Grund, warum wir die Variable $closure
aufrufen können, liegt darin, dass der Wert dieser Variablen ein Abschluss ist und das Abschlussobjekt Magische Methode. Solange nach dem Variablennamen () steht, findet PHP die Methode __invoke()
und ruft sie auf. __invoke()
, array_map()
Methoden verwenden alle Callback-Funktionen. Dies ist der beste Zeitpunkt, um Abschlüsse zu verwenden! preg_replace_callback()
<?php $numbersPlusOne = array_map(function ($number) { return $number + 1; }, [1, 2, 3]); print_r($numbersPlusOne);erhält das Ergebnis:
[2, 3, 4]Vor Schließungen konnten Sie benannte Funktionen nur einzeln erstellen und diese Funktion dann namentlich referenzieren. Dadurch wird die Codeausführung etwas langsamer und die Implementierung des Rückrufs wird vom Nutzungsszenario isoliert.
<?php function incrementNum ($number) { return $number + 1; } $numbersPlusOne = array_map('incrementNum', [1, 2, 3]); print_r($numbersPlusOne);
SPL
ArrayAccess
implementiert die-Schnittstelle, die es Objekten ermöglicht, wie Arrays zu funktionieren. Die ArrayAccess-Schnittstelle enthält vier Methoden, die implementiert werden müssen: ArrayAccess
interface ArrayAccess { //检查一个偏移位置是否存在 public mixed offsetExists ( mixed $offset ); //获取一个偏移位置的值 public mixed offsetGet( mixed $offset ); //设置一个偏移位置的值 public mixed offsetSet ( mixed $offset ); //复位一个偏移位置的值 public mixed offsetUnset ( mixed $offset ); }
SplObjectStorage
Die Klasse implementiert eine Map mit Objekten als Schlüssel oder eine Sammlung von Objekten ( If Sie ignorieren die dem Objekt entsprechenden Daten als Schlüssel) dieser Datenstruktur. Eine Instanz dieser Klasse ähnelt einem Array, die darin gespeicherten Objekte sind jedoch alle eindeutig. Ein weiteres Merkmal dieser Klasse besteht darin, dass Sie das angegebene Objekt direkt daraus löschen können, ohne die gesamte Sammlung durchlaufen oder durchsuchen zu müssen. SplObjectStorage
Syntax ::class
eine Zeichenfolge darstellt. Der Vorteil der Verwendung von ::class
besteht darin, dass Sie es in der IDE direkt in ::class
umbenennen können und die IDE dann automatisch die relevanten Referenzen verarbeitet. class
Klassen korrekt identifizieren. inspect
Eine kurze Analyse des Pimple-Container-Prozesses
Pimpl ist ein beliebter Container in der PHP-Community. Es gibt nicht viel Code, siehehttps://github.com/silexphp/Pimple/blob/master/src/Pimple/Container.php für Details.Unsere Anwendung kann basierend auf Pimple entwickelt werden:
namespace EasyWeChat\Foundation; use Pimple\Container; class Application extends Container { /** * Service Providers. * * @var array */ protected $providers = [ ServiceProviders\ServerServiceProvider::class, ServiceProviders\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->offsetGet($id); } /** * Magic set access. * * @param string $id * @param mixed $value */ public function __set($id, $value) { $this->offsetSet($id, $value); } }So verwenden Sie unsere Anwendung:
$app = new Application([]); $user = $app->user;Danach können wir die Methode des $user-Objekts verwenden . Wir haben festgestellt, dass es kein Attribut $this->user gibt, es aber direkt verwendet werden kann. Hauptsächlich die Rolle dieser beiden Methoden:
public function offsetSet($id, $value){} public function offsetGet($id){}Im Folgenden erklären wir, was Pimple tut, wenn es diese beiden Codezeilen ausführt. Aber bevor wir dies erklären, werfen wir einen Blick auf einige Kernkonzepte von Containern.
Dienstanbieter
Dienstanbieter ist die Brücke zwischen dem Container und der spezifischen Funktionsimplementierungsklasse. Dienstanbieter müssen die Schnittstelle implementieren:ServiceProviderInterface
namespace Pimple; /** * Pimple service provider interface. * * @author Fabien Potencier * @author Dominik Zogg */ interface ServiceProviderInterface { /** * Registers services on the given container. * * This method should only be used to configure services and parameters. * It should not get services. * * @param Container $pimple A container instance */ public function register(Container $pimple); }Alle Dienstanbieter müssen die Schnittstellenregistermethode implementieren. In unserer Anwendung gibt es standardmäßig zwei Dienstanbieter:
protected $providers = [ ServiceProviders\ServerServiceProvider::class, ServiceProviders\UserServiceProvider::class ];Am Beispiel von
schauen wir uns die Code-Implementierung an: UserServiceProvider
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 should only be 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']); }; } }Wir sehen, dass The Die Registrierungsmethode des Dienstanbieters fügt dem Container Attribute
hinzu, aber was zurückgegeben wird, ist kein Objekt, sondern ein Abschluss. Ich werde das später erklären. user
Dienstregistrierung
Wir verwenden im Konstruktor in Application
, um alle Dienstanbieter zu registrieren: $this->registerProviders();
private function registerProviders() { foreach ($this->providers as $provider) { $this->register(new $provider()); } }Sorgfältig hinschauen, finden wir dass der Dienstanbieter hier instanziiert wird und die Registermethode des Containers Pimple heißt:
public function register(ServiceProviderInterface $provider, array $values = array()) { $provider->register($this); foreach ($values as $key => $value) { $this[$key] = $value; } return $this; }Und die
-Methode des Dienstanbieters wird hier aufgerufen, was wir im vorherigen Abschnitt erwähnt haben. Angekommen: Die Registrierungsmethode fügt dem Container Attribute register
hinzu, gibt jedoch kein Objekt, sondern einen Abschluss zurück. user
aufgerufen: Weisen Sie den Attributen offsetSet($id, $value)
und Schlüsseln des Containers Pimple
jeweils Werte zu: values
$this->values[$id] = $value; $this->keys[$id] = true;Hier haben wir die Klasse
, die tatsächlich die eigentliche Funktionalität bereitstellt, noch nicht instanziiert. Die Registrierung des Dienstleisters ist jedoch abgeschlossen. EasyWeChatUserUsr
$user = $app->user;ruft offsetGet($id) auf und instanziiert die echte Klasse:
$raw = $this->values[$id]; $val = $this->values[$id] = $raw($this); $this->raw[$id] = $raw; $this->frozen[$id] = true; return $val;$raw erhält den Abschluss:
$pimple['user'] = function ($pimple) { return new User($pimple['access_token']); };
$raw($this)
返回的是实例化的对象User
。也就是说只有实际调用才会去实例化具体的类。后面我们就可以通过$this['user']
或者$this->user
调用User
类里的方法了。
当然,Pimple里还有很多特性值得我们去深入研究,这里不做过多讲解。
更多相关php知识,请访问php教程!
Das obige ist der detaillierte Inhalt vonKurze Analyse des laufenden Pimple-Prozesses (PHP-Container). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!