Altsınıfları PHP'nin sihirli yöntem __ çağrısı

4 Cevap php

Benim durumun iyi bir kodun ile tarif edilir:

class Foo {
    function bar () {
        echo "called Foo::bar()";
    }
}

class SubFoo extends Foo {
    function __call($func) {
        if ($func == "bar") {
            echo "intercepted bar()!";
        }
    }
}

$subFoo = new SubFoo();

// what actually happens:
$subFoo->bar();    // "called Foo:bar()"

// what would be nice:
$subFoo->bar();    // "intercepted bar()!"

Ben bu bar() (ve tüm ilgili diğer yöntemler) yeniden tanımlayarak işe alabilirsiniz biliyorum alt-sınıf, ama benim amaçlar için, bu güzel olurdu eğer __call fonksiyon onları ele verebilir. Bu sadece bir şeyleri lot kıvrımlara ve daha yönetilebilir yapmak istiyorum.

Bu PHP mümkün mü?

4 Cevap

Aksi takdirde, fonksiyon böylece, örneğin, yazılı olarak, mümkün değildir bulduk değilken __call() sadece çağrılır.

Bu, direkt olarak yapılamaz, ancak bu bir olası alternatiftir:

class SubFoo { // does not extend
    function __construct() {
        $this->__foo = new Foo; // sub-object instead
    }
    function __call($func, $args) {
        echo "intercepted $func()!\n";
        call_user_func_array(array($this->__foo, $func), $args);
    }
}

Bu tür bir şey hata ayıklama ve test için iyidir, ama __call() ve çok etkili değil gibi üretim kodu mümkün olduğunca arkadaş önlemek istiyor.

Eğer ana bara için ekstra bir şey () eklemeniz gerekiyorsa, bu yapılabilir olacaktır?

class SubFoo extends Foo {
    function bar() {
        // Do something else first
        parent::bar();
    }
}

veya bu merakı sadece bir soru?

Eğer aynı etkiye sahip yapabileceği ne aşağıdadır:

    <?php

class hooked{

    public $value;

    function __construct(){
    	$this->value = "your function";
    }

    // Only called when function does not exist.
    function __call($name, $arguments){

    	$reroute = array(
    		"rerouted" => "hooked_function"
    	);

    	// Set the prefix to whatever you like available in function names.
    	$prefix = "_";

    	// Remove the prefix and check wether the function exists.
    	$function_name = substr($name, strlen($prefix));

    	if(method_exists($this, $function_name)){

    		// Handle prefix methods.
    		call_user_func_array(array($this, $function_name), $arguments);

    	}elseif(array_key_exists($name, $reroute)){

    		if(method_exists($this, $reroute[$name])){

    			call_user_func_array(array($this, $reroute[$name]), $arguments);

    		}else{
    			throw new Exception("Function <strong>{$reroute[$name]}</strong> does not exist.\n");
    		}

    	}else{
    		throw new Exception("Function <strong>$name</strong> does not exist.\n");
    	}

    }

    function hooked_function($one = "", $two = ""){

    	echo "{$this->value} $one $two";

    }

}

$hooked = new hooked();

$hooked->_hooked_function("is", "hooked. ");
// Echo's: "your function is hooked."
$hooked->rerouted("is", "rerouted.");
// Echo's: "our function is rerouted."

?>