私は最近、いくつかの最悪の PHP プラクティスに関するこのスレッドを読んでいました。2番目の回答では、 の使用に関するミニディスカッションがあり、extract()
すべてのハフが何であるか疑問に思っています。
$_GET
私は個人的にそれを使用して、またはなどの特定の配列を切り刻み、$_POST
後で変数をサニタイズします。
これは悪い習慣ですか?ここでのリスクは何ですか?の使用についてどう思いますextract()
か?
将来のメンテナ(または数週間後には自分自身)がどこから来ているのかわからない多くの変数につながる可能性があるという点で、それは悪い習慣にすぎないことがわかりました。このシナリオを考えてみましょう。
extract($someArray); // could be $_POST or anything
/* snip a dozen or more lines */
echo $someVariable;
どこ$someVariable
から来たの?誰がどのように言うことができますか?
変数が開始された配列内から変数にアクセスすることに問題は見られないので、それが価値があると私が考えるために使用するための良い事例を提示する必要があります。extract()
余分な文字を入力することに本当に関心がある場合は、次のようにしてください。
$a = $someLongNameOfTheVariableArrayIDidntWantToType;
$a['myVariable'];
ここでのセキュリティ面に関するコメントは、やや誇張されていると思います。EXTR_SKIP
この関数は、既存の変数を上書きしない( )、既存の変数のみを上書きする(ホワイトリストを作成できるようにする)(EXTR_IF_EXISTS
)、変数にプレフィックスを追加するなど、新しく作成された変数を実際にかなり適切に制御できる2番目のパラメーターを取ることができます。 (EXTR_PREFIX_ALL
)。
今すぐ来てください。人々はユーザーではなくツールを非難します。
unlink()
ファイルを削除できるので、それは反対のようなものです。extract()
他の機能と同様に、賢明かつ責任を持って使用してください。しかし、それ自体が悪いと主張しないでください。それは単に無知です。
リスクは次のとおりです。ユーザーからのデータを信頼しないでください。現在のシンボルテーブルに抽出すると、ユーザーが提供するものによって変数が上書きされる可能性があります。
<?php
$systemCall = 'ls -lh';
$i = 0;
extract($_GET);
system($systemCall);
do {
print_r($data[$i];
$i++;
} while ($i != 3);
?>
(無意味な例)
しかし今では、コードを推測または知っている悪意のあるユーザーが次のように呼び出します。
yourscript.php?i=10&systemCall=rm%20-rf
それ以外の
yourscript.php?data[]=a&data[]=b&data[]=c
これで、$systemCallと$iが上書きされ、スクリプトが最初にデータを削除してからハングします。
何も問題はありません。そうでなければ、それは実装されません。多くの (MVC) フレームワークは、ビューに変数を渡す (割り当てる) ときにそれを使用します。慎重に使用する必要があります。これらの配列を extract() に渡す前にサニタイズし、変数をオーバーライドしないようにしてください。この関数はさらにいくつかの引数も受け入れることを忘れないでください! 2 番目と 3 番目の引数を使用すると、衝突が発生した場合の動作を制御できます。プレフィックスをオーバーライド、スキップ、または追加できます。 http://www.php.net/extract
注意して使用しないと、一緒に作業している他の人を混乱させる可能性があります。
<?php
$array = array('huh' => 'var_dump', 'whatThe' => 'It\'s tricky!', 'iDontGetIt' => 'This Extract Function');
extract($array);
$huh($whatThe, $iDontGetIt);
?>
収量:
string(12) "It's tricky!"
string(21) "This Extract Function"
難読化に使用すると便利です。しかし、「その var はどこから来たのですか?」という質問を乗り越えることができません。私が遭遇する問題。
抽出物は悪用される可能性があるため、人々は抽出物について熱心に取り組んでいます。extract($_POST) のようなことをするのは、たとえ自分が何をしているのか分かっていても、良い考えではありません。ただし、変数をビュー テンプレートに公開するなどの作業を行う場合には、それが使用されます。基本的に、そうする正当な理由があると確信している場合にのみ使用し、 $_POST のようなクレイジーなものを渡すという考えが浮かんだ場合は、抽出型パラメーターの使用方法を理解してください。
多くの人がそれを使用することを推奨しない理由は、抽出$_GET
し、$_POST
(さらに$_REQUEST
)スーパーグローバルがそれらの配列内の各キーと同じ名前でグローバル名前空間に変数を登録するためだと思います。これは基本的にREGISTER_GLOBALS=1をエミュレートしています。
関数で抽出すると、変数はそのスコープでのみ使用できます。これはビューでよく使用されます。簡単な例:
//View.php
class View {
function render($filename = null) {
if ($filename !== null) {
$this->filename = $filename;
}
unset($filename);
extract($this->variables);
ob_start();
$this->returned = include($this->dir . $this->filename);
return ob_get_clean();
}
}
//test.php
$view = new View;
$view->filename = 'test.phtml';
$view->dir = './';
$view->variables = array('test' => 'tset');
echo $view->render('test.phtml');
var_dump($view->returned);
//test.phtml
<p><?php echo $test; ?></p>
いくつかの代替ディレクトリを使用して、ファイルが存在し、変数とメソッドが定義されているかどうかを確認します。これで、Zend_View をほぼ複製できました。
$this->outVariables = get_defined_vars();を追加することもできます。インクルードの後、特定のバリアベルでコードを実行し、古い php コードで使用するためにこれらの結果を取得します。
PHP のマニュアルを参考にしてください。
Background: php.iniextract($_REQUEST)
の設定と同じregister_globals = On
別のスレッドで誰かが指摘したように、配列に含まれるすべてのものではなく、指定した変数のみを抽出できるようにすることで、extract を使用するより安全な方法を次に示します。
これは、そこからどの変数が出てくるかを文書化するという二重の目的を果たします。そのため、変数を追跡することはそれほど難しくありません。
リスクはregister_globalsの場合と同じです。攻撃者がリクエストを改ざんするだけで、スクリプトに変数を設定できるようにします。
すべてのメソッドの使用は、アプリケーションの障害点になる可能性があるいくつかの条件につながる可能性があります。個人的には、extract() はユーザー入力 (予測不可能) やサニタイズされていないデータには使用すべきではないと感じています。
CodeIgniter のコア コードでさえ extract を使用しているため、データがサニタイズされて適切に処理されていれば、このメソッドを使用しても問題はありません。
EXTR_IF_EXISTS スイッチを使用して CodeIgniter モデルで抽出を使用し、変数の数を制限したところ、かなりうまく機能しました。