你不能在一个PHP类中放入两个具有唯一参数签名的__construct函数。我想这样做:

class Student 
{
   protected $id;
   protected $name;
   // etc.

   public function __construct($id){
       $this->id = $id;
      // other members are still uninitialized
   }

   public function __construct($row_from_database){
       $this->id = $row_from_database->id;
       $this->name = $row_from_database->name;
       // etc.
   }
}

PHP中最好的方法是什么?


当前回答

我创建这个方法是为了让它不仅在构造函数中使用,而且在方法中使用:

我的构造函数:

function __construct() {
    $paramsNumber=func_num_args();
    if($paramsNumber==0){
        //do something
    }else{
        $this->overload('__construct',func_get_args());
    }
}

我的doSomething方法:

public function doSomething() {
    $paramsNumber=func_num_args();
    if($paramsNumber==0){
        //do something
    }else{
        $this->overload('doSomething',func_get_args());
    }
}

两者都使用这个简单的方法:

public function overloadMethod($methodName,$params){
    $paramsNumber=sizeof($params);
    //methodName1(), methodName2()...
    $methodNameNumber =$methodName.$paramsNumber;
    if (method_exists($this,$methodNameNumber)) {
        call_user_func_array(array($this,$methodNameNumber),$params);
    }
}

所以你可以声明

__construct1($arg1), __construct2($arg1,$arg2)...

or

methodName1($arg1), methodName2($arg1,$arg2)...

等等。

使用时:

$myObject =  new MyClass($arg1, $arg2,..., $argN);

它将调用__constructN,在那里你定义了N个参数

然后 $myObject -> doSomething($arg1, $arg2,..), argM美元)

它会调用doSomethingM,在这里你定义了M个参数;

其他回答

你可以像下面这样做,非常简单明了:

public function __construct()    
{
   $arguments = func_get_args(); 

   switch(sizeof(func_get_args()))      
   {
    case 0: //No arguments
        break; 
    case 1: //One argument
        $this->do_something($arguments[0]); 
        break;              
    case 2:  //Two arguments
        $this->do_something_else($arguments[0], $arguments[1]); 
        break;            
   }
}

按数据类型调用构造函数:

class A 
{ 
    function __construct($argument)
    { 
       $type = gettype($argument);

       if($type == 'unknown type')
       {
            // type unknown
       }

       $this->{'__construct_'.$type}($argument);
    } 

    function __construct_boolean($argument) 
    { 
        // do something
    }
    function __construct_integer($argument) 
    { 
        // do something
    }
    function __construct_double($argument) 
    { 
        // do something
    }
    function __construct_string($argument) 
    { 
        // do something
    }
    function __construct_array($argument) 
    { 
        // do something
    }
    function __construct_object($argument) 
    { 
        // do something
    }
    function __construct_resource($argument) 
    { 
        // do something
    }

    // other functions

} 

在创建具有不同签名的多个构造函数时,我也面临着同样的问题,但不幸的是,PHP没有提供直接的方法来这样做。然而,我发现了一个技巧来克服它。希望也适用于你们所有人。

    <?PHP

    class Animal
    {

      public function __construct()
      {
        $arguments = func_get_args();
        $numberOfArguments = func_num_args();

        if (method_exists($this, $function = '__construct'.$numberOfArguments)) {
            call_user_func_array(array($this, $function), $arguments);
        }
    }
   
    public function __construct1($a1)
    {
        echo('__construct with 1 param called: '.$a1.PHP_EOL);
    }
   
    public function __construct2($a1, $a2)
    {
        echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
    }
   
    public function __construct3($a1, $a2, $a3)
    {
        echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
    }
}

$o = new Animal('sheep');
$o = new Animal('sheep','cat');
$o = new Animal('sheep','cat','dog');

// __construct with 1 param called: sheep
// __construct with 2 params called: sheep,cat
// __construct with 3 params called: sheep,cat,dog

我知道我在这方面非常晚,但我提出了一个相当灵活的模式,应该允许一些真正有趣和通用的实现。

像往常一样设置类,使用您喜欢的任何变量。

class MyClass{ protected $myVar1; protected $myVar2; public function __construct($obj = null){ if($obj){ foreach (((object)$obj) as $key => $value) { if(isset($value) && in_array($key, array_keys(get_object_vars($this)))){ $this->$key = $value; } } } } } When you make your object just pass an associative array with the keys of the array the same as the names of your vars, like so... $sample_variable = new MyClass([ 'myVar2'=>123, 'i_dont_want_this_one'=> 'This won\'t make it into the class' ]); print_r($sample_variable); The print_r($sample_variable); after this instantiation yields the following: MyClass Object ( [myVar1:protected] => [myVar2:protected] => 123 ) Because we've initialize $group to null in our __construct(...), it is also valid to pass nothing whatsoever into the constructor as well, like so... $sample_variable = new MyClass(); print_r($sample_variable); Now the output is exactly as expected: MyClass Object ( [myVar1:protected] => [myVar2:protected] => ) The reason I wrote this was so that I could directly pass the output of json_decode(...) to my constructor, and not worry about it too much. This was executed in PHP 7.1. Enjoy!

我可能会这样做:

<?php

class Student
{
    public function __construct() {
        // allocate your stuff
    }

    public static function withID( $id ) {
        $instance = new self();
        $instance->loadByID( $id );
        return $instance;
    }

    public static function withRow( array $row ) {
        $instance = new self();
        $instance->fill( $row );
        return $instance;
    }

    protected function loadByID( $id ) {
        // do query
        $row = my_awesome_db_access_stuff( $id );
        $this->fill( $row );
    }

    protected function fill( array $row ) {
        // fill all properties from array
    }
}

?>

然后,如果我想要一个学生,我知道ID:

$student = Student::withID( $id );

或者如果我有一个db行数组:

$student = Student::withRow( $row );

从技术上讲,您不需要构建多个构造函数,而只是静态帮助方法,但是这样可以避免构造函数中的大量意大利面条代码。