Heim  >  Artikel  >  Backend-Entwicklung  >  Analyse des laufenden Prozesses des PHP-Containers Pimple

Analyse des laufenden Prozesses des PHP-Containers Pimple

不言
不言Original
2018-07-06 13:45:173553Durchsuche

Dieser Artikel stellt hauptsächlich die Analyse des laufenden Prozesses des PHP-Containers Pimple vor, der einen gewissen Referenzwert hat. Jetzt kann ich ihn mit allen teilen, die ihn brauchen.

Wissenswertes Punkte

Abschlüsse

Abschlüsse und anonyme Funktionen wurden in PHP5.3.0 eingeführt.

Ein 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 Abschlüsse 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 Closure-Klasse.

Abschlüsse sind wie Strings und Ganzzahlen erstklassige Werttypen.

Abschluss erstellen:

<?php
$closure = function ($name) {
    return &#39;Hello &#39; . $name;
};
echo $closure(&#39;nesfo&#39;);//Hello nesfo
var_dump(method_exists($closure, &#39;__invoke&#39;));//true
Der Grund, warum wir die Variable $closure aufrufen können, liegt darin, dass der Wert dieser Variablen ein Abschluss ist und das Abschlussobjekt die magische Methode __invoke() implementiert. Solange nach dem Variablennamen ein () steht, findet PHP die Methode __invoke() und ruft sie auf.

Normalerweise werden PHP-Abschlüsse als Rückrufe von Funktionen verwendet.

array_map(), preg_replace_callback() Methoden verwenden alle Rückruffunktionen. Dies ist der beste Zeitpunkt, um Abschlüsse zu verwenden!

Zum Beispiel:

<?php
$numbersPlusOne = array_map(function ($number) {
    return $number + 1;
}, [1, 2, 3]);
print_r($numbersPlusOne);

Ruft das Ergebnis ab:

[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(&#39;incrementNum&#39;, [1, 2, 3]);
print_r($numbersPlusOne);

SPL

ArrayAccess

implementiert die ArrayAccess-Schnittstelle, die es Objekten ermöglicht, wie Arrays zu funktionieren. Die ArrayAccess-Schnittstelle enthält vier Methoden, die implementiert werden müssen:

interface ArrayAccess {
    //检查一个偏移位置是否存在 
    public mixed offsetExists ( mixed $offset  );
    
    //获取一个偏移位置的值 
    public mixed offsetGet( mixed $offset  );
    
    //设置一个偏移位置的值 
    public mixed offsetSet ( mixed $offset  );
    
    //复位一个偏移位置的值 
    public mixed offsetUnset  ( mixed $offset  );
}

SplObjectStorage

Die SplObjectStorage-Klasse implementiert eine Map mit Objekten als Schlüssel oder eine Sammlung von Objekten (wenn das Objekt als Schlüssel ignoriert wird). ) diese 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.

::class Syntax

Weil ::class eine Zeichenfolge darstellt. Der Vorteil der Verwendung von ::class besteht darin, dass Sie eine Klasse direkt in der IDE umbenennen können und die IDE dann automatisch die zugehörigen Referenzen verarbeitet.
Wenn PHP den relevanten Code ausführt, wird gleichzeitig nicht zuerst die entsprechende Klasse geladen.

In ähnlicher Weise kann die automatisierte Code-Inspektion auch Klassen korrekt identifizieren.

Eine kurze Analyse des Pimple-Container-Prozesses

Pimpl ist ein beliebter Container in der PHP-Community. Es gibt nicht viel Code, siehe https://github.com/silexphp/P... 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[&#39;config&#39;] = function () use ($config) {
            return new Config($config);
        };

        if ($this[&#39;config&#39;][&#39;debug&#39;]) {
            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 Methoden des $user-Objekts verwenden. Wir haben festgestellt, dass es kein $this->user-Attribut 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 Schnittstellen-ServiceProviderInterface implementieren:

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 Schnittstellen-register-Methoden implementieren.

In unserer Anwendung gibt es standardmäßig zwei Dienstanbieter:

protected $providers = [
    ServiceProviders\ServerServiceProvider::class,
    ServiceProviders\UserServiceProvider::class
];

Am Beispiel von UserServiceProvider schauen wir uns die Code-Implementierung an:

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[&#39;user&#39;] = function ($pimple) {
            return new User($pimple[&#39;access_token&#39;]);
        };
    }
}

Wir sehen, dass dieser Dienst Folgendes bietet Die Registrierungsmethode des Benutzers fügt dem Container Attribute user hinzu, aber was zurückgegeben wird, ist kein Objekt, sondern ein Abschluss. Ich werde das später erklären.

Dienstregistrierung

Wir verwenden $this->registerProviders();, um alle Dienstanbieter im Konstruktor der Anwendung zu registrieren:

private function registerProviders()
{
    foreach ($this->providers as $provider) {
        $this->register(new $provider());
    }
}

Bei genauerem Hinsehen stellen wir fest, dass es hier einen instanziierten Dienstanbieter gibt , und rief die register-Methode des Containers Pimple auf:

public function register(ServiceProviderInterface $provider, array $values = array())
{
    $provider->register($this);

    foreach ($values as $key => $value) {
        $this[$key] = $value;
    }

    return $this;
}

Und hier wurde die register-Methode des Dienstanbieters aufgerufen, was wir im vorherigen Abschnitt erwähnt haben: Die Registrierungsmethode gibt den Container fügt das Attribut user hinzu, gibt aber kein Objekt, sondern einen Abschluss zurück.

Wenn wir Attribute user zum Container Pimple hinzufügen, wird die Methode offsetSet($id, $value) aufgerufen: Weisen Sie den Attributen values und keys des Containers Pimple jeweils Werte zu:

$this->values[$id] = $value;
$this->keys[$id] = true;

Gehen Sie hierher, wir haben nicht die Klasse EasyWeChatUserUsr instanziiert, die tatsächlich die eigentliche Funktionalität bereitstellt. Die Registrierung des Dienstleisters ist jedoch abgeschlossen.

Wenn wir hier ausführen:

$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[&#39;user&#39;] = function ($pimple) {
    return new User($pimple[&#39;access_token&#39;]);
};

$raw($this) gibt das instanziierte Objekt User zurück. Das heißt, nur der tatsächliche Aufruf instanziiert die spezifische Klasse. Später können wir Methoden in der User-Klasse über $this['user'] oder $this->user aufrufen.

Natürlich gibt es in Pimple viele Funktionen, die eine eingehende Untersuchung wert sind, daher werden wir sie hier nicht zu ausführlich erläutern.

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich ist. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website.

Verwandte Empfehlungen:

Wie WordPress die Funktion wp_head() verwendet

Geltungsbereich, global, statisch von PHP-Variablen Warten für Schlüsselwörter

Das obige ist der detaillierte Inhalt vonAnalyse des laufenden Prozesses des PHP-Containers Pimple. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn