デフォルトの定義済みクラスについて
自分で定義したクラスの継承関係やらを出力するサンプルスクリプトがあったので、それをまる写しして動かしたところ、エラーがおこりました。以下のスクリプトがそれです。
<?php
function get_methods($object){
$methods=get_class_methods(get_class($object));
if(get_parent_class($object)){
$parent_methods=get_class_methods(get_parent_class($object));
$methods=array_diff($methods,$parent_methods);
}
return $methods;
}
function get_inherited_methods($object){
$methods=get_class_methods(get_class($object));
if(get_parent_class($object)){
$parent_methods=get_class_methods(get_parent_class($object));
$methods=array_intersect($methods,$parent_methods);
}
return $methods;
function get_lineage($object){
if(get_parent_class($object)){
$parent=get_parent_class($object);
$parent_object=new $parent;
$lineage=get_lineage($parent_object);
$lineage[]=get_class($object);
}
else{
$lineage=array(get_class($object));
}
return $lineage;
}
function get_child_classes($object){
$classes=get_declared_classes();
$children=array();
foreach($classes as $class){
if(substr($class,0,2)=='__'){ //ここに問題があるようです。
continue;
}
$child=new $class; //ここで「引数が無効」のエラーになります。
if(get_parent_class($child)==get_class($object)){
$children[]=$class;
}
}
return $children;
}
function print_object_info($object){
$class=get_class($object);
echo '<h2>クラス</h2>';
echo "<p>$class</p>";
echo '<h2>継承関係</h2>';
echo '<h3>親クラス</h3>';
$lineage=get_lineage($object);
array_pop($lineage);
echo count($lineage)?('<p>'.join(' -> ',$lineage).'</p>'):'<i>None</i>';
echo '<h3>子クラス</h3>';
$children=get_child_classes($object);
echo '<p>'.(count($children)?join(',',$children):'<i>None</i>').'</p>';
echo '<h2>メソッド</h2>';
$methods=get_class_methods($class);
$object_methods=get_methods($object);
if(!count($methods)){
echo "<i>なし</i><br/>";
}
else{
echo '<p>継承しているメソッドは、<i>斜体</i>で表示します。</p>';
foreach($methods as $method){
echo in_array($method,$object_methods)?"<b>$method</b>();<br/>":"<i>$method</i>();<br/>";
}
}
echo '<h2>プロパティ</h2>';
$properties=get_class_vars($class);
if(!count($properties)){
echo "<i>なし</i><br/>";
}
else{
foreach(array_keys($properties) as $property){
echo "<b>\$$property</b>=".$object->$property.'<br/>';
}
}
echo '<hr/>';
}
//省略しましたがここにクラスA、B、Cを用意しました。
$a=new A;
$a->foo='sylvie';
$a->bar=23;
$b=new B;
$b->foo='bruno';
$b->quux=true;
$c=new C;
print_object_info($a);
print_object_info($b);
print_object_info($c);
?>
これを実行すると途中からエラーになります。$classがどんな値か出力するために、
foreach($classes as $renban=>$class){
print_r("{$renban}:{$class}\n<br/>");
}
にして出力したら、
0:stdClass
……
139:A
140:B
141:C
になりました。(get_declared_classes()が返す値は、スクリプト内で自分が定義したクラス以外に、PHPがデフォルトで定義しているクラスもあることに、昨日気づきました。)
本を書いた人は、foreach文の直後の
if(substr($class,0,2)=='__'){
continue;
}
の所でデフォルトの定義済みクラスを除外する目的だったと思います。
ここを、
foreach($classes as $class){
if(substr($class,0,1)!='A||B||C'){
continue;
}
に変えたらちゃんと画面が表示されました。
本を書いた人はなぜ、if(substr($class,0,2)=='__')にしたのでしょうか?また、if(substr($class,0,1)!='A||B||C')だとあらかじめ自分が定義しているクラスを記述しているのでなにかぱっとしない感じがします。自分が定義したクラス以外を除外という書き方でなく、デフォルトの定義済みクラスをうまく除外する方法などございましたらアドバイスの方よろしくお願いします。
こちらの環境は、windows vistaにxampp1.6.5、php5.2.5です。よろしくお願いします。
お礼
classの定義はやはりグローバルなスコープを持ちますね。 クラスを動的に定義するのなら__autoloadかclass_existsを用いればよいように思いますが、なぜこんなことをしているのかわかりません。 ありがとうございます。 参考: http://jp.php.net/manual/ja/language.oop5.autoload.php, http://jp.php.net/manual/ja/function.class-exists.php