PHP[OOP] - How to call class constructor manually?

前端 未结 6 481
时光取名叫无心
时光取名叫无心 2020-12-30 07:47

Please see the code bellow:

01. class Test {
02.     public function __construct($param1, $param2, $param3) {
03.         echo $param1.$para         


        
相关标签:
6条回答
  • 2020-12-30 07:56

    If separating instantiation from initialization isn't strictly a requirement, there are two other possibilities: first, a static factory method.

    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);
    }
    

    Or, if you're using php 5.3.0 or higher, you can use a lambda:

    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);
    }
    

    The initialization method described by Asaph is great if for some reason you have a need to logically separate initialization from instantiation, but if supporting your use case above is a special case, not a regular requirement, it can be inconvenient to require users to instantiate and initialize your object in two separate steps.

    The factory method is nice because it gives you a method to call to get an initialized instance. The object is initialized and instantiated in the same operation, though, so if you have a need to separate the two it won't work.

    And lastly, I recommend the lambda if this initialization mechanism is uncommonly used, and you don't want to clutter your class definition with initialization or factory methods that will hardly ever be used.

    0 讨论(0)
  • 2020-12-30 07:58

    to construct your object first and then pass parameters your could try this way:

    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
        }
    }
    

    then it is possible to construct the object and call

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

    later.

    0 讨论(0)
  • 2020-12-30 08:03

    I don't know if there are some security concerns by using the eval() method, but you could make yourself a function like this:

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

    And now $ob should now be defined with its correct parameters, i haven't tested it and maybe there is a mistake in the code, but you get the idea....

    0 讨论(0)
  • 2020-12-30 08:10

    It is not possible to prevent the constructor from being called when the object is constructed (line 9 in your code). If there is some functionality that happens in your __construct() method that you wish to postpone until after construction, you should move it to another method. A good name for that method might be init().

    Why not just do this?

    class Test {
        public function __construct($param1, $param2, $param3) {
            echo $param1.$param2.$param3;
        }
    }
    
    $ob = new Test('p1', 'p2', 'p3');
    

    EDIT: I just thought of a hacky way you could prevent a constructor from being called (sort of). You could subclass Test and override the constructor with an empty, do-nothing constructor.

    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');
    

    This is might make sense if you're dealing with some code that you cannot change for some reason and need to work around some annoying behavior of a poorly written constructor.

    0 讨论(0)
  • 2020-12-30 08:13

    In PHP you can create objects w/o calling the constructor. But that does not work by using new but by un-serializing an object instance.

    The constructor can then be called manually.

    Normally this is not needed. See as well: 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();
    
    0 讨论(0)
  • 2020-12-30 08:14

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

    call_user_func_array
    

    will fail with an error.

    I suggest you to use Reflection class instead; here is how you can do so:

    // 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);
    
    0 讨论(0)
提交回复
热议问题