PHP5.2 起,直至 PHP5.6 中增加的新特征
本文目录:
PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束
PHP5.2:JSON 支持
PHP5.3:弃用的功能,匿名函数,新增魔术方法,命名空间,后期静态绑定,Heredoc 和 Nowdoc, const, 三元运算符,Phar
PHP5.4:Short Open Tag, 数组简写形式,Traits, 内置 Web 服务器,细节修改
PHP5.5:yield, list() 用于 foreach, 细节修改
PHP5.6: 常量增强,可变函数参数,命名空间增强
一、PHP5.2以前(2006前)
顺便介绍一下 PHP5.2 已经出现但值得介绍的特征。
autoload
大家可能都知道 __autoload() 函数,如果定义了该函数,那么当在代码中使用一个未定义的类的时候,该函数就会被调用,你可以在该函数中加载相应的类实现文件,如:
复制代码 代码如下:
function __autoload(classname)
{
require_once(“{classname}.php”)
}
但 该函数已经不被建议使用,原因是一个项目中仅能有一个这样的 __autoload() 函数,因为 PHP 不允许函数重名。但当你使用一些类库的时候,难免会出现多个 autoload 函数的需要,于是 spl_autoload_register() 取而代之:
复制代码 代码如下:
spl_autoload_register(function(classname)
{
require_once(“{classname}.php”)
});
spl_autoload_register() 会将一个函数注册到 autoload 函数列表中,当出现未定义的类的时候,SPL [注] 会按照注册的倒序逐个调用被注册的 autoload 函数,这意味着你可以使用 spl_autoload_register() 注册多个 autoload 函数.
注:SPL: Standard PHP Library, 标准 PHP 库, 被设计用来解决一些经典问题(如数据结构).
PDO 和 MySQLi
即 PHP Data Object, PHP 数据对象,这是 PHP 的新式数据库访问接口。
按照传统的风格,访问 MySQL 数据库应该是这样子:
复制代码 代码如下:
// 连接到服务器,选择数据库
conn=mysqlconnect(“localhost”,“user”,“password”);mysqlselectdb(“database”);//执行SQL查询
type =
POST[‘type′];
sql = "SELECT * FROM `table` WHERE `type` = {type}”;result = mysql_query(
sql);//打印结果while(
row = mysql_fetch_array(
result,MYSQLASSOC))foreach($rowas$k=>$v)print“$k:$v\n”;//释放结果集,关闭连接mysqlfreeresult(
result);
mysql_close($conn);
为了能够让代码实现数据库无关,即一段代码同时适用于多种数据库(例如以上代码仅仅适用于MySQL),PHP 官方设计了 PDO.
除此之外,PDO 还提供了更多功能,比如:
1.面向对象风格的接口
2.SQL预编译(prepare), 占位符语法
3.更高的执行效率,作为官方推荐,有特别的性能优化
4.支持大部分SQL数据库,更换数据库无需改动代码
上面的代码用 PDO 实现将会是这样:
复制代码 代码如下:
// 连接到数据库
conn=newPDO(“mysql:host=localhost;dbname=database”,“user”,“password”);//预编译SQL,绑定参数
query = $conn->prepare(“SELECT * FROM table
WHERE type
= :type”);
query−>bindParam("type",
_POST[‘type’]);
// 执行查询并打印结果
foreach(
query−>execute()as
row)
{
foreach(
rowas
k => v)
print “{k}: {$v}\n”;
}
PDO 是官方推荐的,更为通用的数据库访问方式,如果你没有特殊需求,那么你最好学习和使用 PDO.
但如果你需要使用 MySQL 所特有的高级功能,那么你可能需要尝试一下 MySQLi, 因为 PDO 为了能够同时在多种数据库上使用,不会包含那些 MySQL 独有的功能。
MySQLi 是 MySQL 的增强接口,同时提供面向过程和面向对象接口,也是目前推荐的 MySQL 驱动,旧的C风格 MySQL 接口将会在今后被默认关闭。
MySQLi 的用法和以上两段代码相比,没有太多新概念,在此不再给出示例,可以参见 PHP 官网文档 [注]。
注:http://www.php.net/manual/en/mysqli.quickstart.php
类型约束
通过类型约束可以限制参数的类型,不过这一机制并不完善,目前仅适用于类和 callable(可执行类型) 以及 array(数组), 不适用于 string 和 int.
复制代码 代码如下:
// 限制第一个参数为 MyClass, 第二个参数为可执行类型,第三个参数为数组
function MyFunction(MyClass
a,callable
b, array $c)
{
// …
}
PHP5.2(2006-2011):JSON 支持
包括 json_encode(), json_decode() 等函数,JSON 算是在 Web 领域非常常用的数据交换格式,可以被 JS 直接支持,JSON 实际上是 JS 语法的一部分。
JSON 系列函数,可以将 PHP 中的数组结构与 JSON 字符串进行转换:
复制代码 代码如下:
array=[“key”=>“value”,“array”=>[1,2,3,4]];
json = json_encode(
array);echo“$json\n”;
object = json_decode(
json);printr(
object);
输出:
复制代码 代码如下:
{“key”:”value”,”array”:[1,2,3,4]}
stdClass Object
(
[key] => value
[array] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
)
值得注意的是 json_decode() 默认会返回一个对象而非数组,如果需要返回数组需要将第二个参数设置为 true.
PHP5.3(2009-2012)
PHP5.3 算是一个非常大的更新,新增了大量新特征,同时也做了一些不向下兼容的修改。
【PHP5.3弃用的功能】:以下几个功能被弃用,若在配置文件中启用,则 PHP 会在运行时发出警告。
Register Globals
这是 php.ini 中的一个选项(register_globals), 开启后会将所有表单变量(
GET和
_POST)注册为全局变量.
看下面的例子:
复制代码 代码如下:
if(isAuth())
authorized=true;if(
authorized)
include(“page.php”);
这段代码在通过验证时,将
authorized设置为true.然后根据
authorized 的值来决定是否显示页面.
但由于并没有事先把
authorized初始化为false,当registerglobals打开时,可能访问/auth.php?authorized=1来定义该变量值,绕过身份验证。该特征属于历史遗留问题,在PHP4.2中被默认关闭,在PHP5.4中被移除。MagicQuotes对应php.ini中的选项magicquotesgpc,这个特征同样属于历史遗留问题,已经在PHP5.4中移除。该特征会将所有用户输入进行转义,这看上去不错,在第一章我们提到过要对用户输入进行转义。但是PHP并不知道哪些输入会进入SQL,哪些输入会进入Shell,哪些输入会被显示为HTML,所以很多时候这种转义会引起混乱。SafeMode很多虚拟主机提供商使用SafeMode来隔离多个用户,但SafeMode存在诸多问题,例如某些扩展并不按照SafeMode来进行权限控制。PHP官方推荐使用操作系统的机制来进行权限隔离,让Web服务器以不同的用户权限来运行PHP解释器,请参见第一章中的最小权限原则.【PHP5.3的新增、改进】匿名函数也叫闭包(Closures),经常被用来临时性地创建一个无名函数,用于回调函数等用途。复制代码代码如下:
func = function(
arg)print$arg;;
func(“Hello World”);
以上代码定义了一个匿名函数,并赋值给了
func.可以看到定义匿名函数依旧使用function关键字,只不过省略了函数名,直接是参数列表。然后我们又调用了
func 所储存的匿名函数。
匿名函数还可以用 use 关键字来捕捉外部变量:
复制代码 代码如下:
function arrayPlus(
array,
num)
{
array_walk(array, function(&v) use(num){v += $num;
});
}
上面的代码定义了一个 arrayPlus() 函数(这不是匿名函数), 它会将一个数组(
array)中的每一项,加上一个指定的数字(
num).
在 arrayPlus() 的实现中,我们使用了 array_walk() 函数,它会为一个数组的每一项执行一个回调函数,即我们定义的匿名函数。
在匿名函数的参数列表后,我们用 use 关键字将匿名函数外的 num 捕捉到了函数内,以便知道到底应该加上多少。
魔术方法:__invoke(), __callStatic()
PHP 的面向对象体系中,提供了若干“魔术方法”,用于实现类似其他语言中的“重载”,如在访问不存在的属性、方法时触发某个魔术方法。
随着匿名函数的加入,PHP 引入了一个新的魔术方法 __invoke().
该魔术方法会在将一个对象作为函数调用时被调用:
复制代码 代码如下:
class A
{
public function __invoke($str)
{
print “A::__invoke(): {$str}”;
}
}a = new A;
$a(“Hello World”);
输出毫无疑问是:
复制代码 代码如下:
A::__invoke(): Hello World
__callStatic() 则会在调用一个不存在的静态方法时被调用。
命名空间
PHP的命名空间有着前无古人后无来者的无比蛋疼的语法:
复制代码 代码如下: