zoukankan      html  css  js  c++  java
  • 制作自己的MVC框架(二)——启动

    自己写了个框架,取名为“PrimusPHP”,就3个文件夹,log中是日志文件,会自动生成。

    app中就是控制器和视图,public中是入口文件和静态资源,library中既有框架的核心类,还有工具类,数据操作类等。

    这个框架会用到命名空间,PHP版本如果不能用命名空间,将不能执行。

    一、单一入口

    index.php”就是入口文件,“defined.php”设置一些通用常量,例如绝对目录,并且引入了初始化库。

    define('ROOT', dirname(dirname(__FILE__)));
    define('DS', DIRECTORY_SEPARATOR);
    
    require_once LIB_PATH . DS . 'init.php';

    index.php”就是在执行初始化方法。

    require_once '../defined.php';
    define('APP_NAME', 'weixin');
    define('CONFIG_PATH', APP_PATH . DS . APP_NAME . DS . 'conf');
    
    InitPrimus::getInstance();

    二、初始化

    private function __construct() {
            $this->environment();//环境配置
            $this->reporting();//错误报告
            self::loadFunction(self::$config['autoload']['helper']);//加载辅助函数
            $this->_autoload();//自动载入
            self::openLog(); //开启log
            self::loadClass('librarycoreRouter');//路由
    }

    1)环境配置

    通常会有三个配置环境,本地、测试和正式。

    以前曾经把三个环境的参数写在一个文件中,然后版本控制的时候忽略文件,这样做很不方便。

    尤其是在发布版本的时候,如果要变里面的参数,还得记得在哪里改。

    现在直接分三个文件,各自管各自的,谁也影响不到谁。

    library”中有三个配置文件,在“app”中也放在“conf”方便自行控制。

     

    如何判断当前环境是本地、测试还是正式环境呢?

    这里我将这个变量埋在了“.htaccess”中,如果是nginx,也可以配置。

    RewriteEngine on
    SetEnv ENVIRONMENT local

    2)错误报告

    错误提示在调试的时候很有用,能定位到具体的行数,能提高修正效率。

    在网上搜索了一下,找到了一些代码,再借鉴了CI的错误代码,嫁接到这个框架里。

    set_error_handler('exception_error_handler');//追踪错误栈
    register_shutdown_function('catch_fatal_error');//致命错误

    exception_error_handler”和“catch_fatal_error”是两个函数,写在了“core/Common.php”中。

    在“library/view”中预留了三种错误的模版页面。

    在URL中输入“index/sign”错误的样子如下:

    3)加载辅助函数

    框架中,经常会有一些函数或类,在一开始就被载入进来,这里的这个辅助函数就是这个道理。

    在配置文件中预先写好要载入的文件名。

    public static function loadFunction($name) {
            if(is_array($name)) {
                foreach ($name as $key) {
                    include_once HELPER_LIB_PATH .  DS . $key . '_helper.php';
                }
            }else {
                include_once HELPER_LIB_PATH .  DS . $name . '_helper.php';
            }
    }

    4)自动载入

    当“new libraryxx()”某个类的时候,会自动进入到“spl_autoload_register”函数中。

    在回调函数中将“libraryxx”修改为具体路径,在“include_once”进来,就初始化好了。

    private function _autoload() {
            //$className是通过命名空间获取的
            spl_autoload_register(function ($className) {
                $dir = false;
                $classNames = explode('\', $className);//分割为数组
                $autoDirs = self::$autoDirs;
                foreach ($autoDirs as $path) {
                    $tmpInfo = pathinfo($path);
                    if(in_array($tmpInfo['basename'], $classNames)) {
                        $dir = $tmpInfo['dirname'];
                        break;
                    }
                }
    
                if($dir) {
                    $file = $dir . DS . dir_replace_ds($className) . '.php';
                    include_once($file);
                }
            });
    }

    5)日志

    平时开发的时候,我喜欢将查询语句直接打印到日志中,当将代码放到线上了,也能调试各个语句的结果。

    最近在做微信开发,有很多请求微信的服务器,这些请求的结果只能通过打印日志看到。

    日志的类放在了“util/Log.php”中。

    public function write($txt) {
            if(empty($txt) || !DEVELOPMENT_ENVIRONMENT) {
                return;
            }
            $name = date('Y-m-d') . '.log';
            if(!file_exists(LOG_PATH)) {
                mkdir(LOG_PATH, 0777, true);
            }
            $path = LOG_PATH . DS . $name;
            $content = date('Y-m-d H:i:s') . ' ' . $txt . "
    ";
            file_put_contents($path, $content, FILE_APPEND);
    }

    三、路由

    1)路由选择

    路由支持两种,一种就是“index/index”,另外一种是“v1/index/index”。

    第二种可以用于客户端接口,当客户端更新版本的时候,可能就需要新的接口,而老的接口又不能丢,就可以新开一个模块文件夹。

    $params = explode('/', $uri);
            if(count($params) == 2) {
                $controller = $params[0];//控制器
                $action = $params[1];//操作方法
            }elseif(count($params) == 3) {
                $module = $params[0]; //模块
                $controller = $params[1];//控制器
                $action = $params[2];//操作方法
            }else {
                $controller = 'index';
                $action = 'index';
            }

    2)路由重定向

    以前没注意到重定向,最近在做微信开发的配置文件的时候就发现这个功能。

    访问“bridge.js”其实是访问了某个控制器的“action”,怪不得我在想那些微信token都是通过服务器获取的,这个js文件是怎么搞到的。

    重定向规则可以用正则表达式。

    $init_conf['rewrite'] = array(
        '/new_bridge.js/' => 'index/config',
        '/new_bridge2.js/' => 'index/config2',
        '/p/(d+)/' => 'index/ticket?p=$1'
    );

    下面是正则匹配:

    public function rewrite() {
            $config = InitPrimus::getConfig('rewrite');
            foreach ($config as $src => $redirect) {
                //$pattern = '@^/?' . $src . '/?$@';
                if (preg_match($src, $this->uri)) {
                    $this->uri = preg_replace($src, $redirect, $this->uri);
                    break;
                }
            }
    }

    框架地址:

    https://github.com/pwstrick/PrimusPHP

  • 相关阅读:
    关于BlockingQueue
    关于java的线程
    mongodb的锁和高并发
    innodb的锁和高并发
    mysql的事务隔离级别及其使用场景
    mongodb分页
    ReentrantLock和Synchronized
    spring boot MVC
    svn 入门
    多线程的返回值等问题
  • 原文地址:https://www.cnblogs.com/strick/p/5770221.html
Copyright © 2011-2022 走看看