デフォルトの定義済みクラスについて
自分で定義したクラスの継承関係やらを出力するサンプルスクリプトがあったので、それをまる写しして動かしたところ、エラーがおこりました。以下のスクリプトがそれです。
<?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です。よろしくお願いします。
お礼
> えと………どのように学ばれたのか背景が... 学んだもなにも余りにユーザー定義関数が増えたため(既に100位存在します)クラスにより有る程度分類しなければ 名前が衝突する事態に陥り始めた為に何か対応が必要になった次第です。 > ですが、メソッド名を動的にする必要があると仮定して... 分かりました。参考にさせていただきます。 > ただ、万全のセキュリティ対策を施してなお、 > > 実際に使う時には$_GETの入力値から呼び出すクラスの変更を行おうと考えています。 > については危険性が伴うので、十二分に注意が必要かと思われます。 「$_GETの入力値と同じキーを持つ配列の要素を探しもし見つかった場合要素が保持する値が呼び出すべきクラス名」 となっていますので入力値が直接呼び出すクラス名を指定できる状態にはなっていません。 $class_list = array ("class1" => "class_a", "class2" => "class_b"); $mode = $_GET["mode"]; if (isset ($class_list[$mode])) { $obj = new $class_list[$mode]; } といった挙動です。 > # 多分MVC系のフレームワークのコントローラ部分なのだろうと思われるのですが… > # あと、もしコントローラ部分なら、メソッド名は固定に出来ると思います。 クラスを定義しているファイル自身が独立したファイルです。 またApacheのモジュールのような組み換えを可能にしたい為クラス名の固定を行う事が出来ません。