PHP 5.4 中的新特性

转自:http://www.oracle.com/technetwork/cn/articles/dsl/lerdorf-php54-1564639-zhs.html

 

大约八年前,我为 Oracle 技术网写了一篇名为“您了解 PHP 吗?”的文章。在那篇文章中,我谈到了 PHP 固执的功能优于形式的“Web问题”解决方法,以及它所具备的让事情变得简单的能力。当时,我们即将发布 PHP 5.0。现在,时隔将近十年之后我们推出全新的 PHP5.4.0 版本,虽然在这期间发生了很多事情,但也有许多事情根本没变。

没变的一件事情就是生态系统一如以往那样重要。解决 Web 问题不仅仅关乎脚本语言的选择,它关乎的是周围的整个生态系统。现在,LAMP体系已盛行近 15 年,仍广受欢迎,但我们开始注意到其他功能强大的方案。附带 nginx 的 PHP-FPM 已经快速流行起来,因为从PHP 5.3 开始大大改进了支持,并在 5.4 中进一步得到简化。体系中的 M(即数据库)部分与 8年前相比也开始变得极为不同。与将所有内容都只放入 MyISAM 表中相比,各种 NoSQL 解决方案和 MySQL Cluster提供了一组更丰富的选择。

出现了多种有趣的技术,因而我们编写了 PHP 扩展来轻松访问这些技术。我最喜爱的一个扩展是 libevent,可以用它在PHP 中编写事件驱动的高性能应用程序。另一个是 ZeroMQ,这是一个高级套接字库。与SQLite 不再需要编写另一种原始文件格式和关联的分析器极为相似,ZeroMQ也无需因任何理由而使用套接字协议和关联的套接字处理代码。您甚至可以组合使用 libevent 和ZeroMQ,以获得独立、高性能、事件驱动的卓越服务器。(如果您对此感兴趣,请参见此示例。)我还十分喜欢 SVM(支持向量机)这一机器学习算法,您不必成为机器学习的爱好者也可提出许多问题。

还有许多扩展在最近几年内已被广泛接受。特别是,Gearman 变得流行起来,逐渐成为用户部署的常见体系的一部分。您可以通过Gearman 分派作业,以便由工作器异步完成这些作业。工作器可以遍布多台服务器,它们甚至可以进一步分派更多的 MapReduce类型作业。

2004 年发布 PHP 5.0 之后,接下来在 2005 年推出 5.1,此版本新增了 DateTime 实现、PDO和性能改进。PHP 5.2 于 2006 年发布,引入了改进的内存管理器、JSON 支持和输入筛选。当时,我们着手推动 PHP6,这是一个极其宏伟的计划,完全重写有关 ICU(Unicode 国际化组件)库的所有内容。事实证明这个计划有些操之过急 —我们无法使足够多的开发人员为之兴奋,最终只得将准备引入 PHP 6 的各种特性添加到 2009 年发布的 PHP 5.3 中。5.2与 5.3 版本时隔 3 年,这也意味着 5.3 向 PHP 新增了大量内容:命名空间、后期静态绑定、闭包、垃圾收集、受限goto、mysqlnd(MySQL 原生驱动程序)、更好的 Windows 性能以及许多其他内容。

事后看来,将此版本称为 PHP 6 可能有一定的道理,但 PHP 6 等同于在 Unicode方面所做的努力,以至于为此编写了相关书籍,因此我们认为如果没有对 Unicode 做出重大改进,就不能发布 PHP6。我们引入了名为“intl”的 ICU 扩展,它也针对 PHP 5.2 编译,这可让您访问更多的 ICU 功能。mbstring扩展随时间不断地改进,这意味着几乎任何与 Unicode 相关的问题都有解决方案,只是未明确集成到语言本身中。

这样在 2012 年推出 PHP 5.4。而且,与上一版本时隔将近 3年,我们在此期间对一些内容进行了改进。我宁愿恢复到每年推出一个版本,每个版本包含更少的新特性。

以下是您升级到 5.4 时将看到的主要特性:

内存和性能改进

许多内部结构已变得更小或完全消失,从而在大型 PHP 应用程序中可节省 20-50% 的内存。通过各种优化使性能提高10-30%(主要取决于代码执行的操作),这些优化包括内联各种常见代码路径、将 $GLOBALS 添加到JIT、“@”操作符运算更快、添加了运行时类/函数/常量缓存、运行时字符串常量现在被拘留、通过预先计算的散列更快地访问常量、空数组速度更快并使用更少内存、unserialize()和 FastCGI 请求处理速度更快,以及在整个代码中进行更多的内存和性能调整。

例如,早期的一些测试表明,Zend Framework 在 5.4 中运行速度提高 21% 并且内存使用减少 23%,而 Drupal内存使用减少 50% 并且运行速度大约提高 7%。

Trait

Trait 可能是 PHP 5.4 中谈论最多的特性 — 将它们视为编译器辅助的复制粘贴。Trait 也是 Scala的一个特性。其他语言可能将它们称为“mixin”—或者这些语言根本不对它们进行命名,但具有扩展接口机制,允许接口包含其方法的实际实现。

