web-dev-qa-db-ja.com

eval()されたコードの変数スコープの問題+含まれているPHPファイル

bercart条件付きアクションで、独自のPHPコードを「Execute custom PHP code」というアクションです。このPHPコードでは、2つの変数を使用できます: _$order_および_$account_。

それをテストするために、テキストエリアの最初にいくつかのコードを入れます:

_drupal_set_message('before including file....');
drupal_set_message('isset($account): <pre>'.var_export(isset($account), TRUE).'</pre>');
drupal_set_message('isset($order): <pre>'.var_export(isset($order), TRUE).'</pre>');
drupal_set_message('isset($order->products): <pre>'.var_export(isset($order->products), TRUE).'</pre>');
_

OK、以下を出力します:

_before including file....
isset($account):
true
isset($order):
true
isset($order->products):
true
_

それは正しいので、_$account_および_$order_変数を問題なく使用できます。しかし、コードを別のファイルに入れて、ここに含めたいと思います。そのため、前述の_$account_および_$order_変数をファイルで使用したいと思います。
しかし、ファイルをインクルードした後、ファイルの先頭に_global $account, $order;_と入力しても、これらの変数はファイルのスコープに存在しません!

たとえば、「test_module」というモジュールがあり、ファイルはモジュールのphpディレクトリにあり、その名前は「_testPurchase.inc_」です。次のコードをカスタムの「Execute custom PHP code」テキストエリアに挿入します:

_drupal_set_message('before including file....');
drupal_set_message('isset($account): <pre>'.var_export(isset($account), TRUE).'</pre>');
drupal_set_message('isset($order): <pre>'.var_export(isset($order), TRUE).'</pre>');
drupal_set_message('isset($order->products): <pre>'.var_export(isset($order->products), TRUE).'</pre>');

$module_name = 'test_module';
$filepath = 'php/testPurchase';
$file_extension = 'inc';

module_load_include($file_extension, $module_name, $filepath);
_

そして_testPurchase.inc_の内容:

_<?php

// checking the existence of the $account and $order variables in 'testPurchase.inc' file...
drupal_set_message('this is already in the included file....');
drupal_set_message('isset($account): <pre>'.var_export(isset($account), TRUE).'</pre>');
drupal_set_message('isset($order): <pre>'.var_export(isset($order), TRUE).'</pre>');
drupal_set_message('isset($order->products): <pre>'.var_export(isset($order->products), TRUE).'</pre>');
_

OK、ファイルのインクルードは正しいですが、結果は次のようになります:

_before including file....
isset($account):
true
isset($order):
true
isset($order->products):
true
this is already in the included file....
isset($account):
false
isset($order):
false
isset($order->products):
false
_

したがって、「testPurchase.inc」では、_$account_および_$order_変数は存在しません。
しかし、なぜ?スコープは同じであるべきではありませんか?

このコードが eval() であるという問題の原因はありますか?
この問題を回避するには、コードをファイルに保持しますが、カスタムモジュールを介して述語を定義する必要なく、上記の2つの変数を使用できます?
主にこれが発生する理由を知りたいと思っています。

追伸module_load_include()関数を「純粋に」使用して、require_once()関数を使用せずにすでに試しましたが、結果はまったく同じです。


