KANTENNA.COM

Solarized

HOME > WEBプログラム覚書 > PHP4 func_get_args()とforeachと参照

PHP4 func_get_args()とforeachと参照

まだまだPHP4は現役ですね。 久しぶりにPHP4でコード書いてたら肝心なところがコピー扱いでハマりました。

テストコード

PHP
  1.  <?php
  2.  class Man
  3.  {
  4.   var $name;
  5.   var $comment;
  6.  
  7.   function Man($name, $comment)
  8.   {
  9.   $this->name = $name;
  10.   $this->comment = $comment;
  11.   }
  12.  
  13.   function view()
  14.   {
  15.   printf("<h5>「%s」 - %s -</h5>", $this->comment, $this->name);
  16.   }
  17.  }
  18.  
  19.  class Mens
  20.  {
  21.   var $mens = array();
  22.  
  23.   function Mens()
  24.   {
  25.   foreach (func_get_args() as $man) {
  26.   $this->mens[] =& $man;
  27.   }
  28.   }
  29.  
  30.   function view()
  31.   {
  32.   foreach ($this->mens as $man) {
  33.   $man->view();
  34.   }
  35.   }
  36.  }
  37.  
  38.  $man_1 = new Man("ハリ美jyun", "俺はもう既に本物のヒョウなのかもしれない");
  39.  $man_2 = new Man("JMC パンサー", " 3秒だ。野郎を倒すのも女をオトすのもな");
  40.  $man_3 = new Man("サイバー田中", "俺の行き先?あの太陽にでも聞いてくれ");
  41.  
  42.  $mens = new Mens($man_1, $man_2, $man_3);
  43.  $mens->view();
  44.  
  45.  var_dump($man_1 === $mens->mens[0]);
  46.  var_dump($man_2 === $mens->mens[1]);
  47.  var_dump($man_3 === $mens->mens[2]);
  48.  ?>

実行結果

「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
bool(false) bool(false) bool(true)

なんじゃいこりゃ!?

func_get_args()では参照渡しができない

上記ページに書かれているようにfunc_get_arg()は参照に対応していないので array()でまとめて渡すようにします。

PHP
  1.  <?php
  2.  class Man
  3.  {
  4.   var $name;
  5.   var $comment;
  6.  
  7.   function Man($name, $comment)
  8.   {
  9.   $this->name = $name;
  10.   $this->comment = $comment;
  11.   }
  12.  
  13.   function view()
  14.   {
  15.   printf("<h5>「%s」 - %s -</h5>", $this->comment, $this->name);
  16.   }
  17.  }
  18.  
  19.  class Mens
  20.  {
  21.   var $mens = array();
  22.  
  23.   function Mens(&$mens)
  24.   {
  25.   foreach ($mens as $man) {
  26.   $this->mens[] =& $man;
  27.   }
  28.   }
  29.  
  30.   function view()
  31.   {
  32.   foreach ($this->mens as $man) {
  33.   $man->view();
  34.   }
  35.   }
  36.  }
  37.  
  38.  $man_1 = new Man("ハリ美jyun", "俺はもう既に本物のヒョウなのかもしれない");
  39.  $man_2 = new Man("JMC パンサー", " 3秒だ。野郎を倒すのも女をオトすのもな");
  40.  $man_3 = new Man("サイバー田中", "俺の行き先?あの太陽にでも聞いてくれ");
  41.  
  42.  $mens = new Mens($mens = array(&$man_1, &$man_2, &$man_3));
  43.  $mens->view();
  44.  
  45.  var_dump($man_1 === $mens->mens[0]);
  46.  var_dump($man_2 === $mens->mens[1]);
  47.  var_dump($man_3 === $mens->mens[2]);
  48.  ?>
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
bool(false) bool(false) bool(true)

変化なし。というかそもそもなんで全部最後のオブジェクトになってるの?? なんかそっちが気になってきました。

foreach は参照ではなくコピー

上記ページでdisられてるようにforeachはコピーとなります。 残念ながらforで対応するしかないようです。

