(2)php框架开发---控制器开发

参考Thinkphp3.2的代码,在之前的框架开发中又发现了一些问题。所以在这里又重构了一次代码。因为一开始没有使用到控制器,所以没有发现之前的写法有很大的问题。

具体文件如下图:


这里面Dphp.php文件其实就是index.php入口文件主要载入的一个文件,这个文件主要是用来配置一些服务器的常量的。

Dphp.php

<?

define('DPHP_PATH',__DIR__.'/');    //核心文件根路径

define('PROJECT_PATH',dirname($_SERVER['SCRIPT_FILENAME']).'/');    //项目根路径
define('APP_PATH',PROJECT_PATH.'app/');//应用目录
define('CORE_PATH',realpath(DPHP_PATH.'core').'/'); //核心库文件
define('CONF_PATH',realpath(DPHP_PATH.'conf').'/'); //初始化变量配置文件
define('TEMPLATE_PATH',realpath(DPHP_PATH.'template').'/'); //模板库文件
define('RUNTIME_PATH',realpath(DPHP_PATH.'runtime').'/'); //运行文件

//加载核心类
require_once CORE_PATH.'dphp.php';

//开始
\Dphp\core\dphp::start();

然后,配置完常量后就可以非常方便的使用关于文件的路径问题了。之后就是载入dphp.php文件的start静态方法。

dphp.php

<?php
namespace Dphp\core;

class dphp{

    //类映射
    private static $_map = array();
    //实例化对象
    private static $_instance = array();

    public static function start(){

        // 注册AUTOLOAD方法
        spl_autoload_register('\Dphp\core\dphp::autoload');

        app::run();
    }

    //类自动加载
    public static function autoload($class){
            #echo '<br/>'.__FILE__.'<br/>';
            echo '<br/>'.'自动加载了'.$class.'<br/>';

                @include_once $class.'.php';
    }

    //取得对象实例
    static public function instance($class,$method=''){
        $identify = $class.$method;
        if(!isset(self::$_instance[$identify])){
            if(class_exists($class)){
                $o = new $class();
                if(!empty($method) && method_exists($o,$method)){
                    self::$_instance[$identify] = call_user_func(array(&$o,$method));
                }else{
                    self::$_instance[$identify] = $o;
                }
            }else{
                //错误处理 do something
            }
        }

        return self::$_instance[$identify];
    }

}

这里面有两个参数用来保存方法和对象,然后就是类的自动载入一系列的常用函数。在start里面用一个app::run的静态方法,所以之后就是转到应用的类里面执行。

app.php

namespace Dphp\core;

class app{


    static public function run(){
        
        //url
        dispatcher::dispatch();

        //执行相应目录下的模块-控制器-方法
        app::exec();
    }

    static public function exec(){
        $class = 'app\\'.MODULE_NAME.'\\controller\\'.CONTROLLER_NAME;
        echo '<br/>';
        echo $class;
        echo '<br/>';
        echo '准备创建控制器了';
        echo '<br/>';
        //检测是否存在当前的类
        if(class_exists($class)) {
            $c = new $class();
            echo '创建控制器了';
        }
    }
}

上面的start函数会执行路由解析函数,用来判断应该访问什么文件。

dispatcher.php

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/18
 * Time: 19:15
 */

namespace Dphp\core;

class dispatcher{
    //url映射到控制器
    static public function dispatch(){
        @$path_info = $_SERVER['PATH_INFO'];
        //路径判断是否为空
        if(empty($path_info)){
            $varModule = 'home';
            $varController = 'index';
            $varAction = 'index';
            $urlCase = '';
            echo '0';
        }else{
            echo '1';
            //去除首尾的'/'
            $path_info = trim($path_info,'/');
            //以/为分隔符,分配给数组
            $url = explode('/',$path_info);

            $varModule = $url[0];
            $varController = $url[1];
            $varAction = $url[2];
            //$urlCase = ;
        }
        //定义全局变量
        define('MODULE_NAME',$varModule);
        define('CONTROLLER_NAME',$varController);
        define('ACTION_NAME',$varAction);

    }
}

这里面使用$_SERVER['PATH_INFO']来获取当前的m,v,c的名字,然后再使用define将值传递出去。这样子我们就获得了一个路径了。然后就是app里面继续执行exec函数。这个函数就是要new出一个控制器,这里默认是index控制器。

index.php控制器

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/20
 * Time: 21:42
 */

namespace app\home\controller;

class index extends \Dphp\core\controller{

    public function __construct()
    {
        parent::__construct();
        echo '来到index控制器'.'<br/>';
        $this->display();
    }

}

在app::exec函数里我们采用new 命名空间的形式,所以这里面的命名空间要符合应用文件夹里面的路径,不然会找不到文件的。

之后继承了基本控制器Controller就能够使用smarty模板来输出网页信息了。

控制器的制作就完成了。

效果如下:






2017.9.25


在继续开发框架的过程中,我发现原来我一开始写的控制器存在着一个非常大的问题。那就是无法访问控制器的其它方法函数,因为我的演示是在构造函数里面所以一开始没有发现这个问题。之后,在了解thinkphp的代码的时候,发现可以使用反射的方法来实现函数的调用。

在这我新添加了一个route类。

<?php
/**
 * Created by PhpStorm.
 * User: DMF
 * Date: 2017/9/25
 * Time: 14:06
 */

namespace Dphp\core;


class route
{
    //检查路由信息
    public static function check(){
        self::invoke(ACTION_NAME,'app\\'.MODULE_NAME.'\\controller\\'.CONTROLLER_NAME);
       
    }

    //反射函数
    public static function invoke($name,$className){
        //创建反射方法对象
        $reflect = new \ReflectionMethod($className,$name);
        //获取当前方法的参数
        $params = $reflect->getParameters();
        $args = array();
        //获取要调用方法的实例对象
        $obj = \Dphp\core\dphp::instance($className);
        //遍历参数
        foreach ($params as $param) {
            $args[] = $param->getDefaultValue();
        }

        if(empty($args)){
            return $reflect->invoke($obj);
        }
        else{
            return $reflect->invokeArgs($obj,$args);
        }
    }
}

这个route类就是用来实现函数的调用的,不然只是获取到mvc的名称却无法使用。这个check函数可以放在路由转发的dispatcher 类里面的dispatch方法。

//路由检测
        route::check();

这样子才算真正的实现完成一个控制器。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值