Jan*_*sen 329 php constructor multiple-constructors
您不能在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.
}
}
Run Code Online (Sandbox Code Playgroud)
在PHP中执行此操作的最佳方法是什么?
Kri*_*ris 454
我可能会这样做:
<?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
}
}
?>
Run Code Online (Sandbox Code Playgroud)
然后,如果我想要一个我知道ID的学生:
$student = Student::withID( $id );
Run Code Online (Sandbox Code Playgroud)
或者,如果我有一个db行数组:
$student = Student::withRow( $row );
Run Code Online (Sandbox Code Playgroud)
从技术上讲,你不是构建多个构造函数,只是静态辅助方法,但是你可以通过这种方式避免构造函数中的大量意大利面条代码.
tim*_*hew 82
Kris的解决方案非常好,但我发现工厂和流畅的风格更好:
<?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);
?>
Run Code Online (Sandbox Code Playgroud)
Daf*_*aff 41
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.
}
}
Run Code Online (Sandbox Code Playgroud)
Bjö*_*örn 22
public function __construct() {
$parameters = func_get_args();
...
}
$o = new MyClass('One', 'Two', 3);
Run Code Online (Sandbox Code Playgroud)
现在$ paramters将是一个值为'One','Two',3的数组.
编辑,
我可以补充一点
func_num_args()
Run Code Online (Sandbox Code Playgroud)
将为您提供该功能的参数数量.
Nas*_*jim 17
正如这里已经显示的那样,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.');
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.:)
yan*_*nis 15
从版本5.4开始,PHP支持特征.这不是您正在寻找的,但基于特征的简单方法将是:
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); }
}
Run Code Online (Sandbox Code Playgroud)
我们最终得到两个类,每个构造函数一个,这有点适得其反.为了保持一定的理智,我会投入工厂:
class StudentFactory {
static public function getStudent($id, $name = null) {
return
is_null($name)
? new Student1($id)
: new Student2($id, $name)
}
}
Run Code Online (Sandbox Code Playgroud)
所以,这一切都归结为:
$student1 = StudentFactory::getStudent(1);
$student2 = StudentFactory::getStudent(1, "yannis");
Run Code Online (Sandbox Code Playgroud)
这是一种非常冗长的方法,但它可以非常方便.
And*_*c ॐ 13
你可以这样做:
public function __construct($param)
{
if(is_int($param)) {
$this->id = $param;
} elseif(is_object($param)) {
// do something else
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个优雅的方法来做到这一点。创建特征,在给定参数数量的情况下启用多个构造函数。您只需将参数数量添加到函数名称“__construct”。所以一个参数将是“__construct1”,两个“__construct2”......等等。
trait constructable
{
public function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this,$f='__construct'.$i)) {
call_user_func_array([$this,$f],$a);
}
}
}
class a{
use constructable;
public $result;
public function __construct1($a){
$this->result = $a;
}
public function __construct2($a, $b){
$this->result = $a + $b;
}
}
echo (new a(1))->result; // 1
echo (new a(1,2))->result; // 3
Run Code Online (Sandbox Code Playgroud)
另一种选择是像这样在构造函数中使用默认参数
class Student {
private $id;
private $name;
//...
public function __construct($id, $row=array()) {
$this->id = $id;
foreach($row as $key => $value) $this->$key = $value;
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着您需要使用这样的行实例化:$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));
}
}
Run Code Online (Sandbox Code Playgroud)