PHPはあれらの事を包みます

4068 ワード

匿名関数
匿名関数は、閉包関数とも呼ばれ、はっきり言えば「名前のない関数」であり、一般的な関数構造と同様に、関数名が少なく、最後にセミコロン;を付ける必要がある.
注:理論的には閉パッケージと匿名関数は異なる概念ですが、PHPは同じ概念と見なしています.
$func = function()
{
    echo 'Hello World' . PHP_EOL;
};
$func();

匿名関数と一般関数の区別は次のとおりです.
  • 匿名関数は変数の値としても使用できます.
  • 匿名関数は、親役割ドメインから変数を継承することができ、この親役割ドメインは、閉パケットを定義する関数(必ずしも呼び出される関数ではない)である.
  • $message = 'hello';
    $example = function () use ($message) {
        return $message;
    };
    $message = 'world';
    echo $example();
    
      :hello
    

    注意:useのキーワードを使用して変数を渡す必要があります.具体的には、公式ドキュメントを参照してください.
    クローズドクラス
    閉パッケージ関数を定義します.これは、閉パッケージクラス(Closure)オブジェクトをインスタンス化することです.
    $func = function()
    {
        echo 'hello world' . PHP_EOL;
    };
    var_dump($func);
    
      :
    object(Closure)#1 (0) {
    }
    

    クラスの概要:
    Closure {
         __construct ( void )
         public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
         public Closure bindTo ( object $newthis [, mixed $newscope = 'static' ] )
    }
    

    以上の方法に加えて、閉パケットは、関数を呼び出すようにオブジェクトを呼び出そうとすると、__invoke()メソッドが自動的に呼び出される__invoke()マジックメソッドを実現する.
    bindToメソッド
    次に、bindToメソッドを見てみましょう.このメソッドにより、閉パケットの内部状態を他のオブジェクトにバインドすることができます.ここでbindToメソッドの2番目のパラメータは特に重要であり、その役割は、パケットをバインドしているオブジェクトが属するPHPクラスを指定することであり、パケットを閉じることで、パケットをバインドしているオブジェクトの中で保護され、プライベートなメンバー変数にアクセスすることができる.
    PHPフレームワークは、ルーティングURLを匿名コールバック関数にマッピングするためにbindToメソッドを使用することが多く、フレームワークは匿名コールバック関数をアプリケーションオブジェクトにバインドし、匿名関数では$thisキーワードを使用して重要なアプリケーションオブジェクトを参照することができます.
    class App {
        protected $routes = [];
        protected $responseStatus = '200 OK';
        protected $responseContentType = 'text/html';
        protected $responseBody = 'Hello World';
    
        public function addRoute($path, $callback) {
            $this->routes[$path] = $callback->bindTo($this, __CLASS__);
        }
    
        public function dispatch($path) {
            foreach ($this->routes as $routePath => $callback) {
                if( $routePath === $path) {
                    $callback();
                }
            }
            header('HTTP/1.1 ' . $this->responseStatus);
            header('Content-Type: ' . $this->responseContentType);
            header('Content-Length: ' . mb_strlen($this->responseBody));
            echo $this->responseBody;
        }
    
    }
    

    ここでは、addRouteメソッドに焦点を当てる必要があります.このメソッドのパラメータは、それぞれ1つのルーティングパスと1つのルーティングコールバックであり、dispatchメソッドのパラメータは、現在のHTTP要求のパスであり、一致するルーティングコールバックを呼び出すことになります.9行目がポイントで、ルーティングコールバックを現在のAppインスタンスにバインドします.これにより、コールバック関数でAppインスタンスのステータスを処理できます.
    $app = new App();
    $app->addRoute(‘/user’, function(){
        $this->responseContentType = ‘application/json;charset=utf8’;
        $this->responseBody = '    ';
    });
    $app->dispatch('/user');
    

    IoC容器
    匿名関数は、親役割ドメインから変数を継承できますが、この親役割ドメインは、閉パッケージを定義する関数です(必ずしも呼び出す関数ではありません).
    この特性を利用して、簡単な制御反転IoC容器を実現することができます.
    class Container
    {
        protected static $bindings;
     
        public static function bind($abstract, Closure $concrete)
        {
            static::$bindings[$abstract] = $concrete;
        }
     
        public static function make($abstract)
        {
            return call_user_func(static::$bindings[$abstract]);
        }
    }
     
    class talk
    {
        public function greet($target)
        {
            echo 'Hello ' . $target->getName();
        }
    }
    
    class A
    {
        public function getName()
        {
            return 'World';
        }
    }
     
    //     talk    
    $talk = new talk();
     
    //  A      ,   foo
    Container::bind('foo', function() {
        return new A;
    });
     
    //         
    $talk->greet(Container::make('foo')); // Hello World
    

    上記の例では、makeの方法でインスタンスを取得した場合にのみ、インスタンスが作成され、コンテナを実現することができる.Laravelフレームワークの下部にも、イベントトリガなどのより高度な特性を達成するために、閉パケットおよびbindTo方法が多く使用されている.