构建自己的PHP框架--抽象框架的内容,php框架--抽象
上一篇博客中,我们搭建了一个最简单的框架,从单一入口的public/index.php进入,解析出相应的Controller和Action,去执行,渲染出相应的页面或者输出相应的数据。
但是我们可以看到在public/index.php文件中,是一堆代码,如果之后,我要添加权限/事件等等的机制是不是也要也在这里,那不难想象,不就的将来,index.php就会变成一个巨大无比的php文件。我们当然不想看到这样的情景,所以我们需要将这些内容抽象出来,保持入口文件的简单明了。
那我们要将这些内容抽象到那里去呢?有聪明的同学已经想到了,就是之前在composer.json中定义的位置,我们来看一下composer.json文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span>{
</span> "name" : "craryprimitiveman/simple-framework" <span>,
</span> "description" : "A simple php framework" <span>,
</span> "license" : "MIT" <span>,
</span> "authors" <span>: [
{
</span> "name" : "harrysun" <span>,
</span> "email" : "sunguangjun@126.com" <span>
}
],
</span> "require" <span>: {},
</span> "autoload" <span>: {
</span> "psr-4" <span>: {
</span> "sf\\" : "src/" <span>,
</span> "app\\" : "" <span>
}
},
</span> "repositories" <span>: [
{</span> "type" : "composer" , "url" : "http://packagist.phpcomposer.com" <span>},
{</span> "packagist" : <span>false</span><span>}
]
}</span>
|
登入後複製
可以看到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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?<span>php
namespace sf\base;
</span><span> use </span> <span>Exception</span><span>;
</span><span>
</span>
<span> abstract </span> <span> class </span><span> Application
{
</span><span>
</span>
<span> public </span> <span> $controllerNamespace </span> = 'app\\controllers' <span>;
</span><span>
</span>
<span> public </span> <span> function </span><span> run()
{
</span><span> try </span><span> {
</span><span> return </span> <span> $this </span>-><span>handleRequest();
} </span><span> catch </span> (<span>Exception</span> <span> $e </span><span>) {
</span><span> return </span> <span> $e </span><span>;
}
}
</span><span>
</span>
<span> abstract </span> <span> public </span> <span> function </span><span> handleRequest();
}</span>
|
登入後複製
它是一个抽象类,实现了一个简单的run方法,run方法就是去执行以下handleRequest方法。
它定义了一个抽象方法handleRequest,等待被继承,实现。
它定义了一个controllerNamespace属性,记录controller存放的namesapce,默认值是'app\\controllers'。
再来看在web里的Application.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?<span>php
namespace sf\web;
</span><span>
</span>
<span> class </span> Application <span> extends </span><span> \sf\base\Application
{
</span><span>
</span>
<span> public </span> <span> function </span><span> handleRequest()
{
</span><span> $router </span> = <span> $_GET </span>[ 'r' <span>];
</span><span>list</span>(<span> $controllerName </span>, <span> $actionName </span>) = <span> explode </span>( '/' , <span> $router </span><span>);
</span><span> $ucController </span> = <span>ucfirst</span>(<span> $controllerName </span><span>);
</span><span> $controllerName </span> = <span> $this </span>->controllerNamespace . '\\' . <span> $ucController </span> . 'Controller' <span>;
</span><span> $controller </span> = <span> new </span> <span> $controllerName </span><span>();
</span><span> return </span> <span>call_user_func</span>([<span> $controller </span>, 'action' . <span>ucfirst</span>(<span> $actionName </span><span>)]);
}
}</span>
|
登入後複製
是不是觉得很眼熟,其实就是将之前放在index.php中的内容放到Application的handleRequest方法里了。
然后我们需要从入口文件调用到这里的代码,这就很简单了,index.php的内容如下:
1 2 3 4 5 | <?<span>php
</span><span> require_once </span>(__DIR__ . '/../vendor/autoload.php' <span>);
</span><span> $application </span> = <span> new </span><span> sf\web\Application();
</span><span> $application </span>->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