PHP7要发布了,你连5.X的特性都还不知道么?今天我们就整理了一些属于5.3之后版本PHP的特性。由于PHP版本依旧在不断的更新中,其中不乏一些实用的新特性可以大大简化编程中遇到的问题,这里介绍一些实用的特性
众测的模块日益复杂,在各个模块中容易出现类名或变量名的冲突。因而,命名空间可能是PHP5.3所带来的重要的特性。、
在PHP5.3之前,惯例的划分Package的办法是通过目录名来分隔代码文件,代码中的类名则用下划线_来表示目录。例如主站的模块就可以命名为crowdtest_models_user
这样的命名方式常见于Zend Framework和各种PHP项目。虽然该方法有效避免了类名的冲突,但在编码过程中显得十分笨拙和麻烦。
在PHP5.3中,则只需要指定不同的命名空间即可,命名空间的分隔符为反斜杆\。
<?php namespace crowdtest\models; class User {}这样即使其它命名空间下存在名为User的类,程序在调用时也不会产生冲突。代码的可读性也有所增加。
调用方法:
$user = new crowdtest\models\User();
很多语言中都支持无条件转向语句goto,尽管goto语句降低了代码可读性,使理解代码变得困难,然而在某些情况下具有其独特的方便之处,例如中断深度嵌套的循环和 if 语句。
goto a; echo'CROWDTEST'; a: echo'zhongce';
闭包(Closure)函数和Lambda函数的概念来自于函数编程领域。比如JavaScript的一大特点就是支持闭包和 lambda 函数。
在PHP5.3中,我们同样可以使用Lambda匿名函数来定义一些临时使用(即用即弃型)的函数,以作为array_map()/array_walk()等函数的回调函数。
echo preg_replace_callback('~-([a-z])~', function ($match) { return strtoupper($match[1]); },'hello-zhongce); //输出 helloZhongce $test = function($name) { echo$name; }; $test('zhongce');
用法近似于Heredoc,但使用单引号,而Heredoc则需要通过使用双引号来声明。
Nowdoc中类似于单引号处理字符串,不会做任何变量解析,非常适合于传递一段PHP代码。
//Nowdoc 单引号 PHP 5.3之后支持 $name= 'crowdtest'; echo<<<'EOT' Here is "$name". EOT; //上面代码输出 Here is "$name". ((其中变量不被解析) //Heredoc不加引号 echo<<<FOOBAR Hello crowdtest! FOOBAR; //或者 双引号 PHP 5.3之后支持 echo<<<"FOOBAR" Hellocrowdtest! FOOBAR;
并且新增了一种常量定义方式:
<?php const CONSTANT = ' Hello crowdtest ';
原本格式为是(expr1) ? (expr2) : (expr3),此时如果expr1结果为True,则返回expr2的结果。
PHP5.3中增加了一种书写方式,可以省略中间部分,写成这种 expr1 ?: expr3。此时如果expr1结果为True,则返回expr1的结果。不过此方法感觉并不直观,使用起来对不熟悉语法的小伙伴是不小的挑战
class user{ public static function login() { echo"login!"; } } $class = 'user'; $action = 'login '; $class::$action(); //输出 " login!"
把当前目录作为Root Document,只需要这条命令即可:
# php -S localhost:8888
也可以指定其它路径:
# php -S localhost:8888 -t /home/work
还可以指定路由:
# php -S localhost:8888 router.php
Traits提供了一种灵活的代码重用机制,其实际的目的,是为了有的场合想用多继承,但PHP又没多继承,于是就发明了这样的一个东西。
假如我们有个类为client,有一个变量为address,在兑换礼品的业务中存在order类的,需要访问同样的地址属性,那怎么办呢?order类是没办法继承client类的,因为这个不符合OOP的原则。
trait Address{ private $address; public getAddress() { return $this->address; } public setAddress($address) { $this->address = $address; } } class Order{ use Address; //这里可以使用address属性 }
$arr = [1,'crowdtest', 'test.baidu.com']; $array = [ "test"=> "bar", "crowd"=> "foo" ];
function myArray() { return [1,'crowdtest', 'test.baidu.com']; }在PHP5.4中这样就行了:
echo myArray()[1];
如果用户需要上传一个大文件,和可能需要一个进度条来告知其状态,5.4版本的Session提供了上传进度支持,通过$_SESSION["upload_progress_name"]就可以获得当前文件上传的进度信息,结合Ajax就能很容易实现上传进度条了。
由于php是弱类型的语言,所以在php 5.0后,引入了函数类型提示的功能,其含义为对于传入函数中的参数都进行类型检查,举个例子,有如下的类:
class user { function login(user $user) { }其中函数login中的参数规定了传入的参数必须为user类的实例,否则系统会判断出错。同样对于数组来说,也可以进行判断,比如:
function user (array $ user) {} user(array(1, 2, 3)); // 正确,因为传入的是数组 user(123); // 不正确,传入的不是数组
$val= 0b1101; echo $val;//13另外值得一提的是多字节支持已经默认启用了,
default_charset从ISO-8859-1已经变为UTF-8.
默认发送“Content-Type: text/html; charset=utf-8”,
你再也不需要在HTML里写meta tag,也无需为UTF-8兼容而传送额外的header了。
boolval()由于PHP已经出现了strval、intval和floatval这些类型检查的函数。为了满足强迫症添加了boolval函数。它完全可以作为一个布尔值计算,也可以作为一个回调函数。
hash_pbkdf2()PBKDF2是“Password-Based Key Derivation Function 2”的简写,正如它的名字一样,是一种从密码派生出加密密钥的算法。
$password = "crowdtest"; //生成hash $hash= password_hash($password, PASSWORD_BCRYPT); //验证hash if(password_verify($password, $hash)) {}
目前,empty()语言构造只能用在变量,而不能在其他表达式。
在特定的代码像empty($this->getFriends())将会抛出一个错误。作为PHP5.5这将成为有效的代码
如果你有一个函数接受多个可选的参数,目前没有办法只改变最后一个参数,而让其他所有参数为默认值。
RFC上的例子,如果你有一个函数如下:
function create_query($where, $order_by, $join_type='', $execut e= false, $report_errors = true) { ... }那么有没有办法设置$report_errors=false,而其他两个为默认值。为了解决这个跳跃参数的问题而提出:
create_query("deleted=0","name", default, default, false);
如果你非常讨厌写getXYZ()和setXYZ($value)方法,那么这一特性应该会帮助到你。5.5版本添加一个新的语法来定义一个属性的设置/读取:
class Time { public $seconds; public $hours { get { return $this->seconds / 3600;} set { $this->seconds = $value *3600; } } }
目前,很少使用自定义迭代器,因为它们的实现需要相当多的样板代码。生成器解决这个问题,并提供了一种简单的样板代码来创建迭代器。
例如,你可以定义一个范围函数作为迭代器:
function *range($start, $end) { for ($i = $start; $i < $end; $i ++) { yield $i; } } foreach(range (10, 20) as $i) { // ... }上述range函数具有与内建函数相同的行为,但有一点区别:不是返回一个数组的所有值,而是返回一个迭代器动态生成的值。
使用类似于java中的finally,经典的try... catch ... finally 三段式异常处理。
可变参数函数允许传入任意数量的参数。当你提供给他一些参数,你通常不得不调用 func_get_args 来进行后续操作,这有点不切实际。在这里有这样的例子,在5.5中语法是这样的:
class MySQL implements DB { protected $pdo; public function query($query) { $stmt = $this->pdo->prepare($query); $stmt->execute(array_slice(func_get_args(),1)); return $stmt; }<em> } $userData= $db->query('SELECT * FROM users WHERE id = ?', $userID)->fetch();</em>
现在语法将变成这样:
class MySQL implements DB { public function query($query, ... $params){ $stmt = $this->pdo->prepare($query); $stmt->execute($params); return $stmt; } }使用... $params 语法将会使函数接受第一个参数,将其他的全都放到$params数组当中。同时这个新的语法还允许对额外的参数使用引用传递。给...$params 加一个&符前缀,就像这样&...$params,这是 func_get_args难以企及的。
在改善可变参数函数之后,参数解包也得到了支持。
到目前为止,通过参数的方式,调用一个方法的时候传入任意多个数量的参数的为止方式是使用 call_user_func_array 。字面意思就是“调用一个用户函数并使用一个array作为参数”。这很笨拙和不方便,而且不支持构造函数,速度慢,需要一个字符串形式的回调函数,这意味着大多数的IDE都不能跟踪和支持这个函数。
解包功能将消除上面的所有的缺点,而且自然的补充了上面看到的任意数量参数的支持。解包看起来像这样:
$args = [1, 3, 5, 7, 9]; MyClass::someMethod(...$args);这样的方式就像是这样:
MyClass::someMethod(1,3, 5, 7, 9);通过这一个又一个的参数,使他可以工作在任何的场景下,从类的初始化到各种回调。
PHP7已经公布,在未来我们还将看到更多实用的特性出现在我们面前