先列举一些资源:
有几点事先说明:
- 翻译部分,我只挑选PSR-0和PSR-4中的主要规范内容进行翻译。
- 我的翻译,侧重以理解的角度,而不是严格的文法翻译。
关键修饰词的说明:
**MUST** __务必__**MUST_NOT** __绝不__**REQUIRED** __务必__**SHALL** __务必__**SHALL_NOT** __绝不__**SHOULD** __应该__**SHOULD_NOT** __不应该__**RECOMMENDED** __建议__**MAY** __可以__**OPTIONAL** __可选__
为啥这样子,看看的定义吧!
##PSR-0 类自动加载规范(Autoloading Standard)
已弃用,从2014年10月21日起,PSR-0规范已弃用,并推荐以PSR-4规范作为替代。
###规范正文
- 命名空间(Namespace)和类(Class)__务必__拥有如右侧所示的标准结构
\<Vendor Name>\(<Namespace>\)*<Class Name>
。 - (所有)命名空间(Namespace)__务必__拥有一个顶级的命名空间,如:
Vendor Name
。 - (所有)命名空间(Namespace)__可选__根据实际需要,定义多个子命名空间(注意不是必选项)。
- 在加载时,(所有)命名空间(Namespace)的分隔符
\
会转换为目录分隔符DIRECTORY_SEPARATOR
。 - 类名(Class Name)中的
_
会转换为目录分隔符DIRECTORY_SEPARATOR
,但在命名空间(Namespace)_
不具备任何含义(纯粹修饰性)。 - 在加载时,命名空间(Namespace)和类(Class)时,源文件应该以.php为后缀(这条规则其实定义的很笼统)。
- 命名时,命名空间(Vendor Name,Namespace)、类名(Class Name)__应该__由半角英文字母、大小写组合而成。
###演示
return [ '\Doctrine\Common\IsolatedClassLoader' => '/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php', '\Symfony\Core\Request' => '/path/to/project/lib/vendor/Symfony/Core/Request.php', '\Zend\Acl' => '/path/to/project/lib/vendor/Zend/Acl.php', '\Zend\Mail\Message' => '/path/to/project/lib/vendor/Zend/Mail/Message.php',];
###下划线在命名空间和类名的使用
return [ '\namespace\package\Class_Name' => '/path/to/project/lib/vendor/namespace/package/Class/Name.php', '\namespace\package_name\Class_Name' => '/path/to/project/lib/vendor/namespace/package_name/Class/Name.php'];
##PSR-4 类加载器(Autoloader)
- 本文中的类(Class),可指代包括: 类 (Class,这里可以理解为代码上对类定义的结构体)、 接口 (Interface)、 特征 (Trait),等与之相似的结构体。
- 类全称(the fully qualified class name),如右侧所示
\<顶级命名空间>(\<子级命名空间>)*\<类名>
- 类全称__务必__拥有一个顶级命名空间,常见的如 “Vendor namespace”。
- 类全称__可以__有一个或者多个子命名空间名。
- 类全称__务必__以一个类名(ClassName)终结。
- 下划线
_
不再具有任何指义(区别于 PSR-0#5)。 - 类全称中的英文字母,__可以__由大小写任意组合而成。
- 所有类名在引用时,__务必__遵守其命名的大小写风格。
- 加载(类源文件)时的一致性规则:
- 前缀映射规则:将类全称中的命名空间前缀,去掉最左边的分隔符
\
,映射到一个__基础目录__上去(注意这里所说的命名空间前缀,可以指单个命名空间前缀,也可以是多个命名空间前缀,比如Acme\Log指向一个目录,再把Acme\Log\Writer指向另外一个目录)。 - 前缀映射剩余的子命名空间,__务必__与他所映射的__基础目录__下的目录结构一一对应(这里只说目录结构,不说文件命名)。
- 类源文件需以
.php
为结尾,且__务必__与类命名大小写吻合。
- 前缀映射规则:将类全称中的命名空间前缀,去掉最左边的分隔符
- 类加载器(Autoloader),__绝不__抛出任何异常、任意级别的错误、返回任意的结果。
##看法
PSR-0其实是一个完全没有约束力的规范,因为从第三点开始,已经完全给不出有力的修饰词。
PSR-4就务实多了,从Standard转为er。不过这个前缀映射法,从AgiMVC 3我就开始在玩了,但说实在的,这个东西就是个鸡肋。为啥这么说呢?
PSR-4中的前缀映射,是无限映射,假定我有个类全称是 \My\Sub1\Sub2\Sub3\ClassA
,我将 My\Sub1\Sub2
指向了目录1,将 My\Sub1
指向了目录2,那么在引用这个类的时,loadClass应该如何设计呢?最直接的做法就是,从 My\Sub1\Sub2\Sub3
开始匹配,那么到 My\Sub1\Sub2
时候,我就命中了目录1。天哪,假如我的定义的命名空间很多的话,这个匹配,需要走多少次循环呢?所以就算是Composer也不得不提供一个优化的参数,把一个类库的所有定义的类都做一个枚举。
项目刚开始的时候,我们可能真的需要无限量的空间,但是进入到具体的开发环节,所有的一切都是具体得不能再具体的了。
或者说,这就是PHP语言本身的失败的地方所在,他坚定不移的走在微软无限抄的道路上,但却不给出任何具体的语言规范,乃至更先进一点的加载机制,而把所有的一切都让给了他身后的诸多山寨框架联盟——PSR联盟。
Composer和PSR把所有傻帽坑爹耗性能的事情都一股脑的扣在了PHP这个性能最差的开发语言上……
前些日子用node.js做了一些东西,真心觉得node.js的包机制明确而具体。PHP就不能学学node.js吗,哎,被后来的小弟超越了,PHP啊,你也该甩甩你的老包袱了吧?