本文要点
object
。PHP快成为一种被遗忘的语言了,自2004年PHP 5.0发布之后,十多年没有一个新的大版本。更糟糕的是,PHP 6.x被放弃是因为计划向PHP添加原生Unicode支持却无法实现。
PHP 7.0是一个大版本,增加了一些改进和新特性。7.0中有一些比较显著的新特性,包括:字符串、整数、浮点数和布尔值的标量类型声明;返回类型声明;用于数组常量的新函数define()
;匿名类。该版本还添加了一些特性来改进Unicode支持,包括IntlChar
类和Unicode代码点转义语法。
此外,PHP 7还添加了增强assert()
函数的期望(expectations ),而生成器返回函数和生成器委托改进了生成器的功能。随后的小版本,从PHP 7.1到PHP 7.4,还增加了其他新特性。
在本系列文章中,我们将讨论PHP 7.x版本中的各种新特性。但首先,让我们探讨一下为什么使用PHP 7。
简单来说,PHP 7让PHP达到了其他现代语言的水平。
下面是使用PHP 7其中一些最重要的原因:
当更新PHP的版本时,WordPress建议更新到推荐的PHP 7.3版本。PHP内部团队做得很棒,他们让最新版本成为PHP迄今为止最快的版本。这意味着更新将提高你网站的速度,对你和你的访问者而言都是如此。
要测试或运行本文提供的示例脚本,请下载并安装PHP 7的最新版本(PHP 7.4)。平台不同,下载的二进制文件和安装步骤也会有些差异,因此,请参阅官方PHP文档。不要忘记将安装根目录,例如C:\PHP7.4\php-7.4-ts-windows-vc15-x64-r6c9821a
添加到PATH
环境变量中。将php.ini-production
或php.ini-development
重命名为php.ini
。要使用/ext
目录中的扩展,请在php.ini
中设置extension_dir
指令:
extension_dir = "./ext"
使用下面的命令启动内置服务器:
php -S localhost:8000
在根目录(即安装目录,例如,C:\PHP7\php-7.3.0-Win32-VC15-x64
)的scripts
子目录中添加要运行的所有脚本。可以使用php.ini
中的doc_root
指令将根目录设置为不同的路径。要重用本示例中的PHP脚本,请单独保存它们,而不是将每个脚本作为test.php
测试/运行。
PHP 7.2引入了有限协变和逆变。协变是指子类的方法能够返回更具体的返回类型。逆变是指子类的方法接受不那么具体的参数类型。更具体/不那么具体是在超/子类的上下文中定义的,子类是更具体的。一个类扩展另一个类可以重写其方法,同时仍然保持逆变(对于参数类型)和协变(对于返回类型)。
PHP 7.2仅提供对协变和逆变的有限支持,这意味着只支持没有提供类型的情况。具体来说,可以在重写超类中不存在返回类型的函数时定义返回类型,而在重写超类中存在参数的函数时省略参数类型。
例如,创建一个脚本,声明一个只有一个函数fn1
的类A
,创建另一个类B
,继承类A
并重写其fn1
函数。
在重写后的函数fn1
中,参数类型被删除了,默认成了mixed
类型,该参数类型比类A
中的类型B
更宽泛。在重写后的方法中删除参数类型,而不管类是否是抽象的,这是PHP 7的另一项新特性。
重写后的fn1
方法返回类型是A
,其范围要比类A
中的mixed
类型窄。以下是代码:
<?php
class A {
function fn1(B $b) {}
}
class B extends A {
function fn1($b): A{}
}
PHP 7.2新增了一个类型object
,该类型可以用作参数类型和返回类型。所有类类型的实例都是对象。为了演示如何使用object
作为参数类型和返回类型,在文档根目录下的scripts
目录中创建一个脚本object.php
,并声明两个类ClassA
和ClassB
,每个类都定义 一个hello()
函数,该函数回显字符串消息。接下来,向脚本本身添加hello()
函数,参数类型和返回类型都是object
。直接在脚本中添加的hello()
函数返回类ClassB
的一个实例:
function hello(object $obj) : object
{
return new ClassB();
}
使用ClassA
类的实例作为参数调用该函数,并在返回的对象上调用hello()
函数。
hello(new ClassA())->hello();
The object.php is listed:
<?php
Class ClassA{
function hello()
{
echo "Hello from ClassA";
}}
class ClassB{
function hello()
{
echo "Hello from ClassB";
}}
function hello(object $obj) : object
{
return new ClassB();
}
hello(new ClassA())->hello();
?>
使用URL http://localhost:8000/scripts/object.php运行脚本,输出如下:
Hello from ClassB
由于这是我们运行的第一个示例脚本,所以我们把它在浏览器中的输出截了图,如下所示:
图1:object.php的输出
object
类型本身并不代表一个类;它只是一个类型。如果object
之外的任何类型转化为objec
,就会创建内置类stdClass
的一个实例。
数组可以强制转换为对象类型object
,生成的对象具有名称类似数组键的属性。为了演示如何将数组转换为对象以及几项有用的相关任务,请创建object_array.php
脚本并通过强制转换为object
来声明对象。
$obj = (object) array('journal' => 'Oracle Magazine', 'publisher' => 'Oracle Publishing','edition' => 'January February 2018');
现在,可以使用命名键来输出对象属性了。
echo $obj->{'journal'};
echo $obj->{'publisher'};
echo $obj->{'edition'};
bool isset (mixed$var [,mixed$... ])
函数可以用于检查属性是否已经像下面这样设置:
var_dump(isset($obj->{'journal'}));
使用mixedkey ( array $array)
函数输出一个对象键。
var_dump(key($obj));
使用mixed next ( array &$array)
前移内部数组指针。
next($obj);
调用isset
和key
函数获取下一个数组元素。按顺序重复调用next
、isset
和key
函数获取下一个元素。可以直接访问对象成员变量来输出它们的值。
echo $obj->journal;
echo $obj->publisher;
echo $obj->edition;
检查从数组转换而来的对象是否是stdClass
的实例。
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
}
字符串可以强制转换为object
。转换后的对象的值可以使用成员变量scalar
访问。检查转换后的对象是否为stdClass
的实例。
$obj = (object) 'hello';
echo $obj->scalar;
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
}
以下是object_array.php
脚本的内容:
<?php
$obj = (object) array('journal' => 'Oracle Magazine', 'publisher' => 'Oracle Publishing','edition' => 'January February 2018');
echo $obj->{'journal'};
echo "<br/>";
echo $obj->{'publisher'};
echo "<br/>";
echo $obj->{'edition'};
echo "<br/>";
var_dump(isset($obj->{'journal'}));
echo "<br/>";
var_dump(key($obj));
next($obj);
echo "<br/>";
var_dump(isset($obj->{'publisher'}));
echo "<br/>";
var_dump(key($obj));
next($obj);
echo "<br/>";
var_dump(isset($obj->{'edition'}));
echo "<br/>";
var_dump(key($obj));
echo "<br/>";
echo $obj->journal;
echo "<br/>";
echo $obj->publisher;
echo "<br/>";
echo $obj->edition;
echo "<br/>";
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
echo "<br/>";
}
$obj = (object) 'hello';
echo $obj->scalar;
echo "<br/>";
if($obj instanceof stdClass){
echo '$obj is instance of built-in class stdClass';
}
?>
运行该脚本会输出以下内容:
Oracle Magazine
Oracle Publishing
January February 2018
bool(true)
string(7) "journal"
bool(true)
string(9) "publisher"
bool(true)
string(7) "edition"
Oracle Magazine
Oracle Publishing
January February 2018
$obj is instance of built-in class stdClass
hello
$obj is instance of built-in class stdClass
不仅可以将数组和字符串转换为对象,还可以将任何类型的值转换为对象,包括int
、float
和bool
。例如,将int
转换为object
,输出其scalar
值,然后用接下来的脚本检查转换后的对象是否为stdClass
的实例:
<?php
$obj = (object) 1;
echo $obj->scalar;
echo "<br/>";
if($obj instanceof stdClass){
echo '$obj is instance of built-in class StdClass';
}?>
输出如下:
1
$obj is instance of built-in class stdClass
类的实例是对象而不是stdClass
的实例,将它们转换为object
不会使它们成为stdClass
的实例。为了演示这一点,我们创建一个名为object_instance_of.php
的脚本。然后声明一个类并实例化它。下面的脚本将展示如何确定一个类的实例是否是stdClass
的实例;接下来,该脚本会将类的实例强制转换为object
,并确定转换后的对象是否是stdClass
的实例。object_instance_of.php
脚本如下所示:
<?php
Class A{}
$A = new A;
echo '<br/>';
if ($A instanceof stdClass) {
echo '$A is instance of built-in class stdClass'; }
else{
echo '$A is not instance of built-in class stdClass';
}
echo '<br/>';
echo '<br/>';
$AObj = (object)$A;
if ($AObj instanceof stdClass) {
echo '$AObj is instance of built-in class stdClass';
}else{ echo '$AObj is not instance of built-in class stdClass';
}
echo '<br/>';
?>
以下是该脚本的输出:
$A is not instance of built-in class stdClass
$AObj is not instance of built-in class stdClass
命名类或匿名类的实例已经是object
,将其强制转换为object
不会改变其类型。空数组和NULL
值也可以转换为object
。如前所述,stdClass
是默认的PHP对象,当将标量、数组和NULL
强制转换为object
时,将创建stdClass
的一个实例。匿名类object
、从空数组创建的object
、从NULL
创建的object
或没有函数或变量的类都不会被认为是空的,将empty()
应用于它们中的任何一个都不会返回TRUE
。empty()
函数的作用是:仅当变量或对象不存在或它的值为FALSE
时才返回TRUE
。
如果你想测试一下,可以创建一个脚本文件object_empty.php
,并将下面的代码粘贴进去:
<?php
$obj1 = (object)(new class{}); // 实例化匿名类
$obj2 = (object)[]; // 将空数组转换为对象
class A{}
$A=new A(); // 空类的实例
var_dump($A);
echo "<br/>";
var_dump($obj1);
echo "<br/>";
var_dump($obj2);
echo "<br/>";
echo empty ($obj1);
echo "<br/>";
$obj1=NULL;
$obj3=(object)$obj1;// NULL转换为对象
var_dump($obj3);
echo "<br/>";
echo empty ($A);
echo "<br/>";
echo empty ($obj2);
echo "<br/>";
echo empty ($obj3);
?>
该脚本创建了每一种匿名类的对象:从空数组创建的对象,从NULL
创建的对象,以及没有函数或变量的类对象。运行该脚本将生成以下输出。
object(A)#3 (0) { }
object(class@anonymous)#1 (0) { }
object(stdClass)#2 (0) { };
object(stdClass)#1 (0) { }
object
类型可以用于参数类型的逆变(放宽)和返回类型的协变(缩窄)。
<?php
class A{
public function fn(object $obj) {
}
}
class B extends A{
public function fn($obj) : object {
}
}
我们已经讨论了PHP 7.2对有限协变的支持,它支持向扩展类中的方法添加返回类型,即使在超类中没有声明任何返回类型。我们还讨论了对有限逆变的支持,它允许在扩展类中不指定方法参数的类型。
PHP 7.4添加了对协变和逆变的完全支持。完全支持允许开发人员使用不那具体的参数类型和更具体的返回类型,这意味着参数类型可以用它的超类型替换,而返回类型可以用子类型替换。回想一下,PHP 7.2中对协变和逆变的支持仅限于无类型。在下面的脚本中,ClassB
继承了ClassA
,ClassD
继承了ClassC
。与ClassC
相比,ClassD
中的函数fn1
声明了一个不那么具体的参数类型和一个更具体的返回类型。
<?php
class ClassA {}
class ClassB extends ClassA {}
class ClassC {
public function fn1(ClassB $b): ClassA {}
}
class ClassD extends ClassC {
public function fn1(ClassA $a): ClassB {}
}
?>
以下是全变型支持的部分特性:
object
类型变型;callable
类型变型;在本系列的下一篇文章中,我们将讨论PHP 7.x中类和接口的新特性。
作者简介:
Deepak Vohra是Sun认证Java程序员和Web组件开发人员。他一直在WebLogic Developer’s Journal、XML Journal、ONJava、java.net、IBM developerWorks、Java Developer’s Journal、Oracle Magazine和devx上发表与Java和Java EE相关的技术文章。Deepak还是一名Docker导师,已出版了五本关于Docker的著作。Deepak还发表了多篇关于PHP的文章,并出版了一本著作Ruby on Rails for PHP and Java Developers。
原文链接:
领取专属 10元无门槛券
私享最新 技术干货