一次无意的访问,点击到了一个专门做PHP性能测试的网站,看这里PHP Benchmarks。
在里面发现了框架性能测试的结果,发现Laravel的框架性能尽然是最低的。瞬间受到了一万点的暴击,谁让最近一直用Laravel开发项目的呢。
说到底还是Laravel好用呀,方便不说,各方面支持的也不错,业务方面做的也是内部系统,哪怕性能慢点,也可以用前后端分离、负载均衡等手段解决掉,大体上也是够用。
不过,作为一个开发人员,理想还是要有的,这时就在想能不能采取Laravel框架的优点,用到什么就装什么,去掉一些请求到响应之间用不到的组件,精简框架。
之前也熟读过Laravel的源码,知道它的底层用的是Symfony的组件,毕竟没必要重复的造轮子。那么我们的框架之旅也将基于Symfony组件。。。
目录一、Composer运行机制
二、框架前期准备
三、HttpFoundation组件封装Request、Response
四、路由处理
五、控制器处理相应功能(C)
六、分离模板(V)
七、分离模型(M)
八、剥离核心代码
九、优化框架
十、依赖注入(Dependency Injection)
正文 一、Composer运行机制Composer的使用最关键的得益于PHP标准规范的出现,特别是其中的psr4,自动加载规范,规范了如何指定文件路径从而自动加载类定义,以及自动加载文件的位置。
既然讲到php文件的加载,我们就要聊一聊PHP的加载机制了。
在早前时,加载文件用的都是include、require,但这种加载有很大的局限性,相信同学们都知道,无论用到用不到都要加载大量的文件,相当繁琐。
于是就出现了autoload加载机制,它可以实现懒加载。
function __autoload($class) { require_once ($class.".php"); }当程序引用了未加载的类,就会自动调用__autoload方法,只要维护了__autoload方法,就可以懒加载文件。
但这里有一个很大的问题,就是程序中只能定义一次__autoload,这就需要花大尽力在__autoload中维护文件和空间的对应关系,特别是在大型项目,多人合作中更是繁琐。
而解决这个问题就是SPL Autoload。
SPL Autoload:__autoload调用堆栈。
怎么理解这个堆栈呢,举个例子。
现有的框架比如ThinkPHP、Laravel等都有一个vendor目录,用于存放第三方库,现在vendor下有两个库。
monolog 处理系统日志
guzzlehttp 处理HTTP
当程序引用这两个库的命名空间,并调用monolog、guzzlehttp下面的类时,发现调用的类文件都能被找到。
这主要原理是monolog、guzzlehttp都自定义了类似autoload的方法,然后用spl_autoload_register将方法注册到了SPL堆栈中。
这样的话,当程序调用类的时候,就会统一到SPL堆栈中寻找注册到堆栈中的autoload方法,并加载相应的文件。
以上就是php加载文件的方式,下面就用实战谈一谈composer的运行机制。
创建composer项目
# mkdir phoenix # cd phoenix composer initphoenix是接下来搭建的框架名。
创建成功后,发现当前文件夹下会生成一个composer.json文件,里面是刚写入的内容。
composer dumptree后,就会发现多了一个vendor的目录,里面的autoload.php以及composer文件夹下文件就是整个框架的加载核心。
接下来看一遍这些文件。
在整个框架中,第一行必然要引用 vendor/autoload.php 文件,毕竟这是加载核心,那么就从autoload.php看起。
# autoload.php require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInit599fa618dd1395bdde5fc3a08ff3e4e6::getLoader();只调用了autoload_real.php里面的getLoader()方法。
#autoload_real.php 精简后的代码 public static function loadClassLoader($class) { if ('Composer\Autoload\ClassLoader' === $class) { require __DIR__ . '/ClassLoader.php'; } } public static function getLoader() { #创建ClassLoader类 spl_autoload_register(array('ComposerAutoloaderInit599fa618dd1395bdde5fc3a08ff3e4e6', 'loadClassLoader'), true, true); #初始化ClassLoader对象(主要就是将命名空间和文件的映射写入ClassLoader的属性中) self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInit599fa618dd1395bdde5fc3a08ff3e4e6', 'loadClassLoader')); #loadClass方法(类似autoload方法)注册到 SPL Autoload $loader->register(true); }autoload_real.php 的作用就是引入ClassLoader类、初始化ClassLoader类,并注册到SPL堆栈中。
ClassLoader类中有很多属性,这些属性的作用也很简单:主要就是方便后面程序快速的通过命名空间找到它所映射的类文件。