#必要な知識ポイント
クロージャ
クローズド パッケージと匿名関数はPHP5.3.0 で導入されました。
クロージャとは、
作成時に周囲の状態をカプセル化する関数を指します。クロージャが配置されている環境が存在しなくなっても、クロージャにカプセル化された状態は依然として存在します。
Closure クラスのインスタンスです。
クロージャの作成:
<?php $closure = function ($name) { return 'Hello ' . $name; }; echo $closure('nesfo');//Hello nesfo var_dump(method_exists($closure, '__invoke'));//true
$closure 変数を呼び出すことができる理由は、この変数の値がクロージャであるためです。クロージャー オブジェクトは、
__invoke() マジック メソッドを実装します。変数名の後に () がある限り、PHP は
__invoke() メソッドを見つけて呼び出します。
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('incrementNum', [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 つの特徴は、コレクション全体を走査したり検索したりせずに、指定したオブジェクトをクラスから直接削除できることです。
::classSyntax
::class は文字列を表すためです。
::class を使用する利点は、IDE で
class の名前を直接変更できることです。その後、IDE が関連する参照を自動的に処理します。
inspect もクラスを正しく識別できます。
Pimple コンテナー プロセスの簡単な分析
Pimple は、PHP コミュニティで人気のあるコンテナーです。コードの量はそれほど多くありません。詳細については、https://github.com/silexphp/Pimple/blob/master/src/Pimple/Container.php を参照してください。私たちのアプリケーションは 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['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); } }
$app = new Application([]); $user = $app->user;
public function offsetSet($id, $value){} public function offsetGet($id){}
サービス プロバイダー
サービス プロバイダーは、コンテナーと特定の関数実装クラスの間のブリッジです。サービス プロバイダーはインターフェイスを実装する必要があります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); }
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['user'] = function ($pimple) { return new User($pimple['access_token']); }; } }
user をコンテナに追加しますが、返されるのはオブジェクトではなくクロージャです。これについては後ほど説明します。
サービス登録
Application すべてのサービスのコンストラクターで
$this->registerProviders(); を使用します。プロバイダーが登録されています:
private function registerProviders() { foreach ($this->providers as $provider) { $this->register(new $provider()); } }
public function register(ServiceProviderInterface $provider, array $values = array()) { $provider->register($this); foreach ($values as $key => $value) { $this[$key] = $value; } return $this; }
メソッドは前のセクションで説明したものです。登録メソッドは属性 user
をコンテナに追加しますが、オブジェクトではなくクロージャを返します。 属性 user をコンテナ Pimple に追加するとき、
メソッドを呼び出します。属性 values をコンテナ
Pimple
、キーにはそれぞれ値が割り当てられます: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">$this->values[$id] = $value;
$this->keys[$id] = true;</pre><div class="contentsignin">ログイン後にコピー</div></div>
この時点まで、実際に提供するクラス
をインスタンス化していません。実際の機能。ただし、サービスプロバイダーの登録は完了しています。 ここで実行すると:
$user = $app->user;
は offsetGet($id) を呼び出し、実際のクラスをインスタンス化します:
$raw = $this->values[$id]; $val = $this->values[$id] = $raw($this); $this->raw[$id] = $raw; $this->frozen[$id] = true; return $val;
$raw はクロージャを取得します:
$pimple['user'] = function ($pimple) { return new User($pimple['access_token']); };
$raw($this)
返回的是实例化的对象User
。也就是说只有实际调用才会去实例化具体的类。后面我们就可以通过$this['user']
或者$this->user
调用User
类里的方法了。
当然,Pimple里还有很多特性值得我们去深入研究,这里不做过多讲解。
更多相关php知识,请访问php教程!
以上がPimple 実行プロセス (PHP コンテナー) の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。