自己动手写PHP MVC框架(二)
再来看一下 system/app.php 文件,主要是干嘛的:
<?php
/**
* 应用驱动类
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuanxuxu.com>
* @version 1.0
*/
define('SYSTEM_PATH', dirname(__FILE__));
define('ROOT_PATH', substr(SYSTEM_PATH, 0,-7));
define('SYS_LIB_PATH', SYSTEM_PATH.'/lib');
define('APP_LIB_PATH', ROOT_PATH.'/lib');
define('SYS_CORE_PATH', SYSTEM_PATH.'/core');
define('CONTROLLER_PATH', ROOT_PATH.'/controller');
define('MODEL_PATH', ROOT_PATH.'/model');
define('VIEW_PATH', ROOT_PATH.'/view');
define('LOG_PATH', ROOT_PATH.'/error/');
final class Application {
public static $_lib = null;
public static $_config = null;
public static function init() {
self::setAutoLibs();
require SYS_CORE_PATH.'/model.php';
require SYS_CORE_PATH.'/controller.php';
}
/**
* 创建应用
* @access public
* @param array $config
*/
public static function run($config){
self::$_config = $config['system'];
self::init();
self::autoload();
self::$_lib['route']->setUrlType(self::$_config['route']['url_type']);
$url_array = self::$_lib['route']->getUrlArray();
self::routeToCm($url_array);
}
/**
* 自动加载类库
* @access public
* @param array $_lib
*/
public static function autoload(){
foreach (self::$_lib as $key => $value){
require (self::$_lib[$key]);
$lib = ucfirst($key);
self::$_lib[$key] = new $lib;
}
//初始化cache
if(is_object(self::$_lib['cache'])){
self::$_lib['cache']->init(
ROOT_PATH.'/'.self::$_config['cache']['cache_dir'],
self::$_config['cache']['cache_prefix'],
self::$_config['cache']['cache_time'],
self::$_config['cache']['cache_mode']
);
}
}
/**
* 加载类库
* @access public
* @param string $class_name 类库名称
* @return object
*/
public static function newLib($class_name){
$app_lib = $sys_lib = '';
$app_lib = APP_LIB_PATH.'/'.self::$_config['lib']['prefix'].'_'.$class_name.'.php';
$sys_lib = SYS_LIB_PATH.'/lib_'.$class_name.'.php';
if(file_exists($app_lib)){
require ($app_lib);
$class_name = ucfirst(self::$_config['lib']['prefix']).ucfirst($class_name);
return new $class_name;
}else if(file_exists($sys_lib)){
require ($sys_lib);
return self::$_lib['$class_name'] = new $class_name;
}else{
trigger_error('加载 '.$class_name.' 类库不存在');
}
}
/**
* 自动加载的类库
* @access public
*/
public static function setAutoLibs(){
self::$_lib = array(
'route' => SYS_LIB_PATH.'/lib_route.php',
'mysql' => SYS_LIB_PATH.'/lib_mysql.php',
'template' => SYS_LIB_PATH.'/lib_template.php',
'cache' => SYS_LIB_PATH.'/lib_cache.php',
'thumbnail' => SYS_LIB_PATH.'/lib_thumbnail.php'
);
}
/**
* 根据URL分发到Controller和Model
* @access public
* @param array $url_array
*/
public static function routeToCm($url_array = array()){
$app = '';
$controller = '';
$action = '';
$model = '';
$params = '';
if(isset($url_array['app'])){
$app = $url_array['app'];
}
if(isset($url_array['controller'])){
$controller = $model = $url_array['controller'];
if($app){
$controller_file = CONTROLLER_PATH.'/'.$app.'/'.$controller.'Controller.php';
$model_file = MODEL_PATH.'/'.$app.'/'.$model.'Model.php';
}else{
$controller_file = CONTROLLER_PATH.'/'.$controller.'Controller.php';
$model_file = MODEL_PATH.'/'.$model.'Model.php';
}
}else{
$controller = $model = self::$_config['route']['default_controller'];
if($app){
$controller_file = CONTROLLER_PATH.'/'.$app.'/'.self::$_config['route']['default_controller'].'Controller.php';
$model_file = MODEL_PATH.'/'.$app.'/'.self::$_config['route']['default_controller'].'Model.php';
}else{
$controller_file = CONTROLLER_PATH.'/'.self::$_config['route']['default_controller'].'Controller.php';
$model_file = MODEL_PATH.'/'.self::$_config['route']['default_controller'].'Model.php';
}
}
if(isset($url_array['action'])){
$action = $url_array['action'];
}else{
$action = self::$_config['route']['default_action'];
}
if(isset($url_array['params'])){
$params = $url_array['params'];
}
if(file_exists($controller_file)){
if (file_exists($model_file)) {
require $model_file;
}
require $controller_file;
$controller = $controller.'Controller';
$controller = new $controller;
if($action){
if(method_exists($controller, $action)){
isset($params) ? $controller ->$action($params) : $controller ->$action();
}else{
die('控制器方法不存在');
}
}else{
die('控制器方法不存在');
}
}else{
die('控制器不存在');
}
}
}
我叫它框架驱动类,也许不合适,但是我是这样理解的,它用来启动这个框架,做好一些初始化的工作,下面我来详细分析一下每个方法的功能:
**1.**首先时定义了一些常量,很明了,不解释了
**2.**setAutoLibs 这个方法其实就是设定那些是系统启动时自动加载的类库,类库文件都存放在 SYSLIB_PATH 下面,以 lib开头的,当然这里你可以根据自己的规则来命名
3.autoload 这个方法就是用来引入你要自动加载的类,然后来实例化,用$_lib 数组来保存类的实例,比如$lib[‘route’]system/lib/lib_route.php 中 lib_route 类的实例
**4.**newLib 这个方法是用来加载你自定义的类的,自定义类存放在根目录下的 lib 中,但是自定义的类的文件前缀是你自己定义的,看系统配置文件里面有,我定义的是 my,这样我就可以在 lib 目录下新建一个自定义的类了,比如 my_test.php
<?php
class MyTest {
function __construct() {
echo "my lib test";
}
}
为什么类名这样命名,看下 newLib 方法的实现就知道,其实这些你完全可以定义自己的规则,这个方法会首先去着 lib 下面有没有这个类,如果有就会引入实例化,如果没有就去找系统目录下面的类,有就实例化
**5.**init 就是一个初始化的方法,里面其实就是加载自动加载的类,以及引入核心控制器和核心模型,这个 2 个核心文件过会我们再来分析 **6.**run 方法就是启动这个框架的了,里面的最后 2 步很重要,就是获取 URL 然后拆分成一个数组的形似,然后由 routeToCm 来分发到 Controller 和 Model **7.**routeToCm 很重要,根据 URL 分发到 Controller 和 Model,这个我们过会来说
在 run 方法中
self::$_lib[‘route’]->setUrlType(self::$_config[‘route’][‘url_type’]); //设置url的类型
$url_array = self::$_lib[‘route’]->getUrlArray();//将url转发成数组
好吧,我们来看下 route 的系统类到底做了什么
<?php
/**
* URL处理类
* @copyright Copyright(c) 2011
* @author yuansir <yuansir@live.cn/yuanxuxu.com>
* @version 1.0
*/
final class Route{
public $url_query;
public $url_type;
public $route_url = array();
public function __construct() {
$this->url_query = parse_url($_SERVER['REQUEST_URI']);
}
/**
* 设置URL类型
* @access public
*/
public function setUrlType($url_type = 2){
if($url_type > 0 && $url_type <3){
$this->url_type = $url_type;
}else{
trigger_error("指定的URL模式不存在!");
}
}
/**
* 获取数组形式的URL
* @access public
*/
public function getUrlArray(){
$this->makeUrl();
return $this->route_url;
}
/**
* @access public
*/
public function makeUrl(){
switch ($this->url_type){
case 1:
$this->querytToArray();
break;
case 2:
$this->pathinfoToArray();
break;
}
}
/**
* 将query形式的URL转化成数组
* @access public
*/
public function querytToArray(){
$arr = !empty ($this->url_query['query']) ?explode('&', $this->url_query['query']) :array();
$array = $tmp = array();
if (count($arr) > 0) {
foreach ($arr as $item) {
$tmp = explode('=', $item);
$array[$tmp[0]] = $tmp[1];
}
if (isset($array['app'])) {
$this->route_url['app'] = $array['app'];
unset($array['app']);
}
if (isset($array['controller'])) {
$this->route_url['controller'] = $array['controller'];
unset($array['controller']);
}
if (isset($array['action'])) {
$this->route_url['action'] = $array['action'];
unset($array['action']);
}
if(count($array) > 0){
$this->route_url['params'] = $array;
}
}else{
$this->route_url = array();
}
}
/**
* 将PATH_INFO的URL形式转化为数组
* @access public
*/
public function pathinfoToArray(){
}
}
注意 querytToArray 方法,将将 query 形式的 URL 转化成数组,比如原来是localhost/myapp/index.php/app=admin&controller=index&action=edit&id=9&fid=10 这样的 url 就会被转发成如下的数组
array(
'app' =>'admin',
'controller' =>'index',
'action' =>'edit',
'id' =>array(
'id' =>9,
'fid' =>10
)
)
这下再耐心来看下我写的笨拙的 routeToCm,来通过数组参数来分发到控制器,找到控制器以后还要引用相应的模型,然后就实例化控制器和模型,呵呵,貌似有点成型了。
转载请注明: 转载自Ryan 是菜鸟 | LNMP 技术栈笔记
如果觉得本篇文章对您十分有益,何不 打赏一下
本文链接地址: 自己动手写 PHP MVC 框架(二)
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可