1

インターフェイスを使用して関数の定義を強制できることは理解していますが、関数呼び出しを強制できるものを見つけることができません。そのクラスが必須関数がその関数で部分的に呼び出されることを自動的に保証するための関数。

つまり、さらに明確にするために:

class domain {

   function isEmpty($input) {
      //apply conditional logic and results
   }
}
class test extends domain {

   function addTestToDBTable($test) {
      /** 
       *  try to add but this class automatically makes it so that all rules of
       *  class domain must be passed before it can run
       *  - so essentially, I am no longer required to call those tests for each and
       *    every method 
       **/  
   }
 }

これが何らかの意味で一貫性がないように見える場合は、お詫び申し上げます。確かに、怠け者に見えますが、気にせずにコンテキストを強制できるようにしたいです

アップデート:

さらに明確にするために、PHP では、子クラスの __construct() を拡張して宣言すると、その子クラスは親の __construct() をオーバーライドします。私はこれを望んでいません。子クラスがそうするのと同じように、親コンストラクトが残って、好きなように義務付けてほしいのです。

4

3 に答える 3

0

2つの異なる方法で行うことができると思います。

アスペクト指向プログラミング

こちらをご覧ください https://github.com/AOP-PHP/AOP

Proxy クラスの生成または書き込み

非常に単純な例は次のとおりです。

<?php
class A {
    public function callMe() {
        echo __METHOD__ . "\n";
    }
}

class B extends A {

    // prevents instantiation
    public function __construct() {
    }

    public function shouldCallMe() {
        echo __METHOD__ . "\n";
    }

    public static function newInstance() {
        return new ABProxy();
    }
}

class ABProxy {
    private $b;

    public function __construct() {
        $this->b = new B();
    }

    public function __call($method, $args) {
        $this->b->callMe();
        return call_user_func_array(array($this->b, $method), $args);
    }
}

// make the call
$b = B::newInstance();
$b->shouldCallMe();

// Outputs
// ------------------
// A::callMe
// B::shouldCallMe

これが少し役立つことを願っています。

于 2013-03-13T21:12:53.167 に答える
0

Decoratorが必要なようですね。

その方法の詳細な説明については、この回答を参照してください。クラス拡張は必要ないことに注意してください。

于 2013-03-13T21:13:56.380 に答える
0

doc-block メタプログラミング マジックでドメイン検証デコレータを使用します。しかし、これは実際にはライブラリ全体の仕事であり、間違いなく存在します。

フィドル

<?php
class FooDomain {
    public static function is_not_empty($input) {
        return !empty($input);
    }
}

class Foo {
    /**
     * @domain FooDomain::is_not_empty my_string
     */
    public function print_string($my_string) {
        echo $my_string . PHP_EOL;
    }
}

$foo = new DomainValidator(new Foo());
$foo->print_string('Hello, world!');
try {
    $foo->print_string(''); // throws a DomainException
} catch (\DomainException $e) {
    echo 'Could not print an empty string...' . PHP_EOL;
}

// ---

class DomainValidator {
    const DOMAIN_TAG = '@domain';

    private $object;

    public function __construct($object) {
        $this->object = $object;
    }

    public function __call($function, $arguments) {
        if (!$this->verify_domain($function, $arguments)) {
            throw new \DomainException('Bad domain!');
        }

        return call_user_func_array(
            array($this->object, $function),
            $arguments
        );
    }

    public function __get($name) {
        return $this->object->name;
    }

    public function __set($name, $value) {
        $this->object->name = $value;
    }

    private function verify_domain($function, $arguments) {
        // Get reference to method
        $method = new \ReflectionMethod($this->object, $function);
        $domains = $this->get_domains($method->getDocComment());
        $arguments = $this->parse_arguments(
            $method->getParameters(),
            $arguments
        );
        foreach ($domains as $domain) {
            if (!call_user_func(
                $domain['name'],
                $arguments[$domain['parameter']]
            )) {
                return false;
            }
        }
        return true;
    }

    private function get_domains($doc_block) {
        $lines = explode("\n", $doc_block);
        $domains = array();
        $domain_tag = DomainValidator::DOMAIN_TAG . ' ';
        foreach ($lines as $line) {
            $has_domain = stristr($line, $domain_tag) !== false;
            if ($has_domain) {
                $domain_info = explode($domain_tag, $line);
                $domain_info = explode(' ', $domain_info[1]);
                $domains[] = array(
                    'name'      => $domain_info[0],
                    'parameter' => $domain_info[1],
                );
            }
        }
        return $domains;
    }

    private function parse_arguments($parameters, $values) {
        $ret = array();
        for ($i = 0, $size = sizeof($values); $i < $size; $i++) {
            $ret[$parameters[$i]->name] = $values[$i];
        }
        return $ret;
    }
}

出力:

Hello, world!
Could not print an empty string...
于 2013-03-13T21:21:18.040 に答える