2

オープンソースのoauth-phpライブラリを見つけたコードを理解しようとしています。関連するコードスニペットは次のとおりです。

protected function sql_printf ( $args )
{
    $sql  = array_shift($args);
    if (count($args) == 1 && is_array($args[0]))
    {
        $args = $args[0];
    }
    $args = array_map(array($this, 'sql_escape_string'), $args);
    return vsprintf($sql, $args);
}

ここで、$ argsは、フォーマットされた印刷操作で使用することを目的とした変数を含む引数の配列です。array_mapのドキュメントを確認しました。

http://php.net/manual/en/function.array-map.php

ユーザーのコメントと、array_map()の呼び出しの最初のパラメーターが配列自体であるユースケースは見当たりませんでした。私が見たすべてのユースケースで、最初のパラメーターはNULLまたは(コールバック)関数のいずれかでした。コードが$args配列を受け取り、$ this-> sql_escape_string()によってサニタイズされた引数を使用して新しい配列を構築することは私にはかなり明白に思えます。

しかし、「array($ this、'sql_escape_string')」というステートメントは、単に「$ this-> sql_escape_string」を期待していたので、私をスローしますか、それとも有効な構文ではありませんか?もしそうなら、$ thisと'sql_escape_string'を配列でラップすると、array_map()が使用する有効なコールバック関数がどのように作成されますか?

-ロシュラー

4

3 に答える 3

3

実際にはsql_escape_string、クラス自体からのメソッドをコールバックとして渡します。これは、あいまいなメソッド呼び出しを明確にする方法です。例えば:

array_map('sql_escape_string', $args);

もちろん、のsql_escape_string()各値に適用されますが、次のようになり$argsます。

array_map(array($someClass, 'sql_escape_string'), $args);

sql_escape_string()メソッドfrom$someClassをの各値に適用し$argsます。

于 2011-04-20T00:59:01.397 に答える
3

最初のパラメータはコールバックです。文字列または配列のいずれかです。

単純に「$this->sql_escape_string」を期待していたので

それがたった1つのスカラー値であるとしたら。ただし、配列があり、そのエスケープ関数を配列の各項目に適用する必要があります$args。したがってforeach、その関数を実装して適用するか、。でワンライナーを使用する必要がありますarray_map

于 2011-04-20T00:59:50.277 に答える
1

しかし、「array($ this、'sql_escape_string')」というステートメントは、単に「$ this-> sql_escape_string」を期待していたので、私をスローしますか、それとも有効な構文ではありませんか?

それは有効ですが、あなたがそれが何を指していると思うかについては言及していません。無料の関数、定数、クラス名、変数を検討してください。それぞれが異なる環境(または必要に応じて「名前空間」)に存在しますが、 PHP名前空間と簡単に混同されます。変数のさまざまな環境は、「$」を印章として使用することで明示的になります。つまり、変数$fooと関数foo()、定数foo、およびクラスFooです。これは、定数と変数で大文字と小文字が区別される理由でもありますが、関数とクラス名では大文字と小文字が区別されません。環境が異なれば、名前解決ルールも異なります。

同様に、オブジェクトのメソッドとプロパティはさまざまな環境に存在します。結果として、$this->sql_escape_stringはメソッドではなくプロパティを参照します。問題を混乱させるために、そのプロパティには呼び出し可能オブジェクトが含まれている可能性がありますが、そのような呼び出し可能オブジェクトを直接呼び出すことはできませんでした。

class Foo {
    function frob() {return 23.0 / 42;}
}

$foo = new Foo;
$foo->frob = function () {return 0 / 0;};

$foo->frob(); # calls method, not closure function

$frob = $foo->frob;
$frob(); # oops: division by zero

定数や関数と同様に、プロパティとメソッドは引数リストの有無によって区別されます。

もしそうなら、$ thisと'sql_escape_string'を配列でラップすると、array_map()が使用する有効なコールバック関数がどのように作成されますか?

呼び出し可能な参照のためのPHPの構文は、文字列を超えています。

フリー関数(クラスまたはオブジェクトに関連付けられていない関数。「バインドされた関数」とは対照的)は、それらの名前で明確に参照できます。静的メソッドはクラスにバインドされていますが、クラス名が含まれている場合は文字列で参照できます(構文は「Class :: method」です)。ただし、メソッドは特定のオブジェクトにバインドする必要があり、PHPには文字列を使用してオブジェクトを参照する方法がないため、文字列にオブジェクトメソッドの十分な情報を含めることはできません。PHPの開発者が解決した解決策は、配列構文を使用することでした(質問のサンプルコードに示されているように)。また、静的メソッドの配列構文のサポートも含まれていました(array('Class', 'method'))。

呼び出し可能参照に加えて、呼び出し可能はクロージャにすることができます。これらは、オブジェクトメソッドを渡す別の方法を提供しますが、より冗長で複雑です。

$self = $this; # workaround: $this not accessible in closures before 5.4
$args = array_map(
    function ($value) use($self) {
        return $self->sql_escape_string($value);
    }, $args);

呼び出し可能な参照が機能する場合、クロージャはそれほど有用ではありませんが、全体的にはより強力です。

于 2013-08-04T22:34:07.277 に答える