你不能在一个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中最好的方法是什么?
我知道我在这方面非常晚,但我提出了一个相当灵活的模式,应该允许一些真正有趣和通用的实现。
像往常一样设置类,使用您喜欢的任何变量。
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 5.6构建)。
它将查看构造函数参数类型(数组,类名,无描述)并比较给定的参数。构造函数必须在最后以最少的特异性给出。例子:
// demo class
class X {
public $X;
public function __construct($x) {
$this->X = $x;
}
public function __toString() {
return 'X'.$this->X;
}
}
// demo class
class Y {
public $Y;
public function __construct($y) {
$this->Y = $y;
}
public function __toString() {
return 'Y'.$this->Y;
}
}
// here be magic
abstract class MultipleConstructors {
function __construct() {
$__get_arguments = func_get_args();
$__number_of_arguments = func_num_args();
$__reflect = new ReflectionClass($this);
foreach($__reflect->getMethods() as $__reflectmethod) {
$__method_name = $__reflectmethod->getName();
if (substr($__method_name, 0, strlen('__construct')) === '__construct') {
$__parms = $__reflectmethod->getParameters();
if (count($__parms) == $__number_of_arguments) {
$__argsFit = true;
foreach ($__parms as $__argPos => $__param) {
$__paramClass= $__param->getClass();
$__argVar = func_get_arg($__argPos);
$__argVarType = gettype($__argVar);
$__paramIsArray = $__param->isArray() == true;
$__argVarIsArray = $__argVarType == 'array';
// parameter is array and argument isn't, or the other way around.
if (($__paramIsArray && !$__argVarIsArray) ||
(!$__paramIsArray && $__argVarIsArray)) {
$__argsFit = false;
continue;
}
// class check
if ((!is_null($__paramClass) && $__argVarType != 'object') ||
(is_null($__paramClass) && $__argVarType == 'object')){
$__argsFit = false;
continue;
}
if (!is_null($__paramClass) && $__argVarType == 'object') {
// class type check
$__paramClassName = "N/A";
if ($__paramClass)
$__paramClassName = $__paramClass->getName();
if ($__paramClassName != get_class($__argVar)) {
$__argsFit = false;
}
}
}
if ($__argsFit) {
call_user_func_array(array($this, $__method_name), $__get_arguments);
return;
}
}
}
}
throw new Exception("No matching constructors");
}
}
// how to use multiple constructors
class A extends MultipleConstructors {
public $value;
function __constructB(array $hey) {
$this->value = 'Array#'.count($hey).'<br/>';
}
function __construct1(X $first) {
$this->value = $first .'<br/>';
}
function __construct2(Y $second) {
$this->value = $second .'<br/>';
}
function __constructA($hey) {
$this->value = $hey.'<br/>';
}
function __toString() {
return $this->value;
}
}
$x = new X("foo");
$y = new Y("bar");
$aa = new A(array("one", "two", "three"));
echo $aa;
$ar = new A("baz");
echo $ar;
$ax = new A($x);
echo $ax;
$ay = new A($y);
echo $ay;
结果:
Array#3
baz
Xfoo
Ybar
如果没有找到构造函数,可以将其删除并允许构造函数为“空”,而不是终止异常。或者你喜欢什么都行。
让我在这里加一粒沙子
我个人喜欢将构造函数作为返回类(对象)实例的静态函数添加。代码示例如下:
class Person
{
private $name;
private $email;
public static function withName($name)
{
$person = new Person();
$person->name = $name;
return $person;
}
public static function withEmail($email)
{
$person = new Person();
$person->email = $email;
return $person;
}
}
注意,现在你可以像这样创建Person类的实例:
$person1 = Person::withName('Example');
$person2 = Person::withEmail('yo@mi_email.com');
我的代码来自:
http://alfonsojimenez.com/post/30377422731/multiple-constructors-in-php
这个问题已经用非常聪明的方法回答了,但我想知道为什么不退一步,问一个基本的问题,为什么我们需要一个有两个构造函数的类?
如果我的类需要两个构造函数,那么我设计类的方式可能需要更多的考虑,以提出一个更干净、更可测试的设计。
我们正在尝试混合如何实例化一个类与实际的类逻辑。
如果一个学生对象是在一个有效的状态,那么它是否从一个DB或从一个web表单或cli请求的数据行构造?
现在回答这个问题,可能出现的,如果我们不添加从db行创建一个对象的逻辑,那么我们如何创建一个对象从数据库数据,我们可以简单地添加另一个类,称之为StudentMapper如果你熟悉数据映射模式,在某些情况下,您可以使用StudentRepository,如果没有适合你的需要你可以StudentFactory处理所有类型的对象建设任务。
当我们在处理领域对象时,底线是不要考虑持久化层。