写自己的php框架(二)

继续框架之旅(ps:已经忘了上次写的时候的思路了...)。目前我们已经有了大概的物理目录了,先来写一个控制器吧,这个是用来控制网站运行方式的。这样说貌似不清楚...控制器主要就是分析uri路径,然后按照这个路来调用执行类,来达到控制网站运行的目的。
<?php
/**
*framework\models\controller.class.php
*/
class Controller {
    public function __Construct() {
       
        $request = $_SERVER['REQUEST_URI'];
        $url =  'http://' . $_SERVER ['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
       
        //判断url是否合法
        if (! filter_var($url, FILTER_VALIDATE_URL,FILTER_FLAG_SCHEME_REQUIRED)){
             //这里面是要做错误日志log记录的 本着简单原则 略…… 以后类似得同样略
            $request = '/'; //不合法则使用根目录
        }
               
        $splits = explode('/', trim($request, '/')); // 用/分解uri
       
        $tmp = explode('.', trim($splits[0], '.'));
        $splits[0] = $tmp[0];
        if(!empty($splits[1])){
            $tmp = explode('.', trim($splits[1], '.'));
            $splits[1] = $tmp[0];
        }
       
       
        $this->_Controller = !empty($splits[0]) ? $splits[0] : 'index'; //不存在的话默认index
        $this->_Act

ion = !empty($splits[1]) ? $splits[1] : 'loadindex';//不存在的话默认loadindex

        if(!empty($splits[2])) { //如果目录中存在更长的参数路径
            $keys = $values = array();
            for($idx=2, $cnt = count($splits); $idx<$cnt; $idx++) {
                if($idx%2 == 0){
                    //Is even, is key
                    $keys[] = $splits[$idx];
                } else {
                   //Is odd, is value
                    $values[] = $splits[$idx];
                }
            }
            $this->_Params = array_combine($keys, $values);
            //var_dump($this->_Params);
        }
    }

    public function Route() {
        
        $this->loadControllerClass();
        if(!class_exists($this->GetController())) {
            if ($this->GetController() == 'error') {
                throw new Exception('Not Find error Class', E_USER_ERROR);
            } else {
                #类不存在 页面不存在 log 略……
                $url = 'http://' . $_SERVER ['HTTP_HOST'] . '/error'; //假定网站已经完成了error的页面
                header('Location:'.$url);
            }
        }
       
        if ($rc = new ReflectionClass($this->GetController())) {
           
            if($rc->implementsInterface('IController')) {
               
                if(!$rc->HasMethod($this->GetAction())){
                   
                    //重定向浏览器 到上一层 基类地址
                    $url = 'http://' . $_SERVER ['HTTP_HOST'] . '/' . $this->_Controller;
                    header('Location:' . $url);
                   
                    //确保重定向后,后续代码不会被执行
                    /**
                    *@todo 如果这里使用了session则应该先关闭
                    */
                    exit;
                }
               
                if($rc->HasMethod($this->GetAction())) {
                    $controller = $rc->NewInstance();
                    $method = $rc->GetMethod($this->GetAction());
                    $this->SetBody($method->Invoke($controller));
                } else {
                    throw new Exception("Action");
                }
               
            } else {
                throw new Exception("Interface");
            }
           
        } else {
            throw new Exception("controller");
        }
    }

    /**
        *负责读取class文件,生成类定义
        *@todo 这里是否存在随意调用用户提供名字的文件的漏洞
        */
    public function LoadControllerClass() {
       
        $classFile = './application/controllers/' . $this->_Controller .'.php';
        //var_dump($classFile);
        if (file_exists($classFile)){
            include($classFile);
        }else {
           //error log 略…
            if ($this->_Controller != 'error'){
                $this->_Controller = 'error'; //重新定向到error类  
                $this->LoadControllerClass();
            }
        }
    }

/**
* 获得执行类名
*@return string  Class Name
*/
    public function GetController() {
        return $this->_Controller;
    }
 
   /**
    *获得参数值
    *@return string
    */
    public function GetParams() {
        return $this->_Params;
    }
 
/**
*获得执行函数
*@return string  Class Method
*/
    public function GetAction() {
        return $this->_Action;
    }
   
/**
*获得网页内容
*@return string html body
*/
    public function getBody() {
        return $this->_Body;
    }
   
    public function setBody($body) {
        $this->_Body = $body;
    }
    
    protected $_Controller;    //控制类
    protected $_Action;    //执行方法
    protected $_Params;    //获得的url参数
    protected $_Body;     //输出体
}

控制器主要任务就是分析uri的路径名 并且拆分开了 然后分解成类名与执行函数名,这里做了一个小小的url验证,用到了php标准库的filter_var函数。
http://127.0.0.1/index/
将被分解为          $this->_Controller ='index';        $this->_Action = 'loadindex';
因为action不存在 则自动赋值loadindex这个初始值。
然后下面开始调用这个类,通过loadControllerClass 来include 目录为 application/controllers/下的同类名php文件( application/controllers/index.php)。然后开始调用这个类并执行。这里用到了php的反射机制 ,如果没研究过可以看看手册 。调用过程中程序还检查了这个类是否是 IController接口类。
IController接口很简单
interface IController{
    public function loadindex();
}
保证类拥有loadindex 的接口函数。  保存controller.php
framework\models\controller.class.php

不知道个脚本能否正常运行,肯定要改改才行估计。我原来这个类写的是singleton模式,构造函数用的是private。不过想想没什么必要,反正自己用,这里顺手就改回来了..还有日志记录等等这些让我删掉不少,。主要是避免分散注意力。不过大致思路已经有了。另外关于这个反射,为什么非要用反射呢? 明天有空改成直接调用看看效果-_-;
资料来源:http://uuzhang.blog.163.com/blog/static/3514603120103705940228/
posted @ 2011-10-04 16:13  舍本  阅读(794)  评论(0编辑  收藏  举报