结合namespace自己搭建MVC框架

结合namespace自己搭建MVC框架

自定义MVC框架

  1. MVC基本介绍

    MVC是这3个单词的缩写:
    Model:模型,专门用来处理数据的
    View:视图,专门用来显示内容(保存一些html文件)
    Controller:控制器(中控器),用来分发任务
    (命令模型处理数据、命令视图显示数据)

在这里插入图片描述

  1. MVC的目录结构划分原则

    • 将来使用mvc框架的时候,有一些代码是和具体项目的业务相关的,所以我们将这些代码封装到项目的目录里面,通常取名为application,该名称可以自己修改(jd、taobao),除此之外,还有一些代码是公共的(Controller.class.php,Model.class.php等等),这些代码不管做什么项目都可能会用到,我们就将其封装刀片框架目录里面,取名为framework
    • 由于随着框架的不断完善,里面会出现很多有用的工具类,所以为了有效的管理,我们分目录存储
      像smarty这样别人提供,我们就封装到vendor目录,表示别人赞助的
      像Captcha、Page等等,我们自己写的,一些工具,我们就保存到tools目录
      像DAOPDO、I_DAO这些类、接口,和数据访问相关的,保存到dao目录

      在这里插入图片描述
  2. 我们再看应用程序的代码:
    由于应用程序(项目),分为前台、后台;前台是用户浏览使用的,后台是管理员进行内容管理的,所以我们项目的目录结构也就划分为前台home、后台admin:
    由于前台、后台为了提高开发效率,也都会使用mvc进行代码的管理

    在这里插入图片描述

  3. 入口文件(分发控制器)
    入口文件又称之为分发控制器,就像公司的前台,根据访客的需求,将其引导到对应的办公室。在我们的框架里面,入口文件会根据用户的需求,引导到对应的文件
    那么我们需要在入口文件传递什么参数呢?也就是需要告诉前台哪些信息呢?
    (1)去前台还是后台?admin?home
    (2)去哪个控制器?controller?
    (3)访问控制器的哪个方法? 在这里插入图片描述
    代码实现:
    在这里插入图片描述
    注意:
    由于mvc框架里面的类文件,不会直接执行,而是这些类文件最终被index.php加载,也就是说这些类文件再加载的话,都会从index.php这里出发

    访问一下:
    在这里插入图片描述

    在这里插入图片描述
    错误就是说:在Controller.class.php的第10行,没有找到smarty
    原因:Controller这个类也是被CategoryConreoller继承的,最终也是会去index.php报到,所以里面加载文件的时候,出发点也是index.php
    在这里插入图片描述
    项目中还有很多类需要require加载,这是一个很庞大的工作,而且很繁琐,所以我们使用自动加载机制完成这个工作

  4. 自动加载介绍

    • 介绍:
      当我们使用一个类,但是这个类不存在时,就会触发自动加载机制,自动加载机制提供了最后一次机会,可以把类加载过来
      具体的场景:
      New 类,不存在
      类::静态方法时,类不存在
      类 extends 类2,类2不存在
      类 implements 接口,接口不存在
      在这里插入图片描述
      使用自动加载机制的话,之前所有的require_once就没用了,所以需要把所有的require_once统统删掉

      大家自行把所有类里面的require_once都删掉,smarty除外
      在测试的时候,就会报这样一个错误信息:
      在这里插入图片描述
      思考:仅仅通过需要的类名,能够找到这个类吗?
      找不到,因为不知道去哪个目录里面找,可能admin、home;里面都有CategoryController这个类

      如何解决这个问题?

      如果类的前面有所在的位置信息就好了,给每个增加上命名空间,而且让命名空间和该类所在的位置有一定的关联

    • 5.2结合命名空间
      说明:
      (1)入口文件就不用加命名空间了。因为入口文件用来加载其他类,不定义类
      (2)每个类的命名空间包含当前类所在的路径
      例如:框架的成员,命名空间定义为:framework\core,项目的类命名空间就不要携带application了,因为application是项目的名称,后期可能会变化,所以项目的类的命名空间:admin\controller或home\controller等
      (3)第三方的类,我们不用增加命名空间,我们做一个特例处理(手动require)

      给每个类都加上命名空间:

      在这里插入图片描述
      注意:在使用这些类时,需要告诉PHP程序,使用的是哪一个空间的类
      例如:在入口文件中,实例化控制器类的时候,就需要告诉我们实例化的是哪个空间的类
      在这里插入图片描述
      再来测试的时候,就会提示:
      在这里插入图片描述
      这样我们就可以获得类所在位置了

    • 完成自动加载
      思路:
      就是根据提示的需要的类名,解析出他所在的路径
      (1)先根据\,将字符串分割成数组 在这里插入图片描述
      在这里插入图片描述

    由于我们在定义命名空间的时候,
    项目的目录相关的:admin\controller、admin\model、home\controller、
    和框架的路径相关:framework\core、framework\dao
    我们在加载时,也无非就是去这两个目录中找,所以我们判断一下,如果第一个元素是framwork的话,直接去framework目录找,否则去application目录中找

    spl_autoload_register("autoloader");
    function autoloader($className)
    {
        echo '我们需要:'.$className.'<br>';
        //针对第三方的类,做一个特例处理
        if($className=='Smarty'){
            require_once './framework/vendor/smarty/Smarty.class.php';
            return;
        }
        //1. 先将带有命名空间的类,分隔开
        $arr = explode('\\', $className);
        
        //2. 根据第一个元素确定加载的根目录
        if($arr[0] == 'framework'){
            $basic_path = './';
        }else{
            $basic_path = './application/';
        }
        //3. 确定application、framwork里面的子目录
        $sub_path = str_replace('\\', '/', $className);
        
        //4. 确定文件名
        //确定后缀:类文件的后缀:.class.php,接口文件的后缀是:.interface.php
        //framework\dao\I_DAO,判断最后元素是否是I_开头
        if(substr($arr[count($arr)-1], 0,2)=='I_'){
            //说明是接口文件
            $fix = '.interface.php';
        }else{
            $fix = '.class.php';
        }
        $class_file = $basic_path.$sub_path.$fix;
        
        //5. 加载类
        require_once $class_file;
    //     echo '<pre>';
    //     var_dump($class_file);
    }
    

    测试一把:
    在这里插入图片描述
    我们是在Controller基础控制器中初始化的Smarty
    在这里插入图片描述
    由于会在当前空间找Smarty类,所以提示的错误:framework\core\Smarty
    解决之道:smarty属于全局空间,加上\前缀
    在这里插入图片描述
    再来测试:
    在这里插入图片描述
    说明:smarty_internal_data是smarty自己加载的,也不是我们定义的类,所以我们不需要加载
    最终的入口文件自动加载的代码:index.php

    <?php
    /*
     * 入口文件(分发控制器)
     * 用来接收用户请求时携带的参数
     */
    spl_autoload_register("autoloader");
    function autoloader($className)
    {
        echo '我们需要:'.$className.'<br>';
        //针对第三方的类,做一个特例处理
        if($className=='Smarty'){
            require_once './framework/vendor/smarty/Smarty.class.php';
            return;
        }
        //1. 先将带有命名空间的类,分隔开
        $arr = explode('\\', $className);
        
        //2. 根据第一个元素确定加载的根目录
        if($arr[0] == 'framework'){
            $basic_path = './';
        }else{
            $basic_path = './application/';
        }
        //3. 确定application、framwork里面的子目录
        $sub_path = str_replace('\\', '/', $className);
        
        //4. 确定文件名
        //确定后缀:类文件的后缀:.class.php,接口文件的后缀是:.interface.php
        //framework\dao\I_DAO,判断最后元素是否是I_开头
        if(substr($arr[count($arr)-1], 0,2)=='I_'){
            //说明是接口文件
            $fix = '.interface.php';
        }else{
            $fix = '.class.php';
        }
        $class_file = $basic_path.$sub_path.$fix;
        
        //5. 加载类
        //如果不是按照我们的命名空间的规则定义的,说明不是我们需要加载的类,不用加载
        if(file_exists($class_file)){
            require_once $class_file;
        }
    }
    //前台还是后台?
    $m = isset($_GET['m'])?$_GET['m']:'home';
    //访问哪个控制器
    $c = isset($_GET['c'])?$_GET['c']:'Index';
    //访问控制器的哪个操作
    $a = isset($_GET['a'])?$_GET['a']:'indexAction';
    
    $controller_name = 'admin\controller\\'.$c.'Controller';
    
    //先加载控制器类,再实例化对象
    $controller = new $controller_name;
    
    //调用控制器的方法
    $controller -> $a();
    
    
    
    
    
  5. 5.4封装入口文件
    说明:
    入口文件有什么好封装的呢?
    因为我们采用的OOP(面向对象的思想)封装的框架,框架里面的代码都应该是类,然而现在的入口文件index.php是完全面向过程的写法,所以我们要将其封装到类中

    具体代码实现:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  6. 配置系统

    说明:
    配置系统是什么?
    配置文件就是用来保存一些有固定格式、多文件之间的公共的数据
    我们在学习smarty的时候,使用过配置文件来保存图片的信息,这样,如果将来图片的路径变化了,我们只需修改配置文件即可,从而提升了维护的效率
    我们的mvc框架中,怎么增加配置文件呢?

    框架应该有自己的基本的信息,例如,框架的版本、模板引擎的模板目录、定界符等将来都可能修改,所以框架应该有自己的配置文件

    我们的应用程序也会有一些将来可能修改的数据:数据库的信息,所以应用程序也应该有自己的配置文件

    为了灵活起见,我们给前台、后台也增加一些配置文件,目前可能用不到,但是将来可能会用到,所以我们未雨绸缪
    如果同时存在3个配置文件,优先级:
    框架的配置 < 公共的配置 < 前台、后台各自的配置
    在这里插入图片描述

    • 具体实现:
      先创建各自的配置文件:
      在这里插入图片描述
      如何实现优先级高的 覆盖优先级低的配置文件中的相同的配置项,还有一点需要注意:不相同配置项要合并
      既然配置文件返回的是数组,那么我就使用数组函数:array_merge()合并数组的
      有这样一个机制:相同的会被覆盖、不相同的合并
      举例演示:

在这里插入图片描述
在这里插入图片描述
首先,在Framework.class.php中增加3个方法,加载配置文件
因为该文件就相当于入口文件,在这里定义之后,可以在任何地方使用
在这里插入图片描述
拿到配置文件的信息之后,替换、合并
在这里插入图片描述

  1. 具体应用配置文件:
    在初始化MCA的时候,需要设置默认的模块、控制器、方法
    在这里插入图片描述
    数据库连接部分使用我们配置文件中的配置项进行维护、管理
    数据库的连接、初始化是在Model.class.php基础模型类中初始化的
    在这里插入图片描述
    在这里插入图片描述

  2. 路径常量

    说明:
    路径常量是什么?
    框架中,有一些涉及到路径的地方,我们写死的,例如:
    在这里插入图片描述
    如果项目名称后期改变了,我们就需要找到smarty的配置初始化的代码进行修改,我们就可以将项目的名称、路径保存到常量中

在这里插入图片描述
在这里插入图片描述

将使用到项目、框架的路径部分,使用常量代替:

在这里插入图片描述

最后,附带源码
附带源码url

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值