Closure を使用して PHP で匿名関数を作成する方法の概要

青灯夜游
リリース: 2023-04-09 11:48:01
転載
1857 人が閲覧しました

Closure を使用して PHP で匿名関数を作成する方法の概要

クロージャ クラス

匿名関数を表すために使用されるクラス。

匿名関数 (PHP 5.3 で導入) は、このタイプのオブジェクトを生成します。以前は、このクラスは実装の詳細とみなされていましたが、現在はこのクラスに依存して何かを行うことができます。 PHP 5.4 以降、このクラスには、作成後の匿名関数をより詳細に制御できるメソッドが付属しています。

このクラスはインスタンス化できません。このクラスには 2 つの主要なメソッドがあり、どちらもクロージャをコピーするために使用されます。1 つは静的メソッド、もう 1 つは動的メソッドです。これらの 2 つの理解しにくいメソッドについて詳しく説明します。下に。

Closure::bind

public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )

参数说明:
closure
需要绑定的匿名函数。

newthis
需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包。

newscope
想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 类作用域用来决定在闭包中 $this 对象的 
私有、保护方法 的可见性。 The class scope to which associate the closure is to be associated, or 'static' to keep the 
current one. If an object is given, the type of the object will be used instead. This determines the visibility of 
protected and private methods of the bound object.
ログイン後にコピー

パラメータの説明:

  • クロージャは匿名でバインドする必要があります関数。

  • newこれには、匿名関数にバインドされたオブジェクト、または非バインド クロージャを作成するには NULL が必要です。

  • newscope はクロージャのクラス スコープにバインドされる必要があります。または、「静的」は変更がないことを意味します。オブジェクトが渡された場合は、オブジェクトの型名が使用されます。クラス スコープは、クロージャ内の $this オブジェクトのプライベートな保護されたメソッドの可視性を決定するために使用されます。

クロージャを関連付けるクラス スコープ、または

現在のものを保持する 'static' オブジェクトが指定された場合、代わりにオブジェクトのタイプが使用されます。これにより、バインドされたオブジェクトの

protected メソッドとプライベート メソッドの可視性が決定されます。

上記はメソッドの定義です。

最初のパラメータはクロージャ関数なので分かりやすいですが、

2 番目のパラメータは分かりにくいです。コピーするクロージャに $this が含まれている場合、thisオブジェクトは、この $this を表します。クロージャ関数でのこのオブジェクトへの変更は、属性の変更など、呼び出し完了後も一貫性が保たれます。

3 番目のパラメータはそれほど簡単ではありませんデフォルトのパラメータでは、object $newthis の属性関数にアクセスするために $this-> を呼び出すと、制限があります。 public 属性を持つ関数にのみアクセスできます。protected/private 属性にアクセスしたい場合は、クラス内と同様に、対応するクラス名/クラス インスタンスに設定する必要があります。 、そのクラスの protected/private 属性関数にアクセスします。

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$test = new T();

$func = Closure::bind(function(){
    $this->who();
    $this->name();
    $this->show();
}, $test);

$func();
ログイン後にコピー

上記のコードはエラーを報告します致命的エラー: キャッチされないエラー: コンテキスト 'Closure から保護されたメソッド T::who() を呼び出します###。 bind の 3 番目のパラメータを t::class または new T() に追加すると、それぞれの結果が正常に出力されます。

我是T里面的保护函数:who
我是T里面的公共函数:name
我是T里面的私有函数:show
ログイン後にコピー

もちろん、クロージャはパラメータを渡すこともできます

$test = new StdClass();
var_dump($test);

$func = Closure::bind(function($obj){
    $obj->name = "燕睿涛";
}, null);

$func($test);
var_dump($test);
ログイン後にコピー

上記のプログラムは匿名関数と同じであり、どのオブジェクトにも依存しません。上記のプログラムは出力します:

object(stdClass)#1 (0) {
}
object(stdClass)#1 (1) {
  ["name"]=>
  string(9) "燕睿涛"
}
ログイン後にコピー