PHP
  1.  <?php
  2.  class Man
  3.  {
  4.   var $name;
  5.   var $comment;
  6.  
  7.   function Man($name, $comment)
  8.   {
  9.   $this->name = $name;
  10.   $this->comment = $comment;
  11.   }
  12.  
  13.   function view()
  14.   {
  15.   printf("<h5>「%s」 - %s -</h5>", $this->comment, $this->name);
  16.   }
  17.  }
  18.  
  19.  class Mens
  20.  {
  21.   var $mens = array();
  22.  
  23.   function Mens(&$mens)
  24.   {
  25.   for ($i=0; $i<count($mens); $i++) {
  26.   $this->mens[] =& $mens[$i];
  27.   }
  28.   }
  29.  
  30.   function view()
  31.   {
  32.   for ($i=0; $i<count($this->mens); $i++) {
  33.   $this->mens[$i]->view();
  34.   }
  35.   }
  36.  }
  37.  
  38.  $man_1 = new Man("ハリ美jyun", "俺はもう既に本物のヒョウなのかもしれない");
  39.  $man_2 = new Man("JMC パンサー", " 3秒だ。野郎を倒すのも女をオトすのもな");
  40.  $man_3 = new Man("サイバー田中", "俺の行き先?あの太陽にでも聞いてくれ");
  41.  
  42.  $mens = new Mens($mens = array(&$man_1, &$man_2, &$man_3));
  43.  $mens->view();
  44.  
  45.  var_dump($man_1 === $mens->mens[0]);
  46.  var_dump($man_2 === $mens->mens[1]);
  47.  var_dump($man_3 === $mens->mens[2]);
  48.  ?>
実行結果
「俺はもう既に本物のヒョウなのかもしれない」 - ハリ美jyun -
「 3秒だ。野郎を倒すのも女をオトすのもな」 - JMC パンサー -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
bool(true) bool(true) bool(true)

とりあえず期待通りの出力になりました。 ほんとに参照になってるか確認してみます。

上記コードに下記を追加

PHP
  1.  <?php
  2.  $man_1->name = "TEST";
  3.  var_dump($mens->mens[0]->name);
  4.  ?>
実行結果
string(4) "TEST"

ちゃんと参照となっているようです。

PHP4 におけるオブジェクトの比較

最初の例から === が不穏なtrue返してたんで調べてみたら PHP4ではオブジェクトの比較は == も === も差がないとのこと。

PHP4では、とてもシンプルな作法でオブジェクトを比較できます。すなわち、 二つのオブジェクトは同じ属性と同じ値を持ち、 同じクラスのインスタンス である場合には等しいのです。二つのオブジェクトを比較演算子 (===)で比較した場合でも同様のルールとなります。

PHP: におけるオブジェクトの比較 - Manual

mens配列の要素をコピーにしてみます。

PHP
  1.  <?php
  2.  class Man
  3.  {
  4.   var $name;
  5.   var $comment;
  6.  
  7.   function Man($name, $comment)
  8.   {
  9.   $this->name = $name;
  10.   $this->comment = $comment;
  11.   }
  12.  
  13.   function view()
  14.   {
  15.   printf("<h5>「%s」 - %s -</h5>", $this->comment, $this->name);
  16.   }
  17.  }
  18.  
  19.  class Mens
  20.  {
  21.   var $mens = array();
  22.  
  23.   function Mens(&$mens)
  24.   {
  25.   for ($i=0; $i<count($mens); $i++) {
  26.   $this->mens[] =& $mens[$i];
  27.   }
  28.   }
  29.  
  30.   function view()
  31.   {
  32.   for ($i=0; $i<count($this->mens); $i++) {
  33.   $this->mens[$i]->view();
  34.   }
  35.   }
  36.  }
  37.  
  38.  $man_1 = new Man("ハリ美jyun", "俺はもう既に本物のヒョウなのかもしれない");
  39.  $man_2 = new Man("JMC パンサー", " 3秒だ。野郎を倒すのも女をオトすのもな");
  40.  $man_3 = new Man("サイバー田中", "俺の行き先?あの太陽にでも聞いてくれ");
  41.  
  42.  // arrayの要素をコピーにしてみる。
  43.  $mens = new Mens($mens = array($man_1, $man_2, $man_3));
  44.  $mens->view();
  45.  
  46.  var_dump($man_1 === $mens->mens[0]);
  47.  var_dump($man_2 === $mens->mens[1]);
  48.  var_dump($man_3 === $mens->mens[2]);
  49.  
  50.  $man_1->name = "TEST";
  51.  var_dump($mens->mens[0]->name);
  52.  
  53.  var_dump($man_1 === $mens->mens[0]);
  54.  ?>
「俺はもう既に本物のヒョウなのかもしれない」 - ハリ美jyun -
「 3秒だ。野郎を倒すのも女をオトすのもな」 - JMC パンサー -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
bool(true)
bool(true)
bool(true)
string(13) "ハリ美jyun"
bool(false)

