在 PHP 中执行多个构造函数的最佳方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1699796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to do multiple constructors in PHP
提问by Jannie Theunissen
You can't put two __construct functions with unique argument signatures in a PHP class. I'd like to do this:
您不能在 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.
}
}
What is the best way to do this in PHP?
在 PHP 中执行此操作的最佳方法是什么?
回答by Kris
I'd probably do something like this:
我可能会做这样的事情:
<?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
}
}
?>
Then if i want a Student where i know the ID:
然后,如果我想要一个我知道 ID 的学生:
$student = Student::withID( $id );
Or if i have an array of the db row:
或者,如果我有一个 db 行数组:
$student = Student::withRow( $row );
Technically you're not building multiple constructors, just static helper methods, but you get to avoid a lot of spaghetti code in the constructor this way.
从技术上讲,您不是在构建多个构造函数,只是在构建静态辅助方法,但是您可以通过这种方式避免在构造函数中使用大量意大利面条式代码。
回答by timaschew
Solution of Kris is really nice, but I find the mix of factory and fluent style better:
Kris 的解决方案真的很好,但我发现工厂和 fluent 风格的组合更好:
<?php
class Student
{
protected $firstName;
protected $lastName;
// etc.
/**
* Constructor
*/
public function __construct() {
// allocate your stuff
}
/**
* Static constructor / factory
*/
public static function create() {
$instance = new self();
return $instance;
}
/**
* FirstName setter - fluent style
*/
public function setFirstName( $firstName) {
$this->firstName = $firstName;
return $this;
}
/**
* LastName setter - fluent style
*/
public function setLastName( $lastName) {
$this->lastName = $lastName;
return $this;
}
}
// create instance
$student= Student::create()->setFirstName("John")->setLastName("Doe");
// see result
var_dump($student);
?>
回答by Daff
PHP is a dynamic language, so you can't overload methods. You have to check the types of your argument like this:
PHP 是一种动态语言,因此您不能重载方法。您必须像这样检查参数的类型:
class Student
{
protected $id;
protected $name;
// etc.
public function __construct($idOrRow){
if(is_int($idOrRow))
{
$this->id = $idOrRow;
// other members are still uninitialized
}
else if(is_array($idOrRow))
{
$this->id = $idOrRow->id;
$this->name = $idOrRow->name;
// etc.
}
}
回答by Bj?rn
public function __construct() {
$parameters = func_get_args();
...
}
$o = new MyClass('One', 'Two', 3);
Now $paramters will be an array with the values 'One', 'Two', 3.
现在 $paramters 将是一个值为 'One', 'Two', 3 的数组。
Edit,
编辑,
I can add that
我可以补充一点
func_num_args()
will give you the number of parameters to the function.
将为您提供该函数的参数数量。
回答by Nasif Md. Tanjim
As has already been shown here, there are many ways of declaring multipleconstructors in PHP, but none of them are the correctway of doing so (since PHP technically doesn't allow it).
But it doesn't stop us from hacking this functionality...
Here's another example:
正如这里已经展示的那样,multiple在 PHP 中有很多声明构造函数的方法,但没有correct一种方法是这样做的(因为 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.');
Source:The easiest way to use and understand multiple constructors:
Hope this helps. :)
希望这可以帮助。:)
回答by yannis
As of version 5.4, PHP supports traits. This is notexactly what you are looking for, but a simplistic trait based approach would be:
从 5.4 版本开始,PHP 支持traits。这并不完全是您要寻找的,但基于简单特征的方法是:
trait StudentTrait {
protected $id;
protected $name;
final public function setId($id) {
$this->id = $id;
return $this;
}
final public function getId() { return $this->id; }
final public function setName($name) {
$this->name = $name;
return $this;
}
final public function getName() { return $this->name; }
}
class Student1 {
use StudentTrait;
final public function __construct($id) { $this->setId($id); }
}
class Student2 {
use StudentTrait;
final public function __construct($id, $name) { $this->setId($id)->setName($name); }
}
We end up with two classes, one for each constructor, which is a bit counter-productive. To maintain some sanity, I'll throw in a factory:
我们最终得到两个类,一个用于每个构造函数,这有点适得其反。为了保持理智,我将投入一个工厂:
class StudentFactory {
static public function getStudent($id, $name = null) {
return
is_null($name)
? new Student1($id)
: new Student2($id, $name)
}
}
So, it all comes down to this:
所以,这一切都归结为:
$student1 = StudentFactory::getStudent(1);
$student2 = StudentFactory::getStudent(1, "yannis");
It's a horribly verbose approach, but it can be extremely convenient.
这是一种非常冗长的方法,但它可以非常方便。
回答by Andrei Serdeliuc ?
You could do something like this:
你可以这样做:
public function __construct($param)
{
if(is_int($param)) {
$this->id = $param;
} elseif(is_object($param)) {
// do something else
}
}
回答by rojoca
Another option is to use default arguments in the constructor like this
另一种选择是像这样在构造函数中使用默认参数
class Student {
private $id;
private $name;
//...
public function __construct($id, $row=array()) {
$this->id = $id;
foreach($row as $key => $value) $this->$key = $value;
}
}
This means you'll need to instantiate with a row like this: $student = new Student($row['id'], $row)but keeps your constructor nice and clean.
这意味着您需要使用这样的行实例化:$student = new Student($row['id'], $row)但要保持您的构造函数干净整洁。
On the other hand, if you want to make use of polymorphism then you can create two classes like so:
另一方面,如果你想利用多态,那么你可以像这样创建两个类:
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));
}
}
回答by gpilotino
as stated in the other comments, as php does not support overloading, usually the "type checking tricks" in constructor are avoided and the factory pattern is used intead
如其他评论中所述,由于 php 不支持重载,通常会避免构造函数中的“类型检查技巧”,而是使用工厂模式
ie.
IE。
$myObj = MyClass::factory('fromInteger', $params);
$myObj = MyClass::factory('fromRow', $params);
回答by paishin
You could do something like the following which is really easy and very clean:
您可以执行以下操作,这非常简单且非常干净:
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;
}
}

