Modern PHP 笔记(一):语言特性

系列笔记:
Modern PHP 笔记(一):语言特性
Modern PHP 笔记(二):良好实践
Modern PHP 笔记(三):部署测试和调优

现在正式加入世界上最好的语言大家庭了。jimbochen大佬给推荐了 Josh Lockhart 写的,安道翻译的《Modern PHP》. 准备记录下一些学习笔记。刚刚入坑,如果理解的不对,欢迎指出。

这本书刚看,觉得内容很扎实。对PHP的整个生态有了更深的理解。强烈推荐读一下。顺便吐槽下,的markdown不支持toc,这个蛮影响体验。

第一章:新时代的PHP

PHP正在重生,得益于命名空间、性状、闭包和内置的操作码缓存等有用的特性

现状

跳出了框架的束缚,依赖composer管理插件,混搭合适的组件。

历史

  • 创始人:拉斯姆斯·勒多夫
  • PHP tools:Personal Home Page Tools
  • 1998年,PHP3: PHP: Hypertext Preprocessor
  • PHP引擎: Zend Engine、HipHop Virtual Machine
  • 基于PHP之上的语言:Hack

第二章:特性

命名空间

目的:避免命名冲突

使用命名空间

    // 声明命名空间
    namespace Oreilly\ModernPHP;
    // 厂商命名空间最重要,必须具有全局唯一性

    // 导入类和别名
    use Symfony\Component\HttpFoundation\Response as Res;

    // 导入函数
    use func Namespace\functionName;

    // 导入常量
    use constant Namespamce\CONST_NAME;

全局命名空间

    

Exception类没有命名空间,在全局命名空间中,此时调用\My\App\Foo::doSomething()
报错。
正确写法为:new \Exception()

使用接口

接口是两个PHP对象之间的契约,其目的不是让一个对象依赖另一个对象的身份,而是依赖另一个
对象的能力。我们不关心第三方代码如何实现接口,只关心是否实现了指定接口。

    // 操作的入参Documentale不是类,是接口
    class DocumentStore
    {
        public function addDocument(Documentable $document)
        {
            ...
            $document->getId();
            $document->getContent();
        }
    }

    // 接口定义
    interface Documentable
    {
        public function getId();

        public function getContent();
    }


    // 类1实现了接口
    class HtmlDocument implements Documentable
    {
        public function getId()
        {
            // ...
        }

        public function getContent()
        {
            // ...
        }
    }

    // 类2实现了接口
    class StreamDocument implements Documentable
    {
        public function getId()
        {
            // ...
        }

        public function getContent()
        {
            // ...
        }
    }

性状trait

性状有两个作用:表明类可以做什么(像接口),提供模块化实现(像类)

为什么使用性状

继承模型不好用时,比如想让两个无关的PHP类具有类似的行为?(e.g.零售店类和汽车类都想使用
地理编码转换成经纬度功能时)

  1. 方案一:继承共同父类。——不好。让两个无关类继承自同一祖先。
  2. 方案二:创建地理转换接口。——好一点。但是两个类都需要实现相同的代码,不符合DRY原则
  3. 方案三:使用性状,直接在两个类中混入性状——最好

创建性状

    

使用性状

    class MyClass
    {
        use MyTrait;
        // 类其他实现
    }

PHP会直接把性状代码粘贴在类中,因此要注意兼容问题。

生成器generator

生成器是简单的迭代器。不同的是,不要求类实现Iterator接口,每次只计算下一个值,不会在内存
中预先计算。提升性能

创建生成器函数

  • 是的,生成器是使用了yield关键字的函数。

  • 只产出值,不返回值。

  • 返回一个属于Generator类的对象,可以用foreach()迭代。

  • 生成器每产生一个值内部状态就会停顿,然后恢复,停顿...

      function myGenerator()
      {
          yield 'value1';
          yield 'value2';
      }
    

使用生成器

常用于需要节省内存时,比如生成一个大范围的数、处理很多行的csv文件等。

    foreach (myGenerator() as $yieldValue) {
        echo $yieldValue, PHP_EOL;
    }

闭包

  • 闭包是创建时封闭周围状态的函数。即便闭包所在环境不存在了,闭包中封装的状态依旧存在。
  • 匿名函数时没有名称的函数,非常适合作为函数或方法的回调。

PHP中将闭包和匿名函数视为相同概念。

创建闭包

与函数语法相同,但实际上闭包是Closure类的实例,不是函数。

附加状态

必须调用闭包对象的bindTo()方法或者使用use关键字,将状态附加到PHP闭包上。

    $que = function ($query)use ($id) {
        // $id是外面变量
    }

bindTo()方法将闭包实例的内部状态绑定到其他对象上,则闭包可以访问绑定闭包的对象中受保护方法和私有成员变量。

e.g.,PHP框架经常使用bindTo()方法把路由URL映射到匿名函数。因此可以在匿
名函数中使用$this引用应用对象。

Zend OPcache 字节码缓存

PHP是解释型语言,PHP解释器执行PHP脚本时会解析代码,将其编译成 Zend 操作码,然后执行
字节码。每次HTTP请求都会不断解析、编译、执行。缓存字节码可以节省时间,提高性能。

Zend OPcache 默认不启用,需要手动开启并配置。

内置HTTP服务器

从PHP 5.4 开始

启动内置服务器

    // 根目录
    php -S localhost:4000

自定义配置

    php -S localhost:8000 -c app/config/php.ini

路由器脚本

内置的服务器不支持.htaccess文件,因此很难使用前端控制器。

前端控制器是一个PHP文件,用于转发所有的HTTP请求(通过.htaccess文件或者重写规则实现)。
前端控制器的职责是,分发请求,以及调度适当的PHP代码。

内置服务器使用路由脚本弥补这个功能。处理HTTP请求前,先执行路由器脚本,如果为false,则
返回请求的静态资源URI,否则返回脚本的执行结果。

    php -S localhost:8000 router.php

判断使用哪种服务器

    if (php_sapi_name() === 'cli-server'){
        // PHP 内置的服务器
    } else {
        // 其他 Web 服务器
    }

缺点

不能用在生产环境:

  • 一次只能处理一个请求
  • 只支持少量媒体类型
  • 通过路由器脚本支持少量URL重写规则,更高级不行

更多笔记还在读书中O(∩_∩)O哈哈~

最后,照例记录下一段很喜欢的话共勉。

过一个平凡无趣的人生实在太容易了,你可以不读书,不冒险,不运动,不写作,不外出,不折腾……但是,人生最后悔的事情就是:我本可以。  ——陈素封

你可能感兴趣的:(Modern PHP 笔记(一):语言特性)