PHPコンテナPimpleの実行プロセスの解析

不言
リリース: 2023-04-02 16:42:02
オリジナル
3550 人が閲覧しました

この記事では主にPHPコンテナ「Pimple」の実行プロセスの解析を紹介していますが、一定の参考値があるので皆さんに共有します。困っている友人は参考にしてください。

知識が必要です

クロージャー

クロージャーと匿名関数は PHP5.3.0 で導入されました。

クロージャは、作成時に周囲の状態をカプセル化する関数を指します。クロージャが配置されている環境が存在しなくなっても、クロージャにカプセル化された状態は依然として存在します。

理論的には、クロージャと匿名関数は異なる概念です。しかし、PHP ではこれを同じ概念として扱います。
実際には、クロージャと匿名関数は関数に見せかけたオブジェクトです。これらは Closure クラスのインスタンスです。

クロージャは、文字列や整数と同様、第一級の値型です。

クロージャの作成:

<?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
ログイン後にコピー
$closure 変数を呼び出すことができる理由は、この変数の値がクロージャであり、クロージャ オブジェクトが実装しているためです__invoke()マジックメソッド。変数名の後に () がある限り、PHP は __invoke() メソッドを見つけて呼び出します。

通常、PHP クロージャーは関数のコールバックとして使用されます。

array_map()preg_replace_callback() メソッドはすべてコールバック関数を使用します。クロージャを使用するのに最適な時期です。

例:

<?php
$numbersPlusOne = array_map(function ($number) {
    return $number + 1;
}, [1, 2, 3]);
print_r($numbersPlusOne);
ログイン後にコピー

結果の取得:

[2, 3, 4]
ログイン後にコピー

クロージャが登場する前は、名前付き関数を個別に作成し、その関数を名前で参照することしかできませんでした。これを行うと、コードの実行が若干遅くなり、コールバックの実装が使用シナリオから分離されます。

<?php
function incrementNum ($number) {
    return $number + 1;
}

$numbersPlusOne = array_map(&#39;incrementNum&#39;, [1, 2, 3]);
print_r($numbersPlusOne);
ログイン後にコピー

SPL

ArrayAccess

ArrayAccess インターフェイスを実装すると、オブジェクトが配列のように動作できるようになります。 ArrayAccess インターフェイスには、実装する必要がある 4 つのメソッドが含まれています。

interface ArrayAccess {
    //检查一个偏移位置是否存在 
    public mixed offsetExists ( mixed $offset  );
    
    //获取一个偏移位置的值 
    public mixed offsetGet( mixed $offset  );
    
    //设置一个偏移位置的值 
    public mixed offsetSet ( mixed $offset  );
    
    //复位一个偏移位置的值 
    public mixed offsetUnset  ( mixed $offset  );
}
ログイン後にコピー

SplObjectStorage

SplObjectStorage クラスは、オブジェクトをキーとして使用するマップ (マップ)、またはオブジェクトのコレクション (対応するオブジェクトを無視した場合) を実装します。キーデータへ)このデータ構造。このクラスのインスタンスは配列によく似ていますが、格納されるオブジェクトはすべて一意です。このクラスのもう 1 つの特徴は、コレクション全体を走査したり検索したりせずに、指定したオブジェクトをクラスから直接削除できることです。

::class構文

::class は文字列を表すためです。 ::class を使用する利点は、IDE でクラスの名前を直接変更でき、IDE が関連する参照を自動的に処理することです。
同時に、PHP が関連コードを実行するときに、最初に関連クラスをロードしません。

同様に、自動コード検査でもクラスを正しく識別できます。

Pimple コンテナー プロセスの簡単な分析

Pimple は、PHP コミュニティで人気のあるコンテナーです。コードはそれほど多くありません。詳細については、https://github.com/silexphp/P... を参照してください。

私たちのアプリケーションは Pimple に基づいて開発できます:

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);
    }
}
ログイン後にコピー

アプリケーションの使用方法:

$app = new Application([]);
$user = $app->user;
ログイン後にコピー

その後、$user# のメソッドを使用できます。 ## 物体 。 $this->user 属性はありませんが、直接使用できることがわかりました。主にこれら 2 つのメソッドの役割:

public function offsetSet($id, $value){}
public function offsetGet($id){}
ログイン後にコピー

以下では、これら 2 行のコードを実行するときに Pimple が行う動作について説明します。これを説明する前に、コンテナーの中心的な概念をいくつか見てみましょう。

サービス プロバイダー

サービス プロバイダーは、コンテナーと特定の関数実装クラスを接続するブリッジです。サービス プロバイダーはインターフェイス

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);
}
ログイン後にコピー

を実装する必要があります。すべてのサービス プロバイダーはインターフェイス

register メソッドを実装する必要があります。

アプリケーションにはデフォルトで 2 つのサービス プロバイダーがあります:

protected $providers = [
    ServiceProviders\ServerServiceProvider::class,
    ServiceProviders\UserServiceProvider::class
];
ログイン後にコピー

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[&#39;user&#39;] = function ($pimple) {
            return new User($pimple[&#39;access_token&#39;]);
        };
    }
}
ログイン後にコピー

このサービスが提供するものであることがわかります。ユーザーの登録メソッドは属性

user をコンテナに追加しますが、返されるのはオブジェクトではなくクロージャです。これについては後ほど説明します。

サービス登録

Application のコンストラクターで

$this->registerProviders(); を使用して、すべてのサービス プロバイダーを登録します。注意して見てみると、ここでサービス プロバイダーがインスタンス化されており、コンテナ Pimple の register

メソッドが呼び出されていることがわかります。

private function registerProviders()
{
    foreach ($this->providers as $provider) {
        $this->register(new $provider());
    }
}
ログイン後にコピー
そして、ここでサービス プロバイダーの register が # と呼ばれています。 ## メソッドは前のセクションで説明したものです。登録メソッドは属性

user

をコンテナに追加しますが、オブジェクトではなくクロージャを返します。 属性 user をコンテナ Pimple に追加すると、

offsetSet($id, $value)

メソッドが呼び出されます。コンテナ Pimple keys の属性がそれぞれ割り当てられます:

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

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

    return $this;
}
ログイン後にコピー
この時点まで、クラス EasyWeChat\User\Usr をインスタンス化していません。実際に実際の機能を提供します。ただし、サービスプロバイダーの登録は完了しています。

ここで実行すると:

$this->values[$id] = $value;
$this->keys[$id] = true;
ログイン後にコピー
offsetGet($id)

を呼び出し、実際のクラスをインスタンス化します:

$user = $app->user;
ログイン後にコピー

$raw はクロージャを取得します。

$raw = $this->values[$id];
$val = $this->values[$id] = $raw($this);
$this->raw[$id] = $raw;

$this->frozen[$id] = true;

return $val;
ログイン後にコピー

$raw($this) はインスタンス化されたオブジェクト User を返します。つまり、実際の呼び出しのみが特定のクラスをインスタンス化します。後で、$this['user']

または

$this->user を通じて User クラスのメソッドを呼び出すことができます。 もちろん、Pimple には徹底的に研究する価値のある機能がたくさんあるので、ここではあまり説明しません。

上記がこの記事の全内容です。皆様の学習に役立つことを願っています。その他の関連コンテンツについては、PHP 中国語 Web サイトに注目してください。

関連する推奨事項:

ワードプレスで wp_head() 関数を使用する方法

PHP 変数のスコープ、グローバル、静的キーワードを待ちます

以上がPHPコンテナPimpleの実行プロセスの解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!