php手撸轻量级开发(二)框架加载

先上图,有图有真相

1. 加载index文件

index文件是整个项目的唯一入口,任何请求进入项目都是走的index,只是带的参数不一样,然后再在index文件里加载其他文件,相当于把其他文件整个复制到index文件中,但是开发中会更好看。
index.php 文件代码:

<?php
ini_set('display_errors', 'on');//开启或关闭PHP异常信息
date_default_timezone_set('Asia/Shanghai');

define('FD_DS',     DIRECTORY_SEPARATOR);//定制目录符合
define('ROOT',      __DIR__ .               FD_DS);
define('CORE',      ROOT . 'core' .         FD_DS);
define('MODEL',     ROOT . 'model' .        FD_DS);
define('LIBS',      ROOT . 'libs' .         FD_DS);
define('CONFIG',    ROOT . 'config' .       FD_DS);
define('CTRL',      ROOT . 'controller' .   FD_DS);
define('LOGS',      ROOT . 'logs' .         FD_DS);
define('STATIC',    ROOT . 'static' .       FD_DS);

require_once(CORE . 'core.php');

spl_autoload_register('\core\core::load');

require "vendor/autoload.php";

include LIBS . 'function.php';
\core\core::run();

2. 在index文件设置必要信息

ini_set('display_errors', 'on');//开启或关闭PHP异常信息
date_default_timezone_set('Asia/Shanghai');

异常信息和时区信息一定开始设置好,如果是正式的项目,异常在生产haunting是一定要关闭的,可以通过配置文件来控制开发和生产环境的区别。包括如果是前后端不分离的架构,session也需要在这里开启。

3. 引入核心文件和设置自动加载类

require_once(CORE . 'core.php');
spl_autoload_register('\core\core::load');

引入core文件就不说了,引入了才能调用它的类。
spl_autoload_register 这个函数就有意思了,官网这么解释的

spl_autoload_register — 注册给定的函数作为 __autoload 的实现

就是说,php本身有一个机制,在你使用一个类的时候,如果这个文件还没有加载,就通过这个机制去发现一下包含这个类的文件,如果发现了,就加载进来。但是php默认的方法肯定不满足我们的需求,所以需要自己定制一下。
core文件代码:

namespace core;

use core\route;
class core
{
    //存储已经加载的文件
    public static $classArr = array();

    /**
     * 自动加载函数
     * @param $class
     * @return bool
     */
    public static function load($class)
    {
        if (isset($classArr[$class]))
            return true;
        $class = str_replace('\\', '/', $class);
        $file  = ROOT . $class . '.php';
        if (is_file($file)) {
            include $file . '';
            self::$classArr[$class] = $class;
            return true;
        } else {
            return false;
        }
    }

    public static function run()
    {
        $route    = route::Factory();
        $arr      = $route->active();
        $classStr = $arr['ctrl'] . 'Ctrl';
        $file     = CTRL . $classStr . '.php';
        $action   = $arr['action'];
        if (!file_exists($file)) {
            $file   = CTRL . 'indexCtrl.php';
            $action = 'index';
            $classStr = 'indexCtrl';
        }
        include $file;
        $classStr = '\\controller\\'.$classStr;
        $class = new $classStr();

        //公共初始化方法
        $methods = get_class_methods($class);
        foreach ($methods as &$v) {
            $v = strtolower($v);
        }
        if (in_array('init', $methods)) {
            call_user_func_array(array($class, 'Init'), array());
        }
        //运行本来的方法
        if (method_exists($class, $action)) {
            $class->$action();
        } elseif(method_exists($class, 'index')){
            $class->index();
        }else {
            echo 'error';
        }

    }
}

4. 引入composer的自动加载类

require "vendor/autoload.php";

引入这个文件后,我们再去看这个文件的内容

<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInitc3539f052cfb872b6af631934bd5b1d0::getLoader();

这个文件加载了一个叫做autoload_real.php的文件,看名字不难猜出,这个是进一步判断如何自动加载的文件。
调用这个类的getLoader方法,加载了它的自动加载方法,之后我们用composer拉取的第三方库,就也可以自动加载了。

5. 加载常用函数文件

include LIBS . 'function.php';

这个function.php中,我习惯放一些常用的工具函数,比如目前只有的一个debug类,可以调试程序的时候打印一下各种变量的信息。

function debug() {
    if(func_num_args() >= 2) {
        $var = func_get_args();
    }else{
        $var = current(func_get_args());
    }
    echo '<pre>';
    $vardump = false;
    $vardump = empty($var) ? true : $vardump;
    if($vardump) {
        var_dump($var);
    } else {
        print_r($var);
    }
    exit();
}

不要看这个函数没有参数列表,其实它的参数可以是无限的。func_num_args这个方法就可以拿到调用它时传递的参数数组,然后把它打印在web中,随后中断程序。

6. 调用路由方法

\core\core::run();

这个方法先去调用route类,去获取到控制器和方法的名称,然后加载这个类。这里我定义了一个默认的初始化方法,意思是如果有一个名叫init的方法,不管是自己的方法还是继承过来的方法,都要先调用这个方法。这样做的好处是,之后的业务里可以对接口做统一或者单独的初始化或者拦截设置。
core::run()方法,看上边有整个core文件的代码。
调用的route类代码:

