你不能在一个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中最好的方法是什么?
对于php7,我也比较了参数类型,你可以有两个具有相同数量的参数但不同类型的构造函数。
trait GenericConstructorOverloadTrait
{
/**
* @var array Constructors metadata
*/
private static $constructorsCache;
/**
* Generic constructor
* GenericConstructorOverloadTrait constructor.
*/
public function __construct()
{
$params = func_get_args();
$numParams = func_num_args();
$finish = false;
if(!self::$constructorsCache){
$class = new \ReflectionClass($this);
$constructors = array_filter($class->getMethods(),
function (\ReflectionMethod $method) {
return preg_match("/\_\_construct[0-9]+/",$method->getName());
});
self::$constructorsCache = $constructors;
}
else{
$constructors = self::$constructorsCache;
}
foreach($constructors as $constructor){
$reflectionParams = $constructor->getParameters();
if(count($reflectionParams) != $numParams){
continue;
}
$matched = true;
for($i=0; $i< $numParams; $i++){
if($reflectionParams[$i]->hasType()){
$type = $reflectionParams[$i]->getType()->__toString();
}
if(
!(
!$reflectionParams[$i]->hasType() ||
($reflectionParams[$i]->hasType() &&
is_object($params[$i]) &&
$params[$i] instanceof $type) ||
($reflectionParams[$i]->hasType() &&
$reflectionParams[$i]->getType()->__toString() ==
gettype($params[$i]))
)
) {
$matched = false;
break;
}
}
if($matched){
call_user_func_array(array($this,$constructor->getName()),
$params);
$finish = true;
break;
}
}
unset($constructor);
if(!$finish){
throw new \InvalidArgumentException("Cannot match construct by params");
}
}
}
使用它:
class MultiConstructorClass{
use GenericConstructorOverloadTrait;
private $param1;
private $param2;
private $param3;
public function __construct1($param1, array $param2)
{
$this->param1 = $param1;
$this->param2 = $param2;
}
public function __construct2($param1, array $param2, \DateTime $param3)
{
$this->__construct1($param1, $param2);
$this->param3 = $param3;
}
/**
* @return \DateTime
*/
public function getParam3()
{
return $this->param3;
}
/**
* @return array
*/
public function getParam2()
{
return $this->param2;
}
/**
* @return mixed
*/
public function getParam1()
{
return $this->param1;
}
}
另一种选择是像这样在构造函数中使用默认参数
class Student {
private $id;
private $name;
//...
public function __construct($id, $row=array()) {
$this->id = $id;
foreach($row as $key => $value) $this->$key = $value;
}
}
这意味着你需要实例化一行像这样:$student = new student ($row['id'], $row),但保持你的构造函数漂亮和干净。
另一方面,如果你想利用多态性,那么你可以创建两个类,像这样:
class Student {
public function __construct($row) {
foreach($row as $key => $value) $this->$key = $value;
}
}
class EmptyStudent extends Student {
public function __construct($id) {
parent::__construct(array('id' => $id));
}
}
正如这里已经展示的,在PHP中有许多方法来声明多个构造函数,但是没有一种方法是正确的(因为PHP技术上不允许这样做)。
但这并不能阻止我们破解这个功能……
下面是另一个例子:
<?php
class myClass {
public function __construct() {
$get_arguments = func_get_args();
$number_of_arguments = func_num_args();
if (method_exists($this, $method_name = '__construct'.$number_of_arguments)) {
call_user_func_array(array($this, $method_name), $get_arguments);
}
}
public function __construct1($argument1) {
echo 'constructor with 1 parameter ' . $argument1 . "\n";
}
public function __construct2($argument1, $argument2) {
echo 'constructor with 2 parameter ' . $argument1 . ' ' . $argument2 . "\n";
}
public function __construct3($argument1, $argument2, $argument3) {
echo 'constructor with 3 parameter ' . $argument1 . ' ' . $argument2 . ' ' . $argument3 . "\n";
}
}
$object1 = new myClass('BUET');
$object2 = new myClass('BUET', 'is');
$object3 = new myClass('BUET', 'is', 'Best.');
使用和理解多个构造函数的最简单方法:
希望这能有所帮助。:)
在创建具有不同签名的多个构造函数时,我也面临着同样的问题,但不幸的是,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