php微框架 flight源碼閱讀——框架初始化、Loader、Dispatcher

在自動加載實現完成後,接着new flightEngine()實例化了下框架的核心類Engine,這個類翻譯過來名字就是引擎發動機的意思,是flight的引擎發動機,很有想象力吧。

public static function app() {
    static $initialized = false;

    if (!$initialized) {
        require_once __DIR__.'/autoload.php';

        self::$engine = new \flight\Engine();

        $initialized = true;
    }

    return self::$engine;
}

在實例化Engine這個類的時候,當前類的構造方法進行了對框架的初始化工作。

public function __construct() {
    $this->vars = array();

    $this->loader = new Loader();
    $this->dispatcher = new Dispatcher();

    $this->init();
}

接着來看init方法都做了什麼,將初始化狀態標記爲靜態變量static $initialized,判斷如果爲true,將$this->vars以及$this->loader$this->dispatcher中保存的屬性重置爲默認狀態。

static $initialized = false;
$self = $this;

if ($initialized) {
    $this->vars = array();
    $this->loader->reset();
    $this->dispatcher->reset();
}    

接下來將框架的Request、Response、Router、View類的命定空間地址register(設置)到Loader類的classes屬性中。

// Register default components
$this->loader->register('request', '\flight\net\Request');
$this->loader->register('response', '\flight\net\Response');
$this->loader->register('router', '\flight\net\Router');
$this->loader->register('view', '\flight\template\View', array(), function($view) use ($self) {
    $view->path = $self->get('flight.views.path');
    $view->extension = $self->get('flight.views.extension');
});  

Loader.php

public function register($name, $class, array $params = array(), $callback = null) {
    unset($this->instances[$name]);

    $this->classes[$name] = array($class, $params, $callback);
}

再接下來就是將框架給用戶提供的調用方法,設置到調度器Dispatcher類的events屬性中。

// Register framework methods
$methods = array(
    'start','stop','route','halt','error','notFound',
    'render','redirect','etag','lastModified','json','jsonp'
);
foreach ($methods as $name) {
    $this->dispatcher->set($name, array($this, '_'.$name));
}

Dispatcher.php

/**
 * Assigns a callback to an event.
 *
 * @param string $name Event name
 * @param callback $callback Callback function
 */
public function set($name, $callback) {
    $this->events[$name] = $callback;
}

接下來呢,就是設置框架的一些配置,將這些配置保存在Engine類的vars屬性中。

// Default configuration settings
$this->set('flight.base_url', null);
$this->set('flight.case_sensitive', false);
$this->set('flight.handle_errors', true);
$this->set('flight.log_errors', false);
$this->set('flight.views.path', './views');
$this->set('flight.views.extension', '.php');

Engine.php

/**
 * Sets a variable.
 *
 * @param mixed $key Key
 * @param string $value Value
 */
public function set($key, $value = null) {
    if (is_array($key) || is_object($key)) {
        foreach ($key as $k => $v) {
            $this->vars[$k] = $v;
        }
    }
    else {
        $this->vars[$key] = $value;
    }
}

最後一步的操作,當調用框架的start方法時,給其設置一些前置操作,通過set_error_handler()和set_exception_handler()設置用戶自定義的錯誤和異常處理函數,如何使用自定義的錯誤和異常函數,可以看這兩個範例:https://segmentfault.com/n/13...
https://segmentfault.com/n/13...。這些操作完成後,將$initialized = true

// Startup configuration
$this->before('start', function() use ($self) {
    // Enable error handling
    if ($self->get('flight.handle_errors')) {
        set_error_handler(array($self, 'handleError'));
        set_exception_handler(array($self, 'handleException'));
    }

    // Set case-sensitivity
    $self->router()->case_sensitive = $self->get('flight.case_sensitive');
});

$initialized = true;

/**
 * Custom error handler. Converts errors into exceptions.
 *
 * @param int $errno Error number
 * @param int $errstr Error string
 * @param int $errfile Error file name
 * @param int $errline Error file line number
 * @throws \ErrorException
 */
public function handleError($errno, $errstr, $errfile, $errline) {
    if ($errno & error_reporting()) {
        throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);
    }
}

/**
 * Custom exception handler. Logs exceptions.
 *
 * @param \Exception $e Thrown exception
 */
public function handleException($e) {
    if ($this->get('flight.log_errors')) {
        error_log($e->getMessage());
    }

    $this->error($e);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章