APIを利用する場合、XMLレスポンスとして返ってくるのは、多次元配列の構造になっていることがほとんどです。
simplexml_load_file()関数を使うと、XMLオブジェクトが多次元配列の構造で返ってきて、XML_Unserializerを使うと、まんま配列で受け取れる。
(私は、simplexml_load_file()関数のほうが好きですが)
で、ここのところAWS(アマゾンWebサービス)を利用したサイトをPHPで作っていたのですけど、foreach文を使うと、「Warning: Invalid argument supplied for foreach()」(警告:foreach文に無効な値が渡されました。)の警告文が頻繁に発生しました。
作成中のサイト ⇒ アマちぇっき(8割完成、動作確認まだ完全じゃないです)
原因は、XMLを処理後、出力のときにforeach文の中で、foreach文をもう一回使うことが多いため。
APIから返されるXMLの構造は、以下のような配列構造になっていることが多いです。(あるいは、二次元でなくもっと深い多次元配列の構造)
$array = array(
0 => array('a', 'b', 'c'),
1 => 'd',
2 => array('e', 'f'),
3 => '',
4 => array('x', 'y', 'z')
);
配列構造をよく確認せずに、孫の部分も配列だろうと予測して、この$arrayに対して・・・
foreach ($array as $item) {
foreach ($item as $value) {
echo $value . ', ';
}
echo '<br />';
}
と、2回foreachで単純に回してしまうと、上記の警告文が出てしまう。
a, b, c, Warning: Invalid argument supplied for foreach() in ・・・ e, f, Warning: Invalid argument supplied for foreach() in ・・・ x, y, z,
添え字が、1,3の要素は、値が配列ではないためです。
この警告文を避けるためには・・・
foreach ($array as $item) {
if (is_array($item)) {
foreach ($item as $value) {
echo $value . ', ';
}
} else {
echo $item;
}
echo '<br />';
}
と書いてやればよい。
$itemが配列かどうか確認した後に、foreachで回す。
そして、配列でない場合には、そのまま出力。
a, b, c, d e, f,x, y, z,
すると、今度は上記のように、予想通りにちゃんと表示されます。
$itemが配列要素の場合にのみ出力したければ・・・
foreach ($array as $item) {
if (!is_array($item)) {
continue;
}
foreach ($item as $value) {
echo $value . ', ';
}
echo '<br />';
}
と書けば、実行結果は・・・
a, b, c, e, f, x, y, z,
と、表示されます。
ちょっと調べたところ、「Warning: Invalid argument supplied for foreach()」の警告文が出ているサイト、かなりたくさんあります。
foreach文で処理するために渡す値は、必ず配列でないといけないらしい。
アマちぇっきってサイト、画像にマウスを重ねると拡大画像が出てくるのは面白いですねw思わず何回もマウス重ねたり外したりしてしまいましたw
ただ、キーボードのみで操作してる人は見れないですね^^;
あと、たいしたことじゃないんですが、
配列要素のみ出力する例は
foreach ($array as $item) {
if (is_array($item)) {
foreach ($item as $value) {
echo $value . ', ';
}
echo '<br />';
}
}
でもいいですよね^^
もっとも、ネストが深くなりそうな場合や、ifの中が異常に長くなる場合(※)、あえてcontinue使うことはありますけど。
※別関数にしてしまうのが正しいのでしょうけどw
アマちぇっき、見て頂けましたか。
ありがとうございます。
でも、オンマウスで写真が拡大するのって、私のオリジナルなアイデアではないですよ。
アマゾンのショッピングサイトでは、友人でもあります、Web2.0ラボを運営しているかん吉さんが有名です。
http://www.web2-labo.com/
あと、ビッグサイトでは、日産のカーラインアップページとか。
http://www.nissan.co.jp/CARLINEUP/
リンク先のプレビュー拡大表示のサービスとかもあります。
http://glance.heartrails.com/
https://account.snap.com/signup.php
苦労したのは、ポンッといきなり拡大表示させずに、だんだん拡大させるっていう部分の実装です。
javascriptのsetInterval()使うところで、つまずきました・・・orz
ま、ここがオリジナルと言えば、オリジナルな部分になりますけどね。
foreach文は、確かに木田さんの書いたほうが簡単でしたね。
実際のコーディングでは、私は関数化していますよ。
基本的にif-else分岐やループで、ネストが深くなるのが嫌いなので、foreachやforでは、continueとかbreakとか結構使っちゃってます。
いいもん><
俺には俺の道があるってもんさw
まぁ、自分で切り開いていこうって決めたから
PGに憧れて専門学校に入って
成りたい職業BEST3で
一個だけ書きました
みゅーじしゃんw
PHPだとGOTO文が無いのでネストが深い処理は面倒そうですね。
ちょい調べたら、
break 2;
みたいな数を把握して書かないといけないみたいな・・・
■TAKA SEAくん
そうだね、みんな自分で自分の道、切り開いていくしかないよね。
Mステ出演、目指してよ!
■ふかわくん
たしかに、CやPerlではgoto使えるのは便利だろうなぁ・・と感じることもある。
ただ、前読んだオライリー本に、gotoはスパゲッティになりやすいんで気を付けろって書いたあった。
でも、使い方ちゃんとしてれば便利だよね。
ちなみに、PHP6からgoto使えるようになるらしいよ。
breakは、PHPの場合・・・
foreach ($array as $item) {
foreach ($item as $value) {
・・・
break2;
とすれば、一つ目のforeach文を抜ける。
ので、breakにオプション引数つける場合は、ネストの深さを数えないといけない作りになってる。
ネスト深い場合は、絶対gotoあったほうが便利だよなぁ・・って書いてて思った。ww
■この記事のトラックバックURL:
http://www.mapee.jp/mpe334/mt-tb.cgi/133