- 締切済み
phpでオブジェクト化に挑戦中です。配列がうまく扱えません。
このようなサンプルプログラムを作ってみました どうやら配列がまずいようなのですが、どうすればよいでしょうか。 <?php class TEST2{ var $b1; } class TEST{ var $a1=TEST2; function printout(){ $this->$a1[0]->b1='123 '; $this->$a1[1]->b1='abc '; $this->$a1[2]->b1='DEF '; } } $c = new TEST; $c->printout(); echo $c->$a1[0]->b1; echo $c->$a1[1]->b1; echo $c->$a1[2]->b1; ?> ちなみに出力結果は DEF DEF DEF となりました。 疑問1.なぜ全部同じ結果になるのか 疑問2.配列だと echo $c->$a1[2]->b1; のように、$a1と、$マークがないと動かない。$を取ると強制終了される。 お願いします。へんてこな質問ですみません。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
function TEST(){ $this->a1=array(); $this->a1= new TEST2(); } これではいけません。なぜなら、$this->a1に対して最初に配列変数として利用しようとしているのに 次の行でインスタンス変数として利用しようとしている為です。 (1行目は完全に無視されますね) ですから、$this->a1[0]->b1='123 ';で値をセットしようとすると、 「この変数は配列ではありませんぜ」ってエラーが出ます。 クラス内にある変数配列に対して最大添字を外部で 変化させたいというのなら、 今の形では行えませんね。 <?php class TEST2{ var $b1; } class TEST{ var $a1; function TEST(){ $this->a1=array(); } function NewInstance($i){ $this->a1[$i]= new TEST2(); } function printout($i, $value){ $this->a1[$i]->b1=$value; } } $c = new TEST(); $c->NewInstance(0); $c->printout(0, "123 "); $c->NewInstance(1); $c->printout(1, "abc "); $c->NewInstance(2); $c->printout(2, "DEF "); echo $c->a1[0]->b1; echo $c->a1[1]->b1; echo $c->a1[2]->b1; ?> インスタンスの生成と値のセットを別々に行うなら こんな感じでしょうか。 そうではなくて、強制的に最大添字でインスタンスを生成し、値をセットしたいのなら、 <?php class TEST2{ var $b1; } class TEST{ var $a1; function TEST(){ $this->a1=array(); } function printout($value){ $i = Count($this->a1); $this->a1[$i]= new TEST2(); $this->a1[$i]->b1=$value; } } $c = new TEST(); $c->printout("123 "); $c->printout("abc "); $c->printout("DEF "); echo $c->a1[0]->b1; echo $c->a1[1]->b1; echo $c->a1[2]->b1; ?> こんな感じに。 値のセットをクラス内だけで完結したいのなら、外部で行っている 呼び出し処理をクラス内で関数化し、 外部からは一度その関数を呼ぶとか。 <?php class TEST2{ var $b1; } class TEST{ var $a1; function TEST(){ $this->a1=array(); } function printout($value){ $i = Count($this->a1); $this->a1[$i]= new TEST2(); $this->a1[$i]->b1=$value; } function SetData(){ $this->printout("123 "); $this->printout("abc "); $this->printout("DEF "); } } $c = new TEST(); $c->SetData(); echo $c->a1[0]->b1; echo $c->a1[1]->b1; echo $c->a1[2]->b1; ?> こんな感じに。 PHP5ならクラス内のプロパティ、メソッドに対して スコープ(直接呼出し可能範囲)が指定できますので、 外部から呼び出せないよう制御させたりする事も出来ます。 PHP4ですとそのあたりの定義がちょっと弱い為、 なんでもかんでも呼べちゃいます。 だから作成したプログラムソースを配布する際は ユーザーが意図的に閉鎖的なクラス内の関数や変数を直接呼んだりも出来てしまいます。 3つ目の例ですと、printout()はクラス内で呼んでくれるだけで良いのですが、 外部からも呼べちゃいます。 私もクラス(オブジェクト指向型)については まだまだ勉強中の身ですので、上記くらいの書き方しか思いつきませんでした。 (有用性の有無は関係なく) 他にもっと良い書き方があるのかもしれません。
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
なんかちょっと分かったかもしれません。 疑問1. print_r($c->$a1);とした結果、 stdClass Object ( [b1] => DEF ) です。 クラス自体がTEST2ではないですね。 また、$aとしている時点で、TESTのプロパティ$aを見ているわけではありません。 その証拠に、print_r($c->a1);とすると、 「TEST2」という文字列が入っています。 インスタンスも生成されていませんね。 なんかクラス情報が無い時に勝手に読み込まれるクラス なんでしょうかね。stdClassってのは。空クラスみたいな。 print_r($c);とした結果、 test Object ( [a1] => TEST2 [] => stdClass Object ( [b1] => DEF ) ) です。 つまり、$c->a1にTEST2という文字列が含まれています。 また、a1の配列部には未定義時のクラスオブジェクトが入っている。 ($c->$aとした場合の値。プロパティというより、 完全に変数扱いされている) 通常、インスタンスの生成は$a = new classname(); とする必要があるので、クラスのプロパティ値にいきなり 別クラスのインスタンスを持つ事は出来ないみたいですね。 var $a1 = new TEST2();という表記も出来ません。 コンストラクタを利用すべき箇所ですね。 $a1 = TEST2で、TEST2という文字列が入るとは知りませんでした・・・。 あとわけのわからないクラスについても知りませんでした。 わけのわからないクラスに対して配列指定が無視されるのは 何故かわかりません。 クラスとして動いているせいっぽいです。 仮に $c->$a1->a2 = "abc"; $c->$a1->b2 = "DEF"; とあった場合、 print_r($c)ではクラスの二重構造になりますから。 疑問2. 全ては上手くインスタンスを作れてなかったせいですね。 プロパティa1は初期値で文字列なのに対して それを関数内で配列化し、さらにTEST2のインスタンスである事を前提に プロパティb1へ値を入れようとしていた為です。 プロパティa1はインスタンスでは無い為、printout()では 結局何も入れる事が出来ていません。 また先に述べた通り、$a1->~とする事で、わけのわからない クラスのインスタンスとして扱われています。 なんか説明悪いですが、根源は$this->a1がTEST2のインスタンスでない事です。 $this->a1が配列であり、各添字毎にインスタンスが正しく作られれば、 $c->a1[0]->b1といけるでしょう。
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
<?php class TEST2{ var $b1; } class TEST{ var $a1; function TEST(){ $this->a1[0] = new TEST2(); $this->a1[1] = new TEST2(); $this->a1[2] = new TEST2(); } function printout(){ $this->a1[0]->b1 = '123 '; $this->a1[1]->b1 = 'abc '; $this->a1[2]->b1 = 'DEF '; } } $c = new TEST(); $c->printout(); echo $c->a1[0]->b1; echo $c->a1[1]->b1; echo $c->a1[2]->b1; ?> これで動きますよ。 違いはコンストラスタとプロパティの値の送受信、 インスタンスの生成時です。 質問のコーディングですと、$aは初期値として インスタンスをセットしているのに、 関数内ではいきなり配列になってます。 TEST2のインスタンスのはずなのに、それに配列は存在しません。 その後からはちょっと私の知識では説明出来ません^^; 摩訶不思議な現象が(笑) この時点で$a[0]~[2]とは別モノ状態(?)のようになってしまい、 動きがおかしくなっているように感じます。 配列はないのに、あたかも配列のように扱おうとして、 でも配列は存在しないから、、、、 うむ、わかりません>< 上記プログラムだと、クラスTESTのプロパティとして$a1の配列が存在し、その存在毎にクラスTEST2をセットしているので正常に動作します。 また、 <?php class TEST2{ var $b1; function TEST2(){ $this->b1 = array(); } } class TEST{ var $a1; function TEST(){ $this->a1 = new TEST2(); } function printout(){ $this->a1->b1[0] = '123 '; $this->a1->b1[1] = 'abc '; $this->a1->b1[2] = 'DEF '; } } $c = new TEST(); $c->printout(); echo $c->a1->b1[0]; echo $c->a1->b1[1]; echo $c->a1->b1[2]; ?> とすれば、クラスTESTの$aにはクラスTEST2のインスタンスが存在し、 クラスTEST2のプロパティとして$bを配列として利用していますから、正常に動作します。
お礼
回答ありがとうございました array()とコンストラクタについてなんとなくですが、納得できました。先が見えてきました!! もうひとつ質問ななのですが。 $this->a1[]->b1 のようにa1を配列にするにはどのようにすればよいのですか? 配列をひとつずつ $this->a1[0] = new TEST2(); $this->a1[1] = new TEST2(); $this->a1[2] = new TEST2(); のようにすればいいのはわかるのですが、配列の個数が未知のときはどのようにすればよいのでしょうか。 自分なりに 以下のようなプログラムを書いてみたのですが動きません <?php class TEST2{ var $b1; } class TEST{ var $a1; function TEST(){ $this->a1=array(); $this->a1= new TEST2(); } function printout(){ $this->a1[0]->b1='123 '; $this->a1[1]->b1='abc '; $this->a1[2]->b1='DEF '; } } $c = new TEST; $c->printout(); echo $c->a1[0]->b1; echo $c->a1[1]->b1; echo $c->a1[2]->b1; ?> どうやら$this->a1[0]->b1='123 '; の行でエラーがでるようです。 何度もすみません、お願いします。