• ベストアンサー

変数によるクラスの呼び出しができない

変数によるクラスの呼び出しができません。 <?php class test { public function test_method () { $return = "test"; return $return; } } $test1 = 'test'; $test2 = 'test_method'; new $test1; echo $test1::$test2 (); ?> 問題が起こっているのは new $test1; echo $test1::$test2 (); の部分の$test1をtestに変更する事で正しく動作します。 実際に使う時には$_GETの入力値から呼び出すクラスの変更を行おうと考えています。 セキュリティー対策として登録済みクラスの対応表を使っての呼び出しを行っているので対応表を if ($_GET["~"] == ~) { new ~; ~::test(); } else... のような形式に出来ないわけではないですが対応表自身が変動する為この方法では対応表の書き換えが大変困難なものになってしまいます。 変数を使った呼び出しの方法は無いもなのでしょうか。 環境はWeb ServerがApache 2.2.0,PHPが5.1.4の状態でmod_suPHP 0.6.1を使っています。

  • PHP
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • galluda
  • ベストアンサー率35% (440/1242)
回答No.2

がると申します。 えと………どのように学ばれたのか背景が不明ではあるのですが。クラスの使い方の基本が根本から間違ってますので、是非一度履修されなおすことをお勧めいたします。 まず、 new $test1; については、最低限きちんと $obj = new $test1; とすべきです。これは、new演算子が「インスタンスを返すもの」だからです。 次に echo $test1::$test2(); ですが、メソッド名を動的にする必要があると仮定して、これはPHPであれば call_user_func などを用いたほうがよろしいかと思われます。 上述と絡めると、$test1の部分はインスタンスが格納されている変数名になろうかと思うのですが。 ただ、万全のセキュリティ対策を施してなお、 > 実際に使う時には$_GETの入力値から呼び出すクラスの変更を行おうと考えています。 については危険性が伴うので、十二分に注意が必要かと思われます。 # 多分MVC系のフレームワークのコントローラ部分なのだろうと思われるのですが… # あと、もしコントローラ部分なら、メソッド名は固定に出来ると思います。

izayoimizuki
質問者

お礼

> えと………どのように学ばれたのか背景が... 学んだもなにも余りにユーザー定義関数が増えたため(既に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のモジュールのような組み換えを可能にしたい為クラス名の固定を行う事が出来ません。

その他の回答 (1)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

<?php class test{ function test_method(){ $return = "test"; return $return; } } $test1 = 'test'; $test2 = 'test_method'; $testclass=new $test1; echo $testclass->$test2(); ?>

izayoimizuki
質問者

お礼

ありがとうございます。 解決しました。

関連するQ&A

  • テンプレートクラスでのクラス変数

    テンプレートから生成したクラスごとにクラス変数を設けて、 かつ、クラス変数の初期化をいちいちやらなくてもよい という状況を作りたいと考えています。 そこでたとえば template <int N> class test { public: static int class_var() { static int class_var_ = N; return class_var_; } }; としたとき test<1>::class_var() と test<2>::class_var() はどのような値になるのでしょうか? VC++ではテンプレート全体で class_var_の値が同じになってしまうようのなのですが。。。 そもそも、こういうクラス変数自体を つくろうという考えが間違っているのでしょうか? どなたかご存知でしたらお教えください。

  • 変数を{}で囲むときに$を中に入れるか入れないか

    PHPで変数を書くとき、 echo $test; と書くのが普通ですが、前後に文字を書く場合は、 echo ああ{$test}いい; と書いていました。 が、最近になって、{}内に$を入れないのが普通ということを知りました。 そこで質問なんですが、$を{}内に入れた書き方は本当に間違いなのでしょうか? また、{}内に$を入れない場合は、$_GET['']を囲む場合はどのように囲めばいいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • PHP
  • 同じ名前の変数…

    数日前からPHPをはじめた者です。 クラス変数(という呼び方が適切かは??)と、その変数に値をセット/ゲットする関数を内包するクラスを作ってみたのですが、それに関してどうもピンと来ない部分があるので質問させてください。 以下がソースです。 class sample{ var $hensu; function set_hensu($str){ $hensu = $str; } function get_hensu(){ return $hensu; } } 上記クラスを使って値のセット/ゲットをしようとしたのですが、結果は×でした。 ファンクション内の変数を、thisで指定するとうまく行きました。 最初に指定した変数と、ファンクション内の変数を同一のものだと認識させるには、ファンクション内でのthis指定の他に方法は無いのでしょうか? もしくは、ファンクション内で書いた変数が新しい変数だと認識させない方法とか…。 無いなら諦めます。よろしくお願いします。 また、直接質問とは関係ないのですが、 どうしてPHPは変数名を書いただけで変数が作られてしまうのでしょう。メリットは何ですか? 分かりづらくて戸惑ってます。

    • ベストアンサー
    • PHP
  • デフォルトの定義済みクラスについて

    自分で定義したクラスの継承関係やらを出力するサンプルスクリプトがあったので、それをまる写しして動かしたところ、エラーがおこりました。以下のスクリプトがそれです。 <?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(' -&gt; ',$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です。よろしくお願いします。

    • ベストアンサー
    • PHP
  • PHPの設定について

    よろしくお願いします。 先日、自宅サーバでアパッチとphpの4.3をインストールしました。 で、ローカルで試したところ、他は普通に動くのですが、変数を受け取りません。 たとえば <?php echo $test; ?> と記述したPHPをtest.phpとしてサーバフォルダにおき、 ブラウザでhttp://localhost/test.php?test=abc を見ても真っ白の画面になります。 同様に <form action="test.php" method="post"> (getでも試しました) <input type="text" name="test"> <input type="submit" value="送信"> </form> といったようにmethodで送っても真っ白な画面のままです。 次に test.phpを <?php if( $test == abc ){ echo "OK"; }else{ echo "NG"; } ?> とやってみて試しましたが結果はNGでした。 どうやら変数を受け取ってないらしいです。 phpのセキュリティを変更したらよいとの記事を見つけたのでそういう関係サイトを検索してみたのですが、それらしき内容を見つけられませんでした。 どなたかご教授お願いします。

    • 締切済み
    • PHP
  • 違うクラスからの変数の共有化

    一つのクラスの中にある変数の値を、二つの別なクラスから呼び出して、その二つのクラスのどちらから変数を参照しても同じ値が帰ってくるようにしたいのですが、いろいろ調べてもできなかったので質問させていただきますm(_ _)m // 共有化させたい変数を持つクラス // Var.java public class Var{  public static int i;  public Var(int i){ this.i = i; }  public Var(){}  public static void getI(){   return i;  } } //クラス1 //Class1.java public class Class1{  Var var = new Var(1); } //クラス2 //Class2.java public class Class2{  Var var = new Var();  System.out.println(var.getI()); } とした場合、Class1を実行し、次にClass2を実行すると、クラス1で定義した変数の値である 1 が戻ってくるようにしたいのですが、上記の方法では、Class2を実行すると結果は 0 になってしまいました。 まだまだ習い始めたばかりでいまいちstaticを使い切れていないと思います・・・ たとえば、PrintStreamクラスの public static final PrintStream out というのはどこから参照しても同じ結果なのでそのようなやり方で大丈夫だろうと思ったのですが・・・ このような方法では共有化させることはできないのでしょうか?またできないのでしたらほかのやり方がもしあった場合は教えていただきたいと思います。 どうかお願いします。

    • ベストアンサー
    • Java
  • staticつきのインナークラスのインスタンスについて

    以下のようにTestクラス内にstaticなSIクラスを作成しました。 SIクラスのmethodSI()を呼び出す際に、 ( ( new Test() ).new SI() ).methodSI(); のように呼び出しを行おうとすると、エラーになります。 その原因を教えてください。 public class Test{   static class SI{     void methodSI(){       System.out.println( "method si" );     }   }   public static void main( String args[] ){ //次の行↓     ( ( new Test() ).new SI() ).methodSI(); //以下は全て成功します。     (new Test()).SI();     ( new Test.SI() ).methodSI();     ( new SI() ).methodSI();   } }

  • 例えば、以下のようなクラスでmap変数に、あらかじめ値を入れておいて、

    例えば、以下のようなクラスでmap変数に、あらかじめ値を入れておいて、別のクラスで使うときに Common.map.get(""); と書いて、いつでも値を取り出したいのですが、static変数は、コンストラクタでいじれないようで出来ません。 このCommonクラス内であらかじめ値を入れておく方法はあるでしょうか? public class Common{ public static HashMap<String, String> map = new HashMap(); }

    • ベストアンサー
    • Java
  • 親クラスのポインタで派生クラスの関数呼び出し

    下記のようなクラス構成があるとします。 説明のため簡略化しています。 [Test.h] class CParent { protected: int nParent; public: CParent(){nParent = 10;} ~CParent(){}; virtual int func1(){ // (*1) return nParent; } }; class CSub : public CParent { int m_nSub1; // 派生クラスにしかないメンバ変数 int m_nSub2; // 派生クラスにしかないメンバ変数 public: CSub(){m_nSub = 20;} ~CSub(){}; int func1(){ // (*3) return nParent*2; // 20 } // 派生クラスにしかないメンバ関数 int func2() // (*4) { m_nParent; // 10 return m_nSub1; // 不定値 } int SetData(int n) // (*5) { m_nSub2 = n; return m_nSub2; } }; [Test.cpp] void main() { CParent parent; // 親クラスのオブジェクト CParent* pParent = &parent; // 親クラスのオブジェクトを指すポインタ int nRet = 0; nRet = pParent->func1(); // (*1) // サブクラスのポインタ型にキャストする CSub* pSub = (CSub*)pParent; // (*2) nRet = pSub->func1(); // (*3) nRet = pSub->func2(); // (*4) nRet = pSub->SetData(60); // (*5) } (*3)ではpSubの指すオブジェクトが親クラス(CParent)のため、ポリモーフィズムのメカニズムに従ってCParent::func1()が呼ばれ10が返ってきます。ここまでは想定通りです。 次の(*4)ですが、これはCSub::func2()が呼ばれています。なぜこの呼び出しで子クラスの関数を呼ぶことが出来るのでしょうか? 実際その動作をさせたいのですが、なぜそうなるのかが分かりません。想定ではpSubが指す先は親クラスのため、子クラスにしかないメンバ関数func2()は呼べないはずです。 このコードでは、CSubのコンストラクタは通りませんので(そもそもCSub型のインスタンスは実体化していない)、(*4)の呼び出しでは不定値が返ります。また、(*5)は期待通り動作し、戻り値60が返っています。 これは危険な事をしているのでしょうか? 期待通りではあるのですが、なぜこのような動作になるのか理解できません。 上記のようなことをしたい場合、どのように記述するべきでしょうか?

  • Calendarクラスのフィールドは、クラス変数?インスタンス変数?どちらですか?

    宜しくお願いします。 Calendarクラスのフィールドの、Calendar.YEARなどは、 Calendarというクラス名で修飾されているので「クラス変数」ですよね。 クラス変数なので、全てのインスタンスで共有されているはずです。 なので、あるインスタンスから、Calendar.YEARに変更を加えると、全てのインスタンスに 変更が適用されると思うのですが、そうなりません。何故でしょうか。 例えば以下のようなコードを書いた場合、このように出力されます。 2008年10月6日 2009年10月6日 2008年10月6日 YEARはクラス変数なので、3つ目の出力も2009年になると思ったのですが、YEARは 各インスタンスで所有されているようです。 (上手くインデントできないようでして、読みにくいコードで失礼します) import java.util.*; public class DateTest { public static void main(String[]args){ Calendar cal = Calendar.getInstance(); showDate(cal); Calendar cal2 = Calendar.getInstance(); cal2.add(Calendar.YEAR, 1);//ここでCalendarのクラス変数を変更している showDate(cal2);//変更が適用されている showDate(cal);//変更が適用されていない?なぜ? }  //Calendarインスタンスの年・月・日を出力する public static void showDate(Calendar cal){ System.out.println(cal.get(Calendar.YEAR)+"年"              +(cal.get(Calendar.MONTH)+1)+"月" +cal.get(Calendar.DATE)+"日"); } } プログラムは嘘をつかないので、自分の理解が誤っていると思います。 どなたか解決する知識をお持ちの方、どうぞご教示ください。 (初心者ですので、できれば、ほどほどのレベルの説明でお願いします。) 宜しくお願いします。