上一篇博客中,我们搭建了一个最简单的框架,从单一入口的public/index.php进入,解析出相应的controller和action,去执行,渲染出相应的页面或者输出相应的数据。
但是我们可以看到在public/index.php文件中,是一堆代码,如果之后,我要添加权限/事件等等的机制是不是也要也在这里,那不难想象,不就的将来,index.php就会变成一个巨大无比的php文件。我们当然不想看到这样的情景,所以我们需要将这些内容抽象出来,保持入口文件的简单明了。
那我们要将这些内容抽象到那里去呢?有聪明的同学已经想到了,就是之前在composer.json中定义的位置,我们来看一下composer.json文件:
{ name: craryprimitiveman/simple-framework, description: a simple php framework, license: mit, authors: [ { name: harrysun, email: sunguangjun@126.com } ], require: {}, autoload: { psr-4: { sf\\: src/, app\\: } }, repositories: [ {type: composer, url: http://packagist.phpcomposer.com}, {packagist: false} ]}
可以看到autoload里的psr-4里还有个sf\\,他的地址是src/,这就是我们要放抽象出的内容的地方。
有人会问,为什么不直接使用app\\ 作为namespace呢?因为想到之后要将src下的内容做成一个composer包,迁移到vendor中。
下面就正式开始抽象了。
在src下创建两个文件夹,一个是base,一个是web。base用来存放基础的类,web用来存放与web相关的类。因为将来框架可能还要支持php脚本的执行,所以要将base和web分开,将来要加php脚本时,只需要建立一个console的文件夹就好了。
在两个文件夹中分别建立application.php文件。
先来看在base里的application.php
phpnamespace sf\base;useexception;/** * application is the base class for all application classes. * @author harry sun */abstractclass application{ /** * @var string the namespace that controller classes are located in. * this namespace will be used to load controller classes by prepending it to the controller class name. * the default namespace is `app\controllers`. */public$controllernamespace = 'app\\controllers'; /** * runs the application. * this is the main entrance of an application. */publicfunction run() { try { return$this->handlerequest(); } catch (exception$e) { return$e; } } /** * handles the specified request. */abstractpublicfunction handlerequest();}
它是一个抽象类,实现了一个简单的run方法,run方法就是去执行以下handlerequest方法。
它定义了一个抽象方法handlerequest,等待被继承,实现。
它定义了一个controllernamespace属性,记录controller存放的namesapce,默认值是'app\\controllers'。
再来看在web里的application.php
phpnamespace sf\web;/** * application is the base class for all application classes. * @author harry sun */class application extends \sf\base\application{ /** * handles the specified request. * @return response the resulting response */publicfunction handlerequest() { $router = $_get['r']; list($controllername, $actionname) = explode('/', $router); $uccontroller = ucfirst($controllername); $controllername = $this->controllernamespace . '\\' . $uccontroller . 'controller'; $controller = new$controllername(); returncall_user_func([$controller, 'action'. ucfirst($actionname)]); }}
是不是觉得很眼熟,其实就是将之前放在index.php中的内容放到application的handlerequest方法里了。
然后我们需要从入口文件调用到这里的代码,这就很简单了,index.php的内容如下:
phprequire_once(__dir__ . '/../vendor/autoload.php');$application = new sf\web\application();$application->run();
直接去new一个web application的实例,执行run方法就可以了,是不是很简单。
访问一下:http://localhost/simple-framework/public/index.php?r=site/test,你可以看到上一次一样的结果。
好了,今天就先到这里。项目内容和博客内容也都会放到github上,欢迎大家提建议。
code:https://github.com/craryprimitiveman/simple-framework/tree/0.2
blog project:https://github.com/craryprimitiveman/create-your-own-php-framework
以上就介绍了构建自己的php框架--抽象框架的内容,包括了方面的内容,希望对php教程有兴趣的朋友有所帮助。