modern php读书笔记一
关于php,大家的误解比较多,但其实现代php是一门无论开发效率还是执行效率都相当高的编程语言。关于现代php的各方面特性,大家可以参考作者之前写的 php the right way,中文翻译:php之道。同时,作者也是比较流行的php框架 – slim 的开发者。所以这本书非常值得已读,甚至你只需要懂一些oop的概念即可,并不需要你懂php开发。
part 1 language featurefeaturesnamespaceshelpful tipscode to an interfacetraitgeneratorsclosureszend opcachebuilt-in http serverpart 2 good praticesstandardsphp-figpsrpsr-1 basic coding standardpsr-2 strict code stylepsr-3 logger interfacepsr-4 autoloaderscomponentscomponentscomposersemantic versioningcreate php componentspart 1. language featurefeaturesnamespacesphp命名空间使用 “\” 字符来分割sumnamespaces。与操作系统的物理文件系统不同,php命名空间是一个抽象概念,不必跟文件目录一一对应。大多数php components都是根据psr-4 autoloader standard来组织subnamespaces与文件目录的映射关系的。
从技术上来说,namespaces仅仅是一个php语言的符号,php解释器使用这个符号来作为一组classes/interfaces/functions/constants集合的前缀,仅此而已。
namespaces are important because they let us create sandboxed code that works alongside other developer's code. this is the cornerstone concept of the modern php component ecosystem.
helpful tips1. multiple imports
bad:
good:
bindto($this, __class__); } public function dispatch($currentpath) { foreach ($this->routes as $routepath => $callback) { if ($routepath === $currentpath) { $callback(); } } // 这里返回的state是在callback内修改过的 header('http/1.1 '.$this.responsestatus); header('content-type: '.$this.responsecontenttype); header('content-length: '.mb_strlen($this->responsebody)); echo $this->responsebody; }}// 添加注册一个路由addroute('/users/josh', function() { // 因为这个route是bindto到app class上的,所以这里直接访问$this修改 app 的内部state $this->responsecontenttype = 'application/json;charset=utf8'; $this->responsebody = '{name: josh}';});$app->dispatch('/users/josh');
zend opcache从php 5.5.0开始,php引入了内置的bytecode cache支持,叫做 zend opcache。php解释器在执行php脚本的时候,会首先把php代码编译为zend opcodes (machine-code instructions),然后才会执行bytecode。在所有请求中,php解释器都需要这样处理所有的php文件,read/parse/compiles,然而我们可以通过把php文件预编为php bytecode来省略这个开销,这就是zend opcache。
zend opcache的使用非常简单,在我们配置之后,它就会在内存中自动缓存precompiled php bytecode,在可用的情况就会直接执行这个php bytecode,而不需要再去编译php代码。
具体配置去google吧,有一点需要注意的是,如果同时配置了 xdebug的话,在php.ini文件中,需要在xdebug之前加载zend opcache extension扩展。
built-in http serverphp从5.4.0引入了内置的http server,所以我们在不配置apache或者nginx的情况下就直接预览php程序。
remember, the php built-in server is a web server. it speaks http, and it can serve static assets in addition to php files. it's a great way to write and preview html locally without installing mamp, wamp, or a heavyweight web server.
要使用内置的http server非常简单,在工程的根目录下,执行下面的命令即可:
php -s localhost:4000
如果要让本地网络的其他设备访问php web server,我们可以这么启动:
php -s 0.0.0.0:4000
如果我们希望通过 php ini 配置文件去做一些特殊配置,可以通过下面命令来启动:
php -s localhost:8000 -c app/config/php.ini
我们也可以通过router scripts来实现一些特殊的路由需求,可以通过下面的命令启动:
php -s localhost:8000 router.php
在php代码中,我们可以通过php_sapi_name()来判断:
php tag;每行尽量不要超过80个字符,最多不能超过120个字符;每行结尾不能包含空格;
keywords: 所有的php关键字都必须小写
namespaces: 每个namespace声明后面都必须跟着一个空行;使用use来import or alias namespaces的时候,必须在use声明后面跟一个空行;
classes: 定义类时,开始的大括号(opening bracket)必须新起一行,结束的大括号(closing bracket)必须在类体定义后面新起一行;extents/implements关键字必须跟在类名定义的后面;例如:
methods: 方法定义的大括号规则与类定义类似,opening brackets和closing brackets都必须新起一行。
visibility: 对类中定义的全部property和method都必须声明可见性(visibility),可见性是public, protected, private其中的一个;abstract / final 必须写在visibility之前;static必须写在visibility之后;
control structures : 所有的control structure keyword (if/elseif/else/switch/case/while/do while/for/foreach/try/catch)的后面都必须一个空字符;大括号的规则与class定义不同,opening brackets跟control structure keyword必须在同一行,而closing bracket必须另新一行;
我们可以通过ide的格式化工具来让代码格式化,实现psr-1和psr-2的code style。我经常使用的工具phpstorm就可以设置。还有一些其他工具,比如 php-cs-fixer 或 php code sniffer
psr-3 logger interfacepsr-3 is an interface, and it prescribes methods that can be implemented by php logger components.
psr-4 autoloadersan autoloader is a strategy for finding a php class, interface, or trait and loading it into the php interpreter on-demand at runtime. php components and frameworks that support the psr-4 autoloader standard can be located by and loaded into the php interpreter with only one autoloader.
关于psr-4,看官方文档之后感觉理解很困惑,本书的作者的解释就非常简洁:
the essence of psr-4 is mapping a top-level namespaces prefix to a specific filesystem directory.,简单来说,就是设定了一个namespaces前缀和某个特定的文件目录之间的映射关系,然后在这个namespace前缀之下如果还有更多的sub namespace,这些sub namespaces就会跟这个特定的目录下面的子目录一一映射起来。例如,\oreilly\modernphp namespace与 src/ 物理路径一一映射,那么\oreilly\modernphp\chapter1对应的文件夹就是src/chapter1,而\oreilly\modernphp\chapter1\example类对应的文件路径就是src/chapter1/example.php文件。
psr-4 lets you map a namespace prefix to a filesystem directory. the namespace prefix can be one top-level namespace. the namespace prefix can also be a top-level namespace and any number of subnamespaces. it's quite flexible.
componentscomponentsmodern php is less about monolithic framework and more about composing solutions from specialized and interoperable components.
what are components?: a component is a bundle of code that helps solve a specific problem in your php application.
框架与components:如果我们正在创建一个小项目,可以直接使用一些php components集合来解决问题;如果我们正在进行一个多人合作开发的大项目,我们可以通过使用一个framework;但这都不是绝对的,应该根据具体问题来解决。
packagist:跟其他语言的包管理机制一样,例如maven,也有一个网站 https://packagist.org/ 让我们搜索我们需要的php components的相关信息。总所周知的原因,packagist在国内很不稳定,可以使用国内的全量镜像来代替,http://www.phpcomposer.com/ 。
composercomposer is a dependency manager for php components taht runs on the command line,跟其他现代语言一样,php使用composer来做依赖管理,类似的有ios中的cocoapods,android中的maven/gradle,前端的npm,ruby的gem,这些工具可以大大简化我们管理第三方库的成本。于是,当我们在packagist上面找到我们需要的components之后,就可以通过composer来使用这个库。
当我们使用composer来添加第三方component的时候,composer除了会自动帮我们下载需要的php components之外,还会自动帮我们创建一个符合psr-4的autoloader。
跟cocoapods类似,cocoapods使用podfile来指定需要依赖的第三方库,以及保存有当前使用的具体的第三方库的版本号。所以我们需要把这两个文件都加入到版本控制中进行管理,确保不同成员/ci/开发环境等不同地方大家使用第三方库版本的一致性。对应composer中的文件就是 composer.json以及composer.lock。这里需要注意的是composer install 和 composer update 命令的差别:
* composer install,不会安装比composer.lock中列出的更高版本的components;
* composer update,会更新你的components到最新的稳定版,同时也会更新composer.lock文件为最新的php components版本号。
semantic versioningmodern php components 使用 semantic versioning scheme,同时包含了用小数点(.)分隔的三个数字,比如 1.13.2。同时,这个也是很多其他语言开源库的版本规则,对这个一直比较好奇,终于在modern php中看到了相应的解释。
major release number:第一个数字是major release number,只有当php component发生不再向前兼容的更新时,才需要增加这个版本号。minor release number:第二个数字是minor release number,当php component发生一些小的功能更新,并且没有破坏版本兼容时,增加这个版本号。patch release number:最后一个数字是patch release number,当发生版本兼容的bug修复的时候,增加这个版本号。create php components这部分跟ios创建自己的spec非常相似,并不是非常复杂的问题,参考书或者官方文档很容易就能发布
