忍者ブログ

STEP UP BLOG

Home > ブログ > > [PR] Home > ブログ > php > PHPの参照渡しにハマる

PHPの参照渡しにハマる

ゲームに課金しすぎて依存症になるといった意味ではなくハマったので備忘録がてらブログに書こうと思います。
仕事柄PHPを書く機会が多く、というよりもほとんどPHPしか書いていないのですが、
そうなってくるとなんでもPHPで書きたくなってきます。
これシェルで書いたほうがいいのでは? という処理でも、
とりあえずPHPで出来るか考えてしまいます。
挙句の果てに、シェルコマンド便利だからPHPからシェル叩きましょうみたいな思考になっていき、本日の本題に入ってくるわけです。
PHPで外部プログラムを実行する手段としてはexec()やsystem()があります。
先日私が使ったのはexec()で、そのときにハマった箇所を再現出来そうな例を以下に示します。
<?php

exec('ls .', $output);

foreach ($output as $file) {
    exec('wc -m '.$file, $wc);
    echo ($wc[0]."\n");
}

やりたいこととしてはファイルの一覧を取ってきて、ファイル毎に文字数を出力するというものです。
exec('ls .', $output);

の第2引数に実行結果が配列で格納されます。
で、実行すると、、、
$ php wc.php 
8 a.txt
8 a.txt
8 a.txt
8 a.txt

なんだか同じファイルの文字数が出力されますね。。
少し変えて、
<?php

exec('ls .', $output);

foreach ($output as $file) {
    exec('wc -m '.$file, $wc);
    echo ($file.':'.$wc[0]."\n");
}

としてみると、
$ php wc.php 
a.txt:8 a.txt
b.txt:8 a.txt
c.txt:8 a.txt
wc.php:8 a.txt

wcはループでちゃんと実行されているっぽいけど、結果の出力がおかしい??
ここまできたらvar_dump()しちゃいましょう。
<?php

exec('ls .', $output);

foreach ($output as $file) {
    exec('wc -m '.$file, $wc);
    var_dump($wc);
}

えい!!
$ php wc.php 
array(1) {
  [0]=>
  string(7) "8 a.txt"
}
array(2) {
  [0]=>
  string(7) "8 a.txt"
  [1]=>
  string(8) "12 b.txt"
}
array(3) {
  [0]=>
  string(7) "8 a.txt"
  [1]=>
  string(8) "12 b.txt"
  [2]=>
  string(7) "4 c.txt"
}
array(4) {
  [0]=>
  string(7) "8 a.txt"
  [1]=>
  string(8) "12 b.txt"
  [2]=>
  string(7) "4 c.txt"
  [3]=>
  string(10) "192 wc.php"
}

配列に実行結果が追加されている。。
そうか。参照渡しだからこうなっているのか。。
というところで原点に立ち戻ってマニュアルを確認してみると、

http://php.net/manual/ja/function.exec.php
配列に既に何らかの要素が 含まれる場合は、exec() は配列の最後に追加されることに注意してください。関数が要素を追加することを望まないのなら、それが exec() に渡される前に、配列の unset() を呼び出してください。

パラメータの章でちゃんと注意がされていますね。。。
unset()しなさいという話。
というわけで最終的には以下のようなソースになって希望通りの動きとなりました。
<?php

exec('ls .', $output);

foreach ($output as $file) {
    unset($wc);
    exec('wc -m '.$file, $wc);
    echo ($wc[0]."\n");
}

$ php wc.php 
8 a.txt
12 b.txt
4 c.txt
190 wc.php

結論としては、
・まずはマニュアルをしっかり読みましょう。
・参照渡しはバグが入り込みやすいので、なるべく使わないにこしたことはないですよね。
PR

Comment0 Comment

Comment Form

  • お名前name
  • タイトルtitle
  • メールアドレスmail address
  • URLurl
  • コメントcomment
  • パスワードpassword

PAGE TOP