確かにコピーなのにtrueとなってますね・・・

うーんPHP4で同じオブジェクトか調べるにはどうしたらいいんでしょうか?

PHP5では改善されてます。

上記の2点はPHP5では改善されてます。最初のコードの =& を = にすれば問題なく動きます。やったね。

PHP
  1.  <?php
  2.  class Man
  3.  {
  4.   var $name;
  5.   var $comment;
  6.  
  7.   function Man($name, $comment)
  8.   {
  9.   $this->name = $name;
  10.   $this->comment = $comment;
  11.   }
  12.  
  13.   function view()
  14.   {
  15.   printf("<h5>「%s」 - %s -</h5>", $this->comment, $this->name);
  16.   }
  17.  }
  18.  
  19.  class Mens
  20.  {
  21.   var $mens = array();
  22.  
  23.   function Mens()
  24.   {
  25.   foreach (func_get_args() as $man) {
  26.   $this->mens[] = $man;
  27.   }
  28.   }
  29.  
  30.   function view()
  31.   {
  32.   foreach ($this->mens as $man) {
  33.   $man->view();
  34.  
  35.   }
  36.   }
  37.  }
  38.  
  39.  
  40.  $man_1 = new Man("ハリ美jyun", "俺はもう既に本物のヒョウなのかもしれない");
  41.  $man_2 = new Man("JMC パンサー", " 3秒だ。野郎を倒すのも女をオトすのもな");
  42.  $man_3 = new Man("サイバー田中", "俺の行き先?あの太陽にでも聞いてくれ");
  43.  
  44.  $mens = new Mens($man_1, $man_2, $man_3);
  45.  $mens->view();
  46.  
  47.  var_dump($man_1 === $mens->mens[0]);
  48.  var_dump($man_2 === $mens->mens[1]);
  49.  var_dump($man_3 === $mens->mens[2]);
  50.  
  51.  $man_1->name = "TEST";
  52.  var_dump($mens->mens[0]->name);
  53.  
  54.  var_dump($man_1 === $mens->mens[0]);
  55.  ?>
実行結果
「俺はもう既に本物のヒョウなのかもしれない」 - ハリ美jyun -
「 3秒だ。野郎を倒すのも女をオトすのもな」 - JMC パンサー -
「俺の行き先?あの太陽にでも聞いてくれ」 - サイバー田中 -
bool(true) bool(true) bool(true) string(4) "TEST" bool(true)

トラックバック(0)

コメント

コメントする
Name
Email Address
URL
TIME LINE
2012
02.10

[雑記]縦横がランダムな要素を隙間なく並べるのは無理なのか。

サイトマップ作ったんだけど、やりたかったことが出来なかった。

2012
02.08

[Ubuntu11.10]Winows XPユーザーがUbuntuを使ってみて

Windows XPとUbuntuのデュアルブート環境にしてみておもったこと。

2012
02.03

[jQuery]closest()とparents()

今から16年前Netscapeブラウザのソースコードの公開方法の会議の中で、初めてオープンソースという言葉が使われた今日、 みなさんいかがお過ごしでしょうか。

今回の投稿はそれとは関係のないjQueryのparents()とclosest()が 似てたので何が違うのか試した時のメモです。

2012
02.01

[jQuery Mobile]初期化イベントメモ

jQuery Mobileは読み込まれてから

mobileinit -> pagebeforecreate -> pagecreate -> pageinit

の順番でイベントが発生する。

2012
02.01

[WordPress]管理画面のフッタのフィルタとアクション。

時間も時間なので、あまり使用頻度の高くない微妙なネタを。

会員制サイトなどで不特定多数の人にログインさせる場合、フッタのバージョン情報は隠しておきたかったり、 こじゃれたメッセージを表示したいときとか使うアクションとフィルタ。

2012
01.28

[WordPress] ブログの情報を取得する方法とノーキャッシュ疑惑

ブログのget_bloginfo()で取れないデータが必要な場合に使うもの。

2012
01.26

[jQuery Mobile]ダイアログ

jQuery Mobileにおけるダイアログの扱いはウインドウではなくページ。 なので通常のページと同様に扱える。ダイアログウインドウを出す。じゃなくダイアログページに遷移する。的な。

2012
01.25

[Ubuntu11.10]Ubuntuのインストール後の設定

インストール完了後の環境構築。PC起動時いちいちBIOSからブートドライブ選んで ブートするのかと思ってたら起動時にOS選択画面が出てくる。

すばらしいですね。

2012
01.24