Please tell me how to properly overload using the __call method, the task is as follows: Create a class with several constructors, call constructors depending on the parameters passed

here is the code

<?php class BaseClass { //private $data = array(); private function construct1($color) { echo "1234"; } private function construct2($color, $qwerty) { echo "qwerty"; } private function construct3($color, $qwerty, $name) { echo "09876"; } public function __call(){ if (null === $qwerty) { $this->construct1($color); } elseif (null === $name) { $this->construct2(); } else { $this->construct3 ($color, $qwerty, $name); } } } function __destruct() { //$obj = new BaseClass(); } } $obj2 = new BaseClass("234567"); ?> 
  • one
    Создать класс с несколькими конструкторами - define the behavior directly in the __construct method, the magic __call does not work for it. - vp_arth
  • and then how to do otherwise, what would this magic __call work? they did it already in the way everything works but they require overloading with this method, unfortunately it doesn't work out - nika.brown09
  • Is it easier to use __construct(...$params) ? It will be possible to transfer any number of parameters to the constructor - ilyaplot
  • Do you want to use the __call magic method to create an object? Let's start with the fact that __call works in the context of an object and that the __call method starts working, you need to create an object using the usual constructor. - sscream
  • 2
    Tell me, where do you get all this task from? already in my third time published recently. - teran

3 answers 3

You have some kind of porridge. It looks like you just do not know that the arguments of the function can be given default parameters. In your case, the code might look like this.

 <?php class BaseClass { //private $data = array(); public function __construct($color, $qwerty = null, $name = null) { if ($qwerty === null && $name === null) { echo "09876"; } elseif ($qwerty === null) { echo "qwerty"; } else { echo "1234"; } } } 
  • I added, but I can not help but notice that this approach does not solve all the problems. For example, if you need to have two constructors, one of which accepts ($color,$qwerty) , and the second, for example, ($color,$name) - rjhdby
  • one
    @rjhdby why not decide. Just instead of the "unnecessary" parameter is passed null. PHP is not C ++ - there is no way to overload the method depending on the type of parameters. In this case, the author clearly has a mess in his head and in architecture. - newman
  • Because it is not a solution, but a crutch. As I understand it, the author wants an implementation like, for example, in Java - rjhdby
  • @rjhdby =) but what’s so complicated about the author’s problem? I brought the decision))) - Stanislav
  • @Stanislav here the question is not about complexity, but about the unrealizability in the form in which he wants. To a person accustomed to the same Java, at first, the PHP approach seems somewhat flawed. Well, PHP is not able to do several constructors :) - rjhdby

If you need to create an object depending on the input parameters, then there are three more or less correct paths:

  1. see answer newman
  2. Take advantage of the patterns of the factory method or builder . Here it is described how to implement them in PHP
  3. Pass as an argument an associative array with the necessary parameters

     $a = new BaseClass(["color"=>$color,"qwerty"=>$qwerty,...]) 

    If you are really interested in the ability to control with a dynamic number of parameters, then you can use either this way:

     class A { public function __construct(...$args) { switch (count($args)) { case 1: //use $args[0]; break; case 2: //use $args[0], $args[1]; break; case 3: //use $args[0], $args[1], $args[2]; break; } } } $a = new A('color', 'qwerty', 'color'); 

    or, as already given an example, transfer parameters in the array:

     class B { public function __construct($args) { switch (count($args)) { case 1: //use $args[0]; break; case 2: //use $args[0], $args[1]; break; case 3: //use $args[0], $args[1], $args[2]; break; } } } $b = new B(['123', '234']); class C { public function __construct($args) { if (!emtpy($args['color'])) { if (!empty($args['qwerty'])) { if (!empty($args['name'])) { //use [color, qwerty, name] } else { //use [color, qwerty] } } else { //use only [color] } } } } $c = new C(['color' => '123', 'qwerty' => '234']); 

    , or, if you want dynamic-predynamic at all, then something like this :

     class D { public function three($args) { print $args['color'].', '.$args['name']; } public function __construct($args) { $constructors = [ 'one' => ['color'], 'two' => ['color', 'qwerty'], 'three' => ['name', 'color'], 'four' => ['color', 'qwerty', 'name'] ]; foreach ($constructors as $key => $value) { sort($constructors[$key]); } $keys = array_keys($args); sort($keys); $constructor = array_search($keys, $constructors); if ($constructor!==false) { $this->{$constructor}($args); } else { print 'not found'; } } } $d = new D(['color' => 1, 'name' => 2]); 

    In my opinion, these are the most correct decisions.

    • @ nika.brown09 I added the answer to the class D, now in general the dynamics are the predynamics :) - Stanislav