説明が必要な特別な例もあります

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$func = Closure::bind(function ($obj) {
    $obj->show();
}, null);

$test = new T();

$func($test);
ログイン後にコピー

上記の状況では何が出力されますか? はい、プライベート属性にアクセスできないことを示すエラーが報告されます

show . このとき、3 番目のパラメータを追加します パラメータは 1 つだけで十分です。3 番目のパラメータが $this のスコープに影響を与えるだけでなく、 がパラメータのスコープにも影響を与える可能性があることがわかります。

Closure::bindTo

bindTo には bind と同様の関数があります。ここでは単にもう 1 つ どちらの形式でも 現在のクロージャ オブジェクトをコピーし、指定された $this オブジェクトとクラス スコープをバインドします。 、最初のパラメータは bind より小さい、最後の 2 つは同じです。もちろん、
bindTo は静的メソッドではなく、存在するという別の違いがあります。プロパティメソッドのクロージャーのためだけです。

<?php
class T {
    private function show()
    {
        echo "我是T里面的私有函数:show\n";
    }

    protected  function who()
    {
        echo "我是T里面的保护函数:who\n";
    }

    public function name()
    {
        echo "我是T里面的公共函数:name\n";
    }
}

$func = function () {
    $this->show();
    $this->who();
    $this->name();
};

$funcNew = $func->bindTo(new T(), T::class);

$funcNew();
ログイン後にコピー

上記の関数の出力は、

bind

我是T里面的私有函数:show
我是T里面的保护函数:who
我是T里面的公共函数:name
ログイン後にコピー

a と似ています。トリック

この関数は、composer によって生成された自動読み込みソース コードを調べているときに見つかりました。これは、composer で特別な方法で使用されます。以下は、次のコードの一部のインターセプトです。 combos

// 文件autoload_real.php
call_user_func(\Composer\Autoload\ComposerStaticInit898ad46cb49e20577400c63254121bac::getInitializer($loader));

// 文件autoload_static.php
public static function getInitializer(ClassLoader $loader)
{
    return \Closure::bind(function () use ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$classMap;

    }, null, ClassLoader::class);
}
ログイン後にコピー

上記のコードはかなり奇妙です。

call_user_func では、間違ったパラメータが渡されているのが第一印象です。実際にはそうではありません。ここで関数が呼び出されます。この関数は Closure オブジェクトを返します。 これは匿名関数であり、渡される最後のパラメータは依然として
callable 型です。返されたクロージャをもう一度見てください。その中で use が使用されています。これはクロージャと外部変数を接続するブリッジです。 なぜここで通常のパラメータを渡すことができるかというと、php5ではオブジェクトの仮パラメータと実パラメータが同じオブジェクトを指しており、関数内でオブジェクトを変更するとオブジェクトの外にも反映されるからです。

つまり、上記のようにしても問題ありません。別の形式もあります。

call_user_func(\Composer\Autoload\ComposerStaticInit898ad46cb49e20577400c63254121bac::getInitializer(), $loader);

public static function getInitializer()
{
    return \Closure::bind(function ($loader) {
        $loader->prefixLengthsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixLengthsPsr4;
        $loader->prefixDirsPsr4 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixDirsPsr4;
        $loader->prefixesPsr0 = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$prefixesPsr0;
        $loader->classMap = ComposerStaticInit25885cdf386fdaafc0bce14bb5a7d06e::$classMap;

    }, null, ClassLoader::class);
}
ログイン後にコピー

概要

私はまだやっていません。ブログを長く続けていると、イライラして落ち着かないこともあれば、書きたいことが見つからないこともあります。それでも落ち着いて、すべてをうまくやり、物事が起こっても動揺せず、広い心を保ち、すべてを冷静に処理する必要があります。

関連チュートリアルの推奨事項: 「PHP チュートリアル

以上がClosure を使用して PHP で匿名関数を作成する方法の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:cnblogs.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート