2016-10-31 7 views
2

非静的と呼ばれる静的関数をどのように検出できますか?例えば非静的と呼ばれる静的関数の検出

、この場合には:誰かがどこか間違って、それは、関連する何かを返すだろうと期待して、インスタンス上の関数を呼び出します。

class Foo 
{ 
    public static function bar() 
    { 
     // How can I tell here that bar() is called on an instance? 

     //var_dump(debug_backtrace()[0]['type'] == '::'); 
     // at all times the above prints bool(true) 
     return 1; 
    } 
} 

// later in the code 
$foo = new Foo(); 
$foo::bar(); // that's fine 

// even later 
$foo->bar(); // this should not happen, yet it's here and there 

私は、このような上記の最後の行になどのケースをデバッグし、根絶したいです件名のインスタンスに;代わりに、いくらか関連する定数が得られます。その後、いつ起こるか知る必要があります。地獄が緩んだり、例外がスローされたりするのは私にとっても大丈夫です。

これまでのところ私はdebug_backtrace()[0]['type']したがって、静的な機能のための非静的呼び出しがinternally translated into static callsであることを発見した何も(それは両方のケースで::です)を教えてくれるん。

+0

静的でない関数を静的に呼び出すとエラーになります。静的でない静的関数を呼び出すことは**ではありません**。あなたのコードは前者ではなく後者の例です。 – Sherif

+0

@Sherif質問を更新して、それが実際にはエラーではないことをより明白にしてください。 – sanmai

+0

私は何を疑問に思っているのでしょうか?私を捨てたのは、あなたが「*これらのケースをデバッグする」というステートメントを使用するという事実です。これは、バグの原因となる印象を受けていると信じています。それはできません。 PHPは既にメソッドが静的に宣言されていることをコンパイル時に知っています。したがって、実行時にオブジェクトインスタンスからメソッドを呼び出そうとしても構いません。静的コンテキストを使用することはまだ分かっています。 – Sherif

答えて

0

あなたは永遠にE_STRICTをオフにしたくない場合は、方法があります。

クラスFooだけそうのような場所のカップルでインスタンス化、全くの幸運や摂理によって、ある場合:

public function getFoo() 
{ 
    return new Foo(); 
} 

その後、我々はそれをサブクラス化しbar()を再定義する場合:

class Foo2 extends Foo 
{ 
    public static function bar() 
    { 
     throw new Exception("You're calling Foo::bar() on an instance"); 
    } 
} 

その後FooFoo2に置き換えた場合、インスタンス化された場所は...

public function getFoo() 
{ 
    //return new Foo(); 
    return new Foo2(); 
} 

例外は、上記の新しい静的メソッドを呼び出すときにスローされます。

$q = Foo::bar(); // no error just as before 

$foo = $other->getFoo(); 
$foo->bar(); // throws exception 

誰もが今までこの種・オブFoo$foo->bar();を呼び出す場合、彼はすぐに彼が間違いを犯していたことが通知されるだろう。

2

ソリューションが二つある:

  1. まず一つはE_STRICT報告を無効にする必要があります。

    error_reporting(error_reporting()^E_STRICT); 
    
  2. 次のいずれかが、関数の宣言からstaticキーワードを削除する必要があります。

    public /* static */ function bar() 
    

今では、関数がdebug_backtrace機能の助けを借りて、静的または動的に呼び出されているかどうかを確認することが可能である:

class Foo 
{ 
    public function bar() 
    { 
     $calledStatically = debug_backtrace()[0]['type'] == '::'; 

     if (!$calledStatically) { 
      throw new Exception("Should not happen"); 
     } 

     // ... 
    } 
} 

ドキュメントから:

type(文字列):現在のコールタイプ。メソッド呼び出しの場合は、 " - >"が返されます。 static メソッド呼び出しの場合は、 "::"が返されます。関数呼び出しの場合、何も返されません。 が返されます。

クイックデモ

Foo::bar(); // normal result returned 

$foo = new Foo(); 
$foo->bar(); // throws exception 
+0

私がこの質問に留意しているように、 'debug_backtrace'はあなたがそれを信じるべき方法を助けていません。 – sanmai

+0

'' '$ utils = new Utils(); $ utils :: whoDat(); $ utils-> whoDat(); '' 'これはどのように動作しますか? – sanmai

+0

最後に更新されました... "static"を削除するのが有効なオプションかどうかはわかりません。しかし、これは動作するようです。 –

関連する問題