読者です 読者をやめる 読者になる 読者になる

m6uとFuelPHPとPostgreSQLとAndroid

FuelPHPまわりのメモ、初心者に産毛程度を生やす。

改題済:PHP 5.3系でvalidationのルールをclosure(無名関数)で拡張するときの注意【解決済】

 ハマったのでメモ。

ローカルでテストしてサーバーで動かない、PHPのバージョン違いの影響らしい

 ローカルのPHP 5.4.16なXAMPPで動作確認を取った一式を、サーバーのPHP 5.3.15に反映したら、「Using $this when not in object context」なんてエラーが発生しまして。
 なんでかなーと思ってネット検索してみたところ、「PHP5.3での無名関数内でのselfや$thisは解決できないから気をつけろ」っていう記事が見つかりまして。 これかなと。
 複数のアクションメソッド内で共通する処理(フォーム作成とか)をアクションメソッドの外に追い出そうとして、変数の引き回しに $this->xxxxxx を使った途端、このfatal errorですよ。
 サーバーのPHPバージョンを安易に引き上げられない都合上、5.3対応の書き方を模索しないといけないのですが、方法は如何に?

【追記】アクションメソッドって静的メソッドだったの?(はて?)

 PHPのクラスのこと、よくわかってなかったかもしれん
 「PHPでの動的・静的メソッド呼び出しの比較サンプル」という記事をよく読むと、ズバリ書いてありました。
 「静的メソッド(Stat())内で$this->アクセサを使う」 これのエラーメッセージと同じと判明。
 とくに静的メソッドだと宣言しているわけじゃないけど、静的メソッドとして扱われているのだとしたら、記述方法を変えればいいんだろうか。
 アクションメソッドの外で宣言している変数をstaticで宣言しなおして、参照するときは self::$xxxxxx を徹底して、ローカルでの動作は確認できた。
 サーバーにアップロードして試したところ、「Cannot access self:: when no class scope is active」っていうfatal errorを吐いてる。

【解決】teratailで質問して教えてもらいました

 「PHP - コントローラーの複数アクションメソッドで共通する処理を外出ししたらPHP 5.3でfatal error(38672)|teratail」という質問にて回答を得ました。 ありがとうございます。
 「$validation->add('dummy_xxxxxxxx', 'dummy_xxxxxxxx')->add_rule(array('xxxxxxxx_1' => function () use ($xxxxxxxx) {......}」みたいな書き方でclosure(無名関数)を書いて臨時にバリデーションルールを拡張している関数内でクラス内の変数を参照している箇所でfatal error出してました。
 結論的には、「self::$xxxxxx」と書いていた箇所を、「Controller_Xxxxx::$xxxxxx」にしただけでした。
 あまり、理由・理屈はわかってません。

【解決2】ちゃんとclosure(無名関数)にuseで親クラス(のインスタンス)を引き渡すのがしっくりきた
$self = $this;
$validation->add('dummy_xxxxxx', 'dummy_xxxxxx')->add_rule(array('xxxxxx_1' =>
  function () use ($self, $foo, $bar)
{
  ...
  $val = $self->xxxxxx;
  ...
}

 ってやることで、うまく引き継げました。