与 mixin 相反,PHP 中的 trait 包括显式冲突解决机制,用于多个 trait 实现相同方法的情况。

trait Singleton {
    public static function getInstance() ... }
}

class {
    use Singleton;
    // ...
}

class extends ArrayObject {
    use Singleton;
    // ...
}

// Singleton method is now available for both classes
A::getInstance();
B::getInstance();

请参见 php.net/traits 了解更多示例,包括冲突解决语法、方法优先顺序、可见性以及对trait 中常量和属性的支持。此外,要详细了解概念理论,您可以阅读 Nathan Schärli的论文“Trait:行为构建块中的组合类”。

精简数组语法

新增的一种简单但非常流行的语法:

$a [1, 2, 3];
$b ['foo' => 'orange', 'bar' => 'apple'];

就是说,您现在不再需要使用“array”关键字来定义数组。

函数数组解除引用

新增的另一种常用语法。返回数组的函数调用现在可以直接解除引用:

function fruits() {
   return ['apple', 'banana', 'orange'];
}
echo fruits()[0]; // Outputs: apple

实例方法调用

与函数数组解除引用相关,您现在可以调用对象实例化方法。与早期版本一样,您当然仍可以链接方法调用,因此您现在可以编写如下代码:

class foo {
    public $x 1;
 
    public function getX() {
        return $this->x;
    }
    public function setX($val) {
        $this->x $val;
        return $this;
    }
}
 
$X (new foo)->setX(20)->getX(); 
echo $X; // 20

然而,由于可能丢弃实例化的对象,因此,除非您的构造函数执行有用操作,否则您应该在此改用静态方法调用。如果将它与精简数组语法和函数数组解除引用结合使用,我们可以编写某些十分复杂的代码:

class foo extends ArrayObject {
    public function __construct($arr) {
        parent::__construct($arr);
    }
}
 
echo (new foo( [1, [4, 5], 3] ))[1][0];

看一眼之后,您可以断定输出是什么吗?在此,我们将二维数组传递到仅返回数组的构造函数。然后,我们选出第二个维度的第一个元素,因此这将输出“4”。

闭包绑定

闭包是在 PHP 5.3 中引入的,但在 5.4 中我们改进了闭包与对象的交互方式。例如:

class Foo {
  private $prop;
  function __construct($prop) {
    $this->prop $prop;
  }
  public function getPrinter() {
    return function() echo ucfirst($this->prop); };
  }
}

$a new Foo('bar');;
$func $a->getPrinter();
$func(); // Outputs: Bar

注意闭包访问 $this->prop 这一私有属性。默认情况下,PHP 中的闭包使用预绑定 —这意味着闭包内的变量具有定义闭包时所具有的值。可以使用引用将其转换为后绑定。但是,也可以重新绑定闭包:

$a new Foo('bar');
$b new Foo('pickle');
$func $a->getPrinter();
$func(); // Outputs: Bar
$func $func->bindTo($b);
$func(); // Outputs: Pickle

在此,我们将闭包从 $a 实例重新绑定到 $b 中的实例。如果您不希望闭包随时访问对象实例,可以将闭包声明为静态:

class Foo {
  private $prop;
  function __construct($prop) {
    $this->prop $prop;
  }
  public function getPrinter() {
    return static function() echo ucfirst($this->prop); };
  }
}

$a new Foo('bar');;
$func $a->getPrinter(); 
$func(); // Fatal error: Using $this when not in object context

对象即函数

有一种新的神奇方法,名为“__invoke”,其用法如下:

class MoneyObject {
    private $value;
    function __construct($val) {
        $this->value $val;
    }
    function __invoke() {
        return sprintf('$%.2f',$this->value); 
    }
}
$Money new MoneyObject(11.02/5*13);
echo $Money(); // Outputs:$28.65

内置 Web 服务器 (CLI)

CLI 服务器是一种小型 Web 服务器实现,可以从命令行运行:

% php -S localhost:8000
PHP 5.4.0 Development Server started at Sun Mar 11 13:27:09 2012
Listening on localhost:8080
Document root is /home/rasmus
Press Ctrl-C to quit.


CLI 服务器不适合用作生产 Web 服务器;我们将使用它运行一些 PHP 回归测试,其他单元测试机制也可使用它,并且 IDE也可能使用它。它确实具有一些很有用的特性,用于从命令行进行日常代码调试。默认情况下,它使用当前目录作为DocumentRoot;它也处理静态文件请求。默认目录索引文件为“index.php”,因此您可以在满含.php、.css、.jpg 等文件的目录中激活它,它自己就可以运行。对于可能使用 mod_rewrite将所有请求发送到前端控制器或路由器的更复杂应用程序,您可以将此路由器与一个简单的小脚本包装在一起,并启动 CLI服务器,如下所示:

% php -S localhost:8080 /path/to/router.php
PHP 5.4.0 Development Server started at Sun Mar 11 13:28:01 2012
Listening on localhost:8080
Document root is /tmp/web
Press Ctrl-C to quit.


router.php 脚本可能如下所示:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值