構建本身的PHP框架--抽象框架的內容

上一篇博客中,咱們搭建了一個最簡單的框架,從單一入口的public/index.php進入,解析出相應的Controller和Action,去執行,渲染出相應的頁面或者輸出相應的數據。php

可是咱們能夠看到在public/index.php文件中,是一堆代碼,若是以後,我要添加權限/事件等等的機制是否是也要也在這裏,那不難想象,不就的未來,index.php就會變成一個巨大無比的php文件。咱們固然不想看到這樣的情景,因此咱們須要將這些內容抽象出來,保持入口文件的簡單明瞭。git

那咱們要將這些內容抽象到那裏去呢?有聰明的同窗已經想到了,就是以前在composer.json中定義的位置,咱們來看一下composer.json文件:github

{
    "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/,這就是咱們要放抽象出的內容的地方。web

有人會問,爲何不直接使用app\\ 做爲namespace呢?由於想到以後要將src下的內容作成一個composer包,遷移到vendor中。json

下面就正式開始抽象了。app

在src下建立兩個文件夾,一個是base,一個是web。base用來存放基礎的類,web用來存放與web相關的類。由於未來框架可能還要支持php腳本的執行,因此要將base和web分開,未來要加php腳本時,只須要創建一個console的文件夾就行了。composer

在兩個文件夾中分別創建Application.php文件。框架

先來看在base裏的Application.phpui

<?php
namespace sf\base;

use Exception;

/**
 * Application is the base class for all application classes.
 * @author Harry Sun <sunguangjun@126.com>
 */
abstract class 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.
     */
    public function run()
    {
        try {
            return $this->handleRequest();
        } catch (Exception $e) {
            return $e;
        }
    }

    /**
     * Handles the specified request.
     */
    abstract public function handleRequest();
}

它是一個抽象類,實現了一個簡單的run方法,run方法就是去執行如下handleRequest方法。this

它定義了一個抽象方法handleRequest,等待被繼承,實現。

它定義了一個controllerNamespace屬性,記錄controller存放的namesapce,默認值是'app\\controllers'。

再來看在web裏的Application.php

<?php
namespace sf\web;

/**
 * Application is the base class for all application classes.
 * @author Harry Sun <sunguangjun@126.com>
 */
class Application extends \sf\base\Application
{
    /**
     * Handles the specified request.
     * @return Response the resulting response
     */
    public function handleRequest()
    {
        $router = $_GET['r'];
        list($controllerName, $actionName) = explode('/', $router);
        $ucController = ucfirst($controllerName);
        $controllerName = $this->controllerNamespace . '\\' . $ucController . 'Controller';
        $controller = new $controllerName();
        return call_user_func([$controller, 'action'. ucfirst($actionName)]);
    }
}

是否是以爲很眼熟,其實就是將以前放在index.php中的內容放到Application的handleRequest方法裏了。

而後咱們須要從入口文件調用到這裏的代碼,這就很簡單了,index.php的內容以下:

<?php
require_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

相關文章
相關標籤/搜索