在自動加載實現完成後,接着new \flight\Engine()
自動加載的方式實例化了下框架的核心類Engine,這個類名翻譯過來就是引擎發動機的意思,是flight的引擎發動機,頗有想象力吧。php
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這個類的時候,當前類的構造方法進行了對框架的初始化工做。json
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
中保存的屬性重置爲默認狀態。segmentfault
static $initialized = false; $self = $this; if ($initialized) { $this->vars = array(); $this->loader->reset(); $this->dispatcher->reset(); }
接下來將框架的Request、Response、Router、View類的命定空間地址register(設置)到Loader類的classes屬性中。app
// 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'); });
flight/core/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)); }
flight/core/Dispatcher.phpjsonp
/** * 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屬性中。ui
// 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');
flight/Engine.phpthis
/** * 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...。url
// 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); }
當調用$self->router()
時,會觸發當前類的__call()
魔術方法,經過$this->loader->get($name)
判斷屬性$classes中router索引是否存在,不存在拋出異常,存在就經過$this->loader->load($name, $shared)
去實例化初始化時設置的'\flight\net\Router'
,這裏是工廠模式,接下來的路由文章會詳細分析。
/** * Handles calls to class methods. * * @param string $name Method name * @param array $params Method parameters * @return mixed Callback results * @throws \Exception */ public function __call($name, $params) { $callback = $this->dispatcher->get($name); if (is_callable($callback)) { return $this->dispatcher->run($name, $params); } if (!$this->loader->get($name)) { throw new \Exception("{$name} must be a mapped method."); } $shared = (!empty($params)) ? (bool)$params[0] : true; return $this->loader->load($name, $shared); }
在$this->before()
操做中,會將前置操做設置到Dispatcher類的filters屬性中。這些操做完成後,將$initialized = true
。
/** * Adds a pre-filter to a method. * * @param string $name Method name * @param callback $callback Callback function */ public function before($name, $callback) { $this->dispatcher->hook($name, 'before', $callback); }
flight/core/Dispatcher.php
/** * Hooks a callback to an event. * * @param string $name Event name * @param string $type Filter type * @param callback $callback Callback function */ public function hook($name, $type, $callback) { $this->filters[$name][$type][] = $callback; }