[〜#〜] edit [〜#〜]前述のeval()は、私にはまったくわかりません!

これはPHPの動作方法とは異なると思います。そのため、独自のファイルでテストしました。いくつかの変数を定義してファイルを作成し、次に別のファイルを通常の方法で、その後、eval()を介してファイルをインクルードしました。どちらの場合も、インクルードされたファイル内の以前に定義された変数の存在と値を確認しました。
結果:これらのファイルをインクルードした後もスコープは同じでした-したがって、インクルードファイルで以前に定義された変数を問題なく使用できました!!

テストの結果をお見せしましょう!

変数をテストするための最初のファイルがここに来るので、さまざまな方法でさまざまなファイルを含めます。コードは非常に明確だと思います。

_test_vars_normally_and_eval.php_:

_<?php

    $variable_1 = 12345;
    $variable_2 = 'Test stuff';

    require_once('test_vars_require_normal.php');

    echo '<hr />';

    $test_eval_1 = '
        $eval_variable_1 = 12; 
        $eval_variable_2 = 49;
        echo "<h3><u>eval() - appending var. testing file as a string with file_get_contents():</u></h3>"; 
        ?>'.file_get_contents('test_vars_require_eval.php');

    eval( $test_eval_1 );

    $test_eval_2 = '
        $eval_variable_1 = 666;
        $eval_variable_2 = 999;
        echo "<h3><u>eval() - including var. testing file with require_once() in eval():</u></h3>";
        require_once("test_vars_require_eval.php");
        ';

    eval( $test_eval_2 );
_

_test_vars_require_normal.php_、require_once()で定期的にインクルードするためのファイル:

_<?php

    echo '<h3><u>testing variables after a regular require_once():</u></h3>';
    echo '<b>isset($variable_1):</b><pre>'.var_export( isset($variable_1), TRUE).'</pre>';
    if(isset($variable_1)){
        echo '<b>$variable_1:</b><pre>'.var_export( $variable_1, TRUE).'</pre>';
    }
    echo '<b>isset($variable_2):</b><pre>'.var_export( isset($variable_2), TRUE).'</pre>';
    if(isset($variable_2)){
        echo '<b>$variable_2:</b><pre>'.var_export( $variable_2, TRUE).'</pre>';
    }
_

_test_vars_require_eval.php_、eval()を介してインクルードされるファイル:

_<?php

    echo '<b>isset($eval_variable_1):</b><pre>', var_export(isset($eval_variable_1), TRUE), '</pre>';
    if(isset($eval_variable_1)){
        echo '<b>$eval_variable_1:</b><pre>', var_export($eval_variable_1, TRUE), '</pre>';
    }

    echo '<b>isset($eval_variable_2):</b><pre>', var_export(isset($eval_variable_2), TRUE), '</pre>';
    if(isset($eval_variable_2)){
        echo '<b>$eval_variable_2:</b><pre>', var_export($eval_variable_2, TRUE), '</pre>';
    }

    echo '<hr />';
_

そして最終出力IS THE [〜#〜] following [〜#〜]

通常のrequire_once()の後の変数のテスト:

isset($ variable_1):

_true
_

$ variable_1:

_12345
_

isset($ variable_2):

_true
_

$ variable_2:

_'Test stuff'
_

eval()-変数を追加します。 file_get_contents():を使用してファイルを文字列としてテストする

isset($ eval_variable_1):

_true
_

$ eval_variable_1:

_12
_

isset($ eval_variable_2):

_true
_

$ eval_variable_2:

_49
_

eval()-変数を含みます。 eval()でrequire_once()を使用してファイルをテストする:

isset($ eval_variable_1):

_true
_

$ eval_variable_1:

_666
_

isset($ eval_variable_2):

_true
_

$ eval_variable_2:

_999
_
1
Sk8erPeter

これはおそらくPHPよりもDrupalの質問です。

とにかく、ファイル自体は実行されるものではなく、代わりに変数を渡すことができる関数を使用する必要があります。

だからあなたの.incを変更する必要があります:

<?php
function test_purchase($account, $order) {
  // checking the existence of the $account and $order variables in'testPurchase.inc' file...
  drupal_set_message('this is already in the included file....');
  drupal_set_message('isset($account): <pre>'.var_export(isset($account), TRUE).'</pre>');
  drupal_set_message('isset($order): <pre>'.var_export(isset($order), TRUE).'</pre>');
  drupal_set_message('isset($order->products): <pre>'.var_export(isset($order->products), TRUE).'</pre>');
}

インクルードの後、あなたはできる

 test_purchase($account, $order);

これは、PHPでの一般的なアプローチです。ファイルをインクルードしてコードを実行する代わりに関数を使用する

2
googletorp