namespace core;

class route
{
    private static $in = null;

    private function __construct()
    {

    }

    public static function Factory()
    {
        if (!isset(self::$in)) {
            self::$in = new route();
        }
        return self::$in;
    }

    public function active()
    {
        $ctrl   = 'index';
        $action = 'index';
        if (isset($_SERVER[REQUEST_URI]) && $_SERVER[REQUEST_URI] != '/') {
            $path    = strtok($_SERVER['REQUEST_URI'], '?');
            $patharr = explode('/', trim($path, '/'));
            if (isset($patharr[0])) {
                $ctrl = $patharr[0];
            }
            if (isset($patharr[1])) {
                $action = $patharr[1];
            }
        }
        return array('ctrl'=>$ctrl,'action'=>$action);
    }
}  

所有代码

所有代码都在github上,框架部分在framework分支。

github地址: https://github.com/gaopu1995/hiphp.git

原文地址:https://www.cnblogs.com/alexfly/p/10452964.html

时间: 2024-08-30 07:14:22

php手撸轻量级开发(二)框架加载的相关文章

php手撸轻量级开发(一)

聊聊本文内容 之前讲过php简单的内容,但是原生永远是不够看的,这次用框架做一些功能性的事情. 但是公司用自己的框架不能拿出来,用了用一些流行的框架比如tp,larveral之类的感觉太重,CI也不顺手,于是整体框架就用之前在幕客上看的这个,顺便自己手动改吧改吧,看哪不爽改哪里,一个精简的框架就出来了. 也在做java,但正是php这种能让人一眼看明白的精简的架构吸引了我,没有过多的设计和复杂的实现,整个项目就是明明白白聚焦于业务就好,怎么爽怎么来就好了. 前置的要求 具有一点php的功底.这个

框架开发(五)----自动加载类

一 . 为什么自动加载 自动加载字面的意思就不解释了.我这里自动加载类解析下 是自动加载类文件的意思.__autoload方法完全可行,但是不要问为什么,还是用spl_autoload_register.不只是灵活,而且就是灵活,还是灵活,体现在__autoload只能这么命名,spl_auto_register() 能调用不同的函数. 二  自动加载函数原理   通常情况下,一个类的定义都是一个文件,当类与类需要相互引用的时候,就需要include(require)相应的类文件,带来的问题就是

iframe框架加载完成后执行函数

var iframe = document.createElement("iframe"); iframe.src = "http://www.baidu.com/"; if (!/*@[email protected]*/0) { //if not IE iframe.onload = function(){ alert("框架加载完毕."); }; } else { iframe.onreadystatechange = function()

HTML5手机端手指滑动上拉加载代码

在线预览   源码下载 HTML5手机端手指滑动上拉加载代码是一款通过jquery实现tab切换和上拉加载更多的效果,适用于手机端页面开发.该特效适用浏览器:360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗. 不支持IE8及以下浏览器. 加入前端爱好者QQ群(123235875) 点击加群,共同交流进度!

ExtJs非Iframe框架加载页面实现

在用Ext开发App应用时,一般的框架都是左边为菜单栏,中间为tab页方式的显示区域.而tab页面大多采用的嵌入一个iframe来显示内容.但是采用iframe方式有一个很大的弊端就是每次在加载一个新的iframe时都要将Ext的核心js,css文件重新加载.由于Ext是一个庞大的类库,这些文件的体积都很庞大,仅仅是ext-all.js就有400多k,所以用iframe方式加载就大大降低了效率.为了能解决这个问题,我推荐使用Ext.Panel的autoload模式进行加载页面.用这种模式加载就可

从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用

标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11717254.html 源代码:https://github.com/lamondlu/DynamicPlugins 前景回顾 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.NET Core MVC的插件

EasyUI1.4.2 DataGrid二次加载的问题

最近在使用EasyUI1.4.2的DataGrid的过程中,发现了两个会二次加载的情况: 第一个是在页面初始化的时候,如果给datagrid指定了URL属性,而且pageNumber属性没有设置为1的时候,就会出现二次加载的情况. 第二个是条件查询的时候,填上条件之后,直接点击分页栏的左右按钮,这个时候,会产生两次请求,第一次请求是正常的带条件的请求,第二次请求是请求URL属性设置的地址,最后表格中的数据也是请求URL属性设置的地址返回的结果. 解决方案: 第一个问题比较好解决,将pageNum

手机端和PC端分别加载不同的js文件

分手机端和PC端其实方法很多,我们在响应式设计.响应式网站建设中经常碰到此类需求.下面说说我们在项目中遇到的需求: 手机端和PC端分别加载不同的js客服代码(注意:是要在PC和手机端分别加载不同的js文件) 第一种方法(简单型): <script type="text/javascript"> // 根据屏幕尺寸 if (screen && screen.width > 480) { document.write('<script type=&q

laravel框架加载静态资源注意事项

laravel框架加载静态资源 要注意路径问题,一般静态资源都保存在public目录下 默认访问的路径就指向public目录,用 / 表示public目录 静态资源加载示例: <link href="/admin/css/bksystem.css" rel="stylesheet" type="text/css" /> bksystem.css文件存放在public目录下的admin目录下的css文件下面,这里最前面的/千万不要省略否