PHP [OOP] - elle sınıf kurucusunu çağırmak nasıl?

6 Cevap php

Please see the code bellow:

01. class Test {
02.     public function __construct($param1, $param2, $param3) {
03.         echo $param1.$param2.$param3;
04.     }
05. }
06. 
07. $params = array('p1','p2','p3');
08. 
09. $ob = new Test;
10. 
11. if(method_exists($ob,'__construct')) {
12.     call_user_func_array(array($ob,'__construct'),$params);
13. }

Şimdi, sorunun constructor olduğu doğrultusunda 09 çağrılır

Ama hattında 11-13 at manually onu aramak istiyorum

Bu mümkün mü? O zaman nasıl olur? Herhangi bir idea, lütfen?

6 Cevap

Bu nesne (kodunuzda satır 9) inşa çağrılan olmaktan kurucu önlemek mümkün değildir. Eğer inşaat sonrasına kadar ertelemek isteyen sizin __construct() yöntem olur bazı işlevler varsa, başka bir yöntemle taşımak gerekir. Bu yöntem için iyi bir isim olabilir init().

Neden sadece bu yapmak değil mi?

class Test {
    public function __construct($param1, $param2, $param3) {
        echo $param1.$param2.$param3;
    }
}

$ob = new Test('p1', 'p2', 'p3');

EDIT: Ben sadece (çeşit) çağrılan bir kurucu engelleyebilecek bir hacky şekilde düşündüm. Sen Test alt sınıf ve boş, hiçbir şey yapmama kurucu ile kurucu geçersiz olabilir.

class SubTest extends Test {
    public function __construct() {
        // don't call parent::__construct()
    }

    public function init($param1, $param2, $param3) {
        parent::__construct($param1, $param2, $param3);
    }
}

$ob = new SubTest();
$ob->init('p1', 'p2', 'p3');

Bu size bir nedenle değiştirmek ve bir kötü yazılmış yapıcı bazı can sıkıcı davranışları etrafında çalışmak gerekmez bazı kod ile uğraşıyoruz eğer mantıklı olabilir olduğunu.

Note that if the constructor (__construct method) contains arguments passed by reference, then the function:

call_user_func_array

bir hata ile başarısız olur.

Ben yerine Yansıma sınıfını kullanmanızı öneririm; Burada bunu nasıl olduğunu:

// assuming that class file is already included.

$refMethod = new ReflectionMethod('class_name_here',  '__construct');
$params = $refMethod->getParameters();

$re_args = array();

foreach($params as $key => $param)
{
	if ($param->isPassedByReference())
	{
		$re_args[$key] = &$args[$key];
	}
	else
	{
		$re_args[$key] = $args[$key];
	}
}

$refClass = new ReflectionClass('class_name_here');
$class_instance = $refClass->newInstanceArgs((array) $re_args);

İlk, statik fabrika yöntemi: başlatma dan örneğinin ayıran kesinlikle bir gereklilik değilse, diğer iki olasılık vardır.

class Test {
    public function __construct($param1, $param2, $param3) {
        echo $param1.$param2.$param3;
    }

    public static function CreateTest($param1, $param2, $param3) {
        return new Test($param1, $param2, $param3);
    }
}

$params = array('p1','p2','p3');

if(method_exists($ob,'__construct')) {
    call_user_func_array(array($ob,'CreateTest'),$params);
}

Eğer php 5.3.0 veya daha yüksek kullanarak eğer Veya, bir lambda kullanabilirsiniz:

class Test {
    public function __construct($param1, $param2, $param3) {
        echo $param1.$param2.$param3;
    }
}

$params = array('p1','p2','p3');

$func = function ($arg1, $arg2, $arg3) {
    return new Test($arg1, $arg2, $arg3);
}

if(method_exists($ob,'__construct')) {
    call_user_func_array($func, $params);
}

Herhangi bir nedenle örnekleme mantıksal ayrı başlatma için bir ihtiyaç varsa Asaf tarafından açıklanan başlatma yöntemi harika ama yukarıdaki kullanım davayı destekleyen özel bir durum değil, normal bir gereklilik ise, kullanıcıların örneğini gerektiren için sakıncalı olabilir ve iki ayrı adımda nesnesi başlatılamıyor.

Size başlatılmış bir örneğini almak için aramak için bir yöntem verir çünkü fabrika yöntemi güzel. Nesne başlatıldı ve örneği aynı operasyonda olsa da, bu yüzden ikisini ayırmak için bir ihtiyaç varsa o iş olmaz edilmektedir.

Ve son olarak, ben bu başlatma mekanizması nadiren kullanılan eğer lambda tavsiye ve başlatma veya hemen hemen hiç kullanılacaktır fabrika yöntemleri ile sınıf tanımını yığılmayı istemiyorum.

Bazı güvenlik endişeleri eval () yöntemini kullanarak olup olmadığını bilmiyorum, ama kendinizi böyle bir fonksiyon yapabilir:

function CreateObj($className,$params)
{
    $strArgs = '$params['.implode('],$params[',array_keys($params)).']';
    eval('$ob = new '.$className.'('.$strArgs.');');
    return $ob
}

Ve şimdi $ ob şimdi onu test değil ve belki kodunda bir hata var, onun doğru parametreleri ile tanımlanmış olmalıdır, ama fikir olsun ....

PHP Eğer yapıcı arama w / o nesneleri oluşturabilirsiniz. Ama bu yeni kullanarak ancak bir nesne örneği un-serializing ile çalışmıyor.

Yapıcı sonra elle çağrılabilir.

Normal olarak, bu gerekli değildir. De bakınız: Loading an object from PHP session, does it call constructor?

<?php

class Test
{
    public function __construct()
    {
        echo '__construct called.',"\n";
    }
}

function old($class)
{
    return unserialize
    (
        sprintf
        (
            'O:%d:"%s":0:{}', 
            strlen($class), 
            $class
        )
    );
}

$test = old('Test');
$test->__construct();

ilk nesneyi oluşturmak ve sonra senin bu şekilde deneyebilirsiniz parametreleri geçirmek için:

class Test {
    public function __CONSTRUCT($p1="Bundy", $p2="house", $p3=10) {
        $this->init($p1, $p2, $p3);
    }
    public function init($p1, $p2, $p3) {
        //setup your object here
    }
}

o nesne oluşturmak ve çağırmak mümkün

$ob->init($p1, $p2, $p3);

daha sonra.