PHP 5.4 和 Traits

PHP 5.4 和 Traits

Chris Yue 3 comments
Posts

PHP 5.4 带来的新功能相比 5.3 只能说更让人兴奋,让我们来看看 5.4 到底做了什么功能改进:

翻译自http://php.net/manual/en/migration54.new-features.php

  • 首当其冲的是 trait,一个新的语法结构
  • 数组简写,比如 $arr = [1, 2, 3, 4];$arr = ['one' => 1, 'two' => 2];(泪流满面啊……)
  • 直接获取函数返回的数组的某个元素,比如 foo()[0](再次泪流满面……)
  • 闭包(cloure)支持 $this(必须的啊)
  • <?= 一直可用,无论short_open_tags是否为 0(这个必须赞一个,以前就觉得 <? 不能用是因为和 xml 冲突,但是 <?= 不冲突啊,为啥非要写成 <?php echo 呢)
  • 现在可以在初始化对象之后立马调用对象的方法或属性,比如 (new foo())->bar()
  • 现在支持 Class::{expr}() 语法(这是神马语法?)
  • 现在支持二进制数格式 e.g. 0b001001101(我去,原来以前一直不支持么……)
  • 改进错误提示的内容(好的错误信息能让你更快定位错误)
  • 会话(session)扩展可以追踪文件的上传进度(这也是个亮瞎眼的功能!可以从 $_SESSION['upload_progress_name'] 这个变量中获取许多上传的数据,比如有几个文件已经上传完毕,已经传输了多少数据,一共要传输多少数据等等,可以用 js 方便的把进度条展现给用户)
  • 内置服务器(在命令行下启动,类似 ruby on rails 里提供的 Webrick)

现在重点来说说 traits,单独提出来是因为,它真的是太她妈好用了,解决了长期困扰 phper 的一个问题。

traits 其实就是在代码层提供了一个复制粘贴的功能,当然它比直接的复制粘贴更具有维护性。说一个我最近使用 traits 的一个例子

我有好几个类,都是 singleton 模式。大部分程序员都应该腻烦了反复为类实现 singleton 写大量同样代码,yes, now trait comes here to rescue! 只要你定义一个叫 singleton 的 trait,然后在需要实现 singleton 的类里简单加上一句 use singleton;,此类就一秒变 singleton了!好方便有木有?另外 trait 也是支持命名空间的,并且也支持自动加载机制,可以使用 __autoload 或者 spl_autoload_register 为 trait 实现自动加载。

//这里需要注意一下,namespace 里面不能出现 trait 关键字,否则会报错,所以我改用 snippet
namespace MyComponent\Snippet;

trait Singleton
{
    static private $instance;

    private function __construct()
    {
    }

    private function __wakeup()
    {
    }

    private function __clone()
    {
    }

    static public function getInstance()
    {
        return self::$instance ?: self::$instance = new self;
    }
}

使用:

<?php

namespace MyComponent;

require __DIR__.'/Snippet/Singleton.php';
// 如果已经注册过自动加载,上面那句就不用写了

class Loader
{
    use Snippet\Singleton; // 只用关注这一行就好了,后面都不是重点……

    private $namespaces = [
        'MyComponent' => __DIR__
    ];

    private $prefixes = [];

    public function addNamespace($ns, $path)
    {
        $this->namespaces[$ns] = $path;
        return $this;
    }

    public function registerAutoload()
    {
        spl_autoload_register([$this, 'loadClass']);
    }

    public function loadClass($className)
    {
        $parts = explode('\\', $className, 2);
        if (isset($parts[1])) {
            // 表明用的是namespace
            if (isset($this->namespaces[$parts[0]])) {
                require sprintf(
                    $this->namespaces[$parts[0]], 
                    str_replace('\\', '/', $parts[1])
                );
            } else {
                trigger_error(
                    sprintf('Namespace "%s" has not register to the loader', $parts[0]),                     
                    E_USER_ERROR
                );
            }
            return ;
        }
        // else
        $parts = explode('_', $className, 2);
        if (isset($parts[1])) {
            if (isset($this->prefixes[$parts[0]])) {
                require sprintf($this->prefixes[$parts[0]], str_replace('_', '/', $parts[1]));
            } else {
                trigger_error(
                    sprintf('Prefix "%s" has not register to the loader', $parts[0]), 
                    E_USER_ERROR
                );
            }

            return ;
        }
        // else
        trigger_error(sprintf('Cannot load class %s', $className));
    }
}

PHP 5.4 和 Traits by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

微信赞赏码

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人

3 Comments

james

六月 8, 2012 在 6:29 下午

Chrisyue,你好。我看到你关于symfony+nginx配置的文章。http://hi.baidu.com/chrisyue/blog/item/6f35b9fb7a76ae2e4e4aea5f.html
我最近也在处理类似的事情,但是我在symonfy+nginx的配置上遇到了问题。按照你的配置,项目可以访问了。但是似乎项目中的.css文件内容没有被加载到浏览器中。

    Chris Yue

    六月 12, 2012 在 2:04 上午

    你是用的哪个配置?访问css文件报什么错

     

    james

    六月 15, 2012 在 11:36 上午

    是自己遗漏了“include mime.types;default_type application/octet-stream;”配置。十分多谢,希望通过email多做技术交流viewsoft@yeah.net。
    祝:工作顺利

     

发表评论

− 7 = 1