4

[編集] 問題をより正確に反映するようにタイトルを更新

私が解決しようとしている問題は次のとおりです。メソッドが経由parent::で呼び出されたかどうかを知る必要があり、それを使用できる間はdebug_backtrace、これを行うためのより良い方法があるはずです。

私は後期静的バインディングを調べてきましたが、解決策を理解するのに十分なほどよく理解していない可能性があります。

問題のメソッドは__call、エラーとして余分なパラメーターを単純に渡すことができないため、正確に2つ以上またはそれ以下になることです。

この問題を解決しようとする理由は、親クラスにはがあります__callが、子には がある場合とない場合があるため_callです。子がそれを持っておらず、親が呼び出しをディスパッチしない場合、例外またはエラーをスローしたいと思います。子がメソッドを持っている場合は、戻りますfalse(いいえ、これを処理しませんでした) 子_callメソッドを続行させます。

これまでのところ、私の唯一の有効な解決策は、子呼び出しparent::__callを try/catch ブロックでラップし、要求をルーティングしない場合、デフォルトで親に例外をスローさせることです。

すなわち。

class Parent {
  public function __call( $method, $params ) {
    if( preg_match( $this->valid, $method ) {
      $this->do_stuff();
      // if child has a call method, it would skip on true
      return true;
    }
    elseif( ** CHILD HAS CALL METHOD ** ) {
      // this would let the child's _call method kick in
      return false;
    }
    else {
      throw new MethodDoesNotExistException($method);
    }
  }
}

class Child extends Parent {
  public function __call( $method, $params ) {
    if( ! parent::__call( $method, $params ) ) {
      do_stuff_here();
    }
  }
}

親がメソッドを処理しない場合は例外をスローしますが、フロー制御に例外を使用することは正しくないように思われるため、より洗練された解決策があるかどうかを確認しようとしています。ただし、スタックトレースを使用して呼び出し元を特定することもありません。

4

2 に答える 2

4

これは親クラスで行う必要があります。

if (__CLASS__ != get_class($this))
于 2012-11-13T17:31:35.807 に答える
1

これがあなたのニーズに合っているかどうかは完全にはわかりません。また、この種のハックは OO 設計の観点からは本当に悪いと考えています。しかし、コーディングするのは楽しいことでした:)

<?php

class ParentClass 
  {
  public function __call( $method, $params ) 
  {
    if($method === 'one')
    {
      echo "Parent\n";
      return true;
    }
    elseif($this->shouldForwardToSubclass($method)) 
      {
        return false;
      }
    else 
    {
      throw new Exception("No method");
    }
  }

   protected function shouldForwardToSubclass($methodName)
   {
      $myClass = get_class($this);
      if (__CLASS__ != $myClass)
      {
        $classObject = new ReflectionClass($myClass);
        $methodObject = $classObject->getMethod('__call');
        $declaringClassName = $methodObject->getDeclaringClass()->getName();
        return $myClass == $declaringClassName;
      }
      else 
          {
            return false;
          }
}

}

class ChildClass1 extends ParentClass {
  public function __call( $method, $params ) {
    if( ! parent::__call( $method, $params ) ) 
    {
      echo "Child handle!\n";
    }
  }
}

class ChildClass2 extends ParentClass {
}

後で行う:

$c = new ChildClass1();
$c->one();
$c->foo();

$c = new ChildClass2();
$c->foo();

次の結果が得られます。

Parent
Child handle!
PHP Fatal error:  Uncaught exception 'Exception' with message 'No method' in /home/andres/workspace/Playground/test.php:18
Stack trace:
#0 /home/andres/workspace/Playground/test.php(58): ParentClass->__call('foo', Array)
#1 /home/andres/workspace/Playground/test.php(58): ChildClass2->foo()
#2 {main}

HTH

于 2012-11-13T20:02:08.193 に答える