在这篇文章中,我们将讨论PHP中构造函数的基础知识。你将了解到PHP构造函数的目的以及如何使用它们。
什么是构造函数?
下面是官方的定义。
构造函数是普通的方法,在其相应对象的实例化过程中被调用。因此,它们可以定义任意数量的参数,这些参数可能是必需的,可能有一个类型,也可能有一个默认值。构造函数参数的调用方法是将参数放在类名后面的圆括号中。PHP手册。构造函数和析构函数
当你实例化一个任何类的对象时,如果该类已经定义了构造函数方法,它将被自动调用。如果构造函数方法定义了任何强制性的参数,那么当你实例化该类的对象时,也必须传递这些参数。
让我们快速看看PHP中的构造方法是什么样子的。
<?php
class tutsplus {
public function __construct()
{
// you can initialize object properties here
echo 'Hey, you have just instantiated a new object!';
}
}
$objTutsplus = new tutsplus();
// output: Hey, you have just instantiated a new object!
?>
所以这就是你如何在你的类中定义一个构造函数。你必须在你的类中定义__construct 方法,然后它就成为你的类的构造方法。在上面的例子中,每当你实例化tutsplus 对象时,__construct 方法将被首先调用。需要注意的是,你必须把构造方法定义为public,否则你将无法实例化你的类的对象!
在PHP 5之前,要定义一个构造函数,可以使用一个与它所定义的类同名的函数,它将被当作一个构造方法来处理你可能在其他编程语言如C++中熟悉这种声明构造函数的方式。在PHP中,它们被称为PHP4风格的构造函数,我们不建议使用这种风格,因为它们迟早会被废弃。
让我们修改一下前面的例子,看看构造函数在以前版本的PHP中会是什么样子。
<?php
class tutsplus {
public function tutsplus()
{
// you can initialize object properties here
echo 'Hey, you have just instantiated a new object!';
}
}
$objTutsplus = new tutsplus();
// output: Hey, you have just instantiated a new object!
?>
在写这篇文章的时候,这个例子仍然有效。试试吧!
构造函数的目的是什么?
现在你知道了如何在PHP中声明一个构造方法,但构造方法的用途是什么?这就是我们将在本节中通过几个真实的例子来讨论的。
初始化必要的属性
构造函数方法的主要目的是在创建对象时初始化对象的属性。这种方法的好处是,你不必在创建对象后再调用setter方法来初始化对象的属性。因此,如果你认为一个对象必须设置一些属性,那么构造函数方法就是最好的选择
让我们快速浏览一下下面的例子,了解它是如何工作的。
<?php
class tutsplusAuthor
{
private $author_name;
private $author_email;
public function __construct($name, $email)
{
$this->author_name = $name;
$this->author_email = $email;
}
public function getAuthorName()
{
return $this->author_name;
}
public function getAuthorEmail()
{
return $this->author_email;
}
}
$objTutsplusAuthor = new tutsplusAuthor("John", "john@tutsplus.com");
echo $objTutsplusAuthor->getAuthorName();
echo $objTutsplusAuthor->getAuthorEmail();
?>
如你所见,当tutsplusAuthor 对象被实例化时,__construct 方法被调用。__construct 方法期望有两个参数,我们在创建新对象时已经传递了这两个参数:new tutsplusAuthor("John", "john@tutsplus.com") 。最后,我们将author_name 和author_email 属性初始化为__construct 方法中传递的相应值。因此,通过这种方式,你可以用构造方法来初始化对象属性。
如果你试图在不传递任何参数的情况下实例化tutsplusAuthor 对象,你会得到一个致命的错误,如下面的片段所示。
<?php
// try to instantiate tutsplusAuthor without arguments
$objTutsplusAuthor = new tutsplusAuthor();
// output
// PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function tutsplusAuthor::__construct(), 0 passed in /public_html/examples/constructor.php on line 24 and exactly 2 expected in /public_html/examples/constructor.php
?>
所以你需要确保在实例化tutsplusAuthor 对象时传递任何必要的参数。
类型检查构造函数参数
事实上,如果你希望参数必须是特定的类型,你也可以进行类型检查。
<?php
class tutsplusAuthor
{
...
...
public function __construct(string $name, string $email, array $hobbies)
{
$this->author_name = $name;
$this->author_email = $email;
$this->hobbies = $hobbies;
}
...
...
}
在上面的例子中,你必须传递类型为string 的前两个参数,最后一个参数必须是类型为array 。如果你在最后一个参数中传递一个字符串值,你会得到以下错误。
PHP Fatal error: Uncaught TypeError: Argument 3 passed to tutsplusAuthor::__construct() must be of the type array, string given
所以这就是你如何对构造器参数进行严格的类型检查。
初始化一个数据库连接
构造函数的另一个用途是做一些I/O:例如,打开一个文件并开始读取其内容,开始一个API请求,或者创建一个数据库连接。
让我们来看看一个创建数据库连接的构造函数的例子。
<?php
class Database
{
private $host;
private $user;
private $password;
private $dbname;
private $connection;
public function __construct($host, $user, $password, $dbname)
{
$this->host=$host;
$this->user=$user;
$this->password=$password;
$this->dbname=$dbname;
$this->connection = mysqli_connect($this->host, $this->user, $this->password, $this->dbname);
if (!$this->connection) {
die("connection failed: " . mysqli_connect_error());
}
}
// other DBAL methods
}
?>
如何调用父类的构造函数?
在最后一节,我们将看到如何调用父类的构造函数。如果你知道继承的概念,你就会知道一个类可以扩展另一个类来建立其功能。
现在,有一种可能是子类和父类都有自己的构造函数。那么,当子类对象被实例化时,你如何调用父类的构造函数呢?
让我们试着用一个例子来理解它。
<?php
class Person
{
private $name;
public function __construct($name)
{
$this->name=$name;
}
}
class Employee extends Person
{
private $employee_id;
public function __construct($name, $employee_id)
{
parent::__construct($name);
$this->employee_id=$employee_id;
}
}
$obj=new Employee('John', 'J123');
?>
正如你所看到的,Employee 类扩展了Person 类。现在,当Employee 对象被实例化时,Employee 类的__construct() 方法被调用。在这个方法中,我们使用了特殊的parent 关键字来调用父类的__construct() 方法。因此,它最终会调用Person 类的__construct() 方法。如果你的类扩展了任何类,调用父类的__construct() 方法总是一个好的做法。
总结
今天,我们讨论了PHP中的构造函数以及一些真实世界的例子。你看到了如何创建一个构造函数,以及构造函数在PHP类中的一些使用情况。