[解決済み] クラス変数であるクロージャを呼び出すには?
質問
class MyClass {
var $lambda;
function __construct() {
$this->lambda = function() {echo 'hello world';};
// no errors here, so I assume that this is legal
}
}
$myInstance = new MyClass();
$myInstance->lambda();
//Fatal error: Call to undefined method MyClass::lambda()
クラス変数に到達するための正しい文法は何でしょうか?
どのように解決するのですか?
PHPでは、メソッドとプロパティは別の名前空間にあり(同じ名前のメソッドとプロパティを持つことができます)、プロパティとメソッドのどちらにアクセスするかは、それを行うために使用する構文に依存します。
$expr->something()
はメソッド呼び出しなので、PHP は
something
をクラスのメソッド一覧から探します。
$expr->something
はプロパティの取得なので、PHP は
something
をクラスのプロパティの一覧から探します。
$myInstance->lambda();
はメソッド呼び出しとしてパースされるので、PHP はその名前のメソッドを探します。
lambda
という名前のメソッドを探しますが、そのようなメソッドはありません (そのため
未定義のメソッドへの呼び出し
エラーが発生します)。
というわけで、このような場合は フェッチプロパティ 構文を使ってラムダを取得し、それを呼び出します。
-
PHP 7.0 以降、これを行うには
($obj->lambda)()
:($obj->lambda)();
括弧は、PHP が
($obj->lambda)
として lambda という名前のプロパティを取得します。 . 次に()
はプロパティをフェッチした結果を呼び出します。 -
で行うこともできます。
->lambda->__invoke()
:$myInstance = new MyClass(); $myInstance->lambda->__invoke();
__invoke
は PHP のマジックメソッド . オブジェクトがこのメソッドを実装すると、呼び出すことができるようになります。$var()
構文で呼び出すことができます。匿名関数はClosure
を実装している__invoke
. -
またはローカル変数に代入します。
$lambda = $myInstance->lambda; $lambda();
-
またはcall_user_funcを使って呼び出します。
call_user_func($myInstance->lambda);
call_user_func
は、任意のcallable
を、無名関数を含めて呼び出すことができます。 -
あるいは、これがあなたのコードで一般的なパターンである場合、あなたのコードに
__call
メソッドを設定して、ラムダへの呼び出しを転送することもできます。class MyClass { private $lambda; public function __construct() { $this->lambda = function() { echo "Hello world!\n"; }; } public function __call($name, $args) { return call_user_func_array($this->$name, $args); } }
これでうまくいきました。
$myInstance = new MyClass(); $myInstance->lambda();
PHP 5.4以降では、traitの中でそれを行うこともできます。
trait LambdasAsMethods { public function __call($name, $args) { return call_user_func_array($this->$name, $args); } } class MyClass { use LambdasAsMethods; private $lambda; public function __construct() { $this->lambda = function() { echo "Hello World!\n"; }; } } $myInstance = new MyClass(); $myInstance->lambda();
関連
-
[解決済み】php, mysql - データベースへの接続数が多すぎるエラー
-
[解決済み】In_arrayが動作しない。
-
[解決済み] オートロードとは何ですか; spl_autoload、__autoload、spl_autoload_register はどのように使うのですか?
-
[解決済み] ループ内のJavaScriptクロージャ - シンプルな実用例
-
[解決済み] PHPでSQLインジェクションを防ぐにはどうしたらいいですか?
-
[解決済み] ある文字列が特定の単語を含んでいるかどうかを確認するにはどうすればよいですか?
-
[解決済み] YouTube APIからYouTubeビデオのサムネイルを取得する方法を教えてください。
-
[解決済み] C#がforeachで変数を再利用するのは理由があるのか?
-
[解決済み] クロージャ」と「ラムダ」の違いは何ですか?
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】接続の取得に失敗しました: php_network_getaddresses: getaddrinfo failed: 名前またはサービスが不明
-
[解決済み】DateTimeクラスのオブジェクトを文字列に変換できない
-
[解決済み】Xampp ローカルホスト/ダッシュボード
-
[解決済み】foreach()に与えられた引数が無効です。)
-
[解決済み】 $_SERVER['DOCUMENT_ROOT'] と $_SERVER['HTTP_HOST'] の違いについて]
-
[解決済み】PHPからPythonスクリプトを実行する
-
[解決済み】子テーマのCSSが親テーマをオーバーライドしない
-
[解決済み】警告:mysql_fetch_array()はパラメータ1がリソースであることを期待、ブール値は[重複]で与えられる]
-
[解決済み】Fatal error: mysqli_result 型のオブジェクトは使用できません [終了] 。
-
[解決済み] オートロードとは何ですか; spl_autoload、__autoload、spl_autoload_register はどのように使うのですか?