PHPには連想配列を変数に展開する関数extract()があって便利なんですが、WordPressではコーディング規約でエラーになります。
ようは使わないでね? と言ってる。
(個人的にはWordPressに限らず使うのを避けるべきだと思っている。)
なぜ WordPressではエラーにするのか見ていきます。
何が起きるのか分からないことを懸念するWordPress
WordPressでショートコードを作るとき、その内部処理をこのように書いているコードを今だに見ることが多いです。
function wpdocs_bartag_func( $atts ) {
extract( shortcode_atts(
array(
'foo' => 'no foo',
'bar' => 'default bar',
), $atts, 'bartag' ) );
return 'bartag: ' . esc_html( $foo ) . ' ' . esc_html( $bar );
}
add_shortcode( 'bartag', 'wpdocs_bartag_func' );
ただ extract() を使うと、WordPressコーディング規約ではこのようなエラーになる。
extract() usage is highly discouraged, due to the complexity and unintended issues it might cause.
(extract() は複雑で意図しない問題を引き起こす可能性があるため非常に推奨されません。)
コーディング規約のエラーメッセージ(筆者翻訳)
文言は強めに非推奨にしています。だから警告ではなくエラーなんですね?
WordPressでは何が複雑だと思ってるのかを書く前にextract() は何なのか見ていきましょう。
変数展開を1行でやってしまうextract()
extract() の使い方は百聞は一見にしかずなので、いきなりサンプルコードを見てみましょう。
<?php
$arr = [
'val1' => 'sample1',
'val2' => 'sample2',
'val3' => 'sample3',
];
extract($arr);
echo $val1 . PHP_EOL;
echo $val2 . PHP_EOL;
echo $val3 . PHP_EOL;
sample1
sample2
sample3
val1, val2, val3 の変数宣言、値入力をしていないのに、extract()を使えば連想配列から変数を展開して値まで入れてくれます。
extract() を使わない場合はこのように自力で変数を用意しないといけません。
<?php
$arr = [
'val1' => 'sample1',
'val2' => 'sample2',
'val3' => 'sample3',
];
$val1 = $arr['val1'];
$val2 = $arr['val2'];
$val3 = $arr['val3'];
連想配列の数が多ければ多いほど使い勝手の良い関数です。
『こんなに便利なものを使っちゃダメなの?』と思うでしょうが、その理由はいくらでも出てきます。
それをWordPressでは『複雑で意図しない問題を引き起こす可能性』と言ってるんですね?
extract() の問題点
extract()の問題点はパッと思いつくだけでも多く出てきます。
- URLクエリーなど、ユーザーが自由に要素名が指定できるデータの場合、何が起きるのか予想できない。(セキュリティに問題あり。)
- 連想配列を変更すると変数名まで変わって余計な修正が発生してしまう。
- クラスや関数の外のグローバルで使うのは絶対NG。プログラマが意図していないグローバル変数はセキュリティ的にもバグ発生の可能性でも致命的。
この関数はプログラムを書いた本人には楽で便利なものですが、よくよく考えて使わないと、あとのことを考えてない身勝手なものになります。
正直、気軽にextract()を使ったあとのコードを修正したくない。バグが起きる匂いがプンプンするから。
WordPressに限らず使うのを避けるべきでしょう。
ちなみに、PHPの公式ドキュメントでも分かりやすく警告しています。
ユーザーの入力、例えば $_GET や $_FILES のような、 信頼できないデータに extract() を使用しないでください。
PHP公式ドキュメント
PHP公式ドキュメント
唯一、問題ない使い方
使うのを避けましょうと言いましたが、絶対に使うべきでないとは思いません。
たとえば、連想配列の要素名が確実に決まっていれば、むしろ使ったほうが便利でスッキリとしたコードになります。
function test( args ) {
extract( array(
'val1' => args[0],
'val2' => args[1],
'val3' => args[2],
));
}
ただ、WordPressではコーディング規約違反ですけどね?