This article mainly introduces the implementation of MVC structure micro-framework in PHP source code. It has certain reference value. Now I share it with you. Friends in need can refer to it.
Main:
Constant optimization path
Auto-loading class
Optimization entry file
Secure Access Project Directory
##
---------------------------------------------------- blog ├─App │ ├─Model 模型 │ │ └─UserModel.class.php 用户模型类 │ ├─View 视图 │ │ ├─Back后台 │ │ │ └─Index │ │ │ └─index.html 后台首页面 │ │ └─Home前台 │ │ └─User 用户视图目录 │ │ └─login.html 登录表单页面 │ ├─Controller 控制器 │ │ ├─Back后台 │ │ │ └─IndexController.class.php 后台首页控制器 │ │ └─Home前台 │ │ └─UserController.class.php 用户控制器 ├─Public 静态公共文件(js,css,images) │ ├─Plugins 插件 │ │ └─layui 前端框架插件 │ ├─Back后台 │ │ ├─js/ js文件 │ │ ├─css/ css样式文件 │ │ └─image img图片 │ └─Home前台 │ ├─js/ js文件 │ ├─css/ css样式文件 │ └─image img图片 ├─Frame 公共使用的类 │ ├─BaseModel.class.php 数据库连接类 │ ├─BaseController.class.php 控制器公共操作(设置编码,信息跳转) │ ├─FactoryModel.class.php 模型工厂类 │ ├─Init.class.php 初始化应用类 │ └─MySQLDB.class.php 数据库操作工具类 └─index.php 入口文件 -----------------------------------------------------------------
Download and view the source code of the project: https://gitee.com/NewbiesYang/young_blog
Constant optimization path
1 $ git checkout master 2 $ git checkout -b "MVC"
3) When loading the view, use constants to replace part of the path, such as include VIEW.'login.html' Simple form
step 1: 在入口文件中定义所需要的常量 step 2: 控制器中引入视图时, 使用常量进行优化
2) Define common path constants in the entry file 【index.php】
1 <?php 2 /** 3 * 入口文件 4 */ 5 $p = !empty($_GET['p']) ? $_GET['p'] : 'Home'; //平台 6 $c = !empty($_GET['c']) ? $_GET['c'] : 'User'; //控制器 7 $a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //动作 8 9 define('PLAT', $p); //平台常量 10 define('CTR', $c); //控制器 11 define('ACTION', $a); //动作 12 13 14 define('DS', DIRECTORY_SEPARATOR); //目录分割符 15 define('ROOT', getcwd().DS); //当前所在目录 项目目录 16 define('FRAME', ROOT.'Frame'.DS); 17 define('APP', ROOT.'App'.DS); 18 define('PUB', ROOT.'Public'.DS); 19 define('ADMIN', PUB.'Admin'.DS); 20 define('HOME', PUB.'Home'.DS); 21 22 //MVC目录 23 define('MODEL', APP.'Model'.DS); 24 define('VIEW', APP.'View'.DS.PLAT.DS.CTR.DS); 25 define('CTRONLLER', APP.'Controller'.DS.PLAT.DS); 26 27 $ctr = $c."Controller"; 28 29 require_once FRAME.'Db.class.php'; //数据库操作类 30 require_once FRAME.'BaseModel.class.php'; //基础模型类 31 require_once MODEL.'UserModel.class.php'; //用户模型类 32 require_once FRAME.'FactoryModel.class.php';//模型工厂类 33 require_once FRAME.'BaseController.class.php'; //基础控制器类 34 require_once CTRONLLER.$ctr.'.class.php'; 35 36 37 //实例化控制器 38 $userCtr = new $ctr(); 39 40 $userCtr -> $a();
2) Use of constants:
Background home page controller [App/Controller/Admin/IndexController.class .php】
1 <?php 2 /** 3 * IndexController控制器类 4 * 后台相关操作 5 * User: young 6 */ 7 8 class IndexController extends BaseController 9 { 10 //展示后台首页 11 public function index() 12 { 13 include VIEW.'index.html'; 14 } 15 }
User controller login view introduction path【 App/Controller/Home/UserController.class.php】
1 <?php 2 /** 3 * UserController.class.php 用户控制器 4 */ 5 6 class UserController extends BaseController{ 7 /** 8 * 展示登录界面 9 * @access public 10 */ 11 public function login() 12 { 13 include VIEW."login.html"; 14 } 15 。。。 16 。。。 17 。。。
3) Submit code
$ git add -A $ git commit -m "常量使用"
Auto-loading class
IdeaSolution: Automatically load class files
Method 1: Use the automatic loading class function __autoload() to achieve automatic loading
Method 2: In actual projects, multiple people develop, according to Practicality, more is to use sql_autoload_register() registration function to automatically load
Implement automatic loading according to the characteristics of the directory
Controller file features: Class name ending with Controller, substr($class,-10)
Public class: There is no unified form of class name, you can put the public classes under Fame into the array, Then determine whether the class is in the array, thereby automatically loading the class file in the directory
1 <?php 2 /** 3 * 入口文件 4 */ 5 $p = !empty($_GET['p']) ? $_GET['p'] : 'Home'; //平台 6 $c = !empty($_GET['c']) ? $_GET['c'] : 'User'; //控制器 7 $a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //动作 8 9 define('PLAT', $p); //平台常量 10 define('CTR', $c); //控制器 11 define('ACTION', $a); //动作 12 13 14 define('DS', DIRECTORY_SEPARATOR); //目录分割符 15 define('ROOT', getcwd().DS); //当前所在目录 项目目录 16 define('FRAME', ROOT.'Frame'.DS); 17 define('APP', ROOT.'App'.DS); 18 define('PUB', ROOT.'Public'.DS); 19 define('ADMIN', PUB.'Admin'.DS); 20 define('HOME', PUB.'Home'.DS); 21 22 //MVC目录 23 define('MODEL', APP.'Model'.DS); 24 define('VIEW', APP.'View'.DS.PLAT.DS.CTR.DS); 25 define('CTRONLLER', APP.'Controller'.DS.PLAT.DS); 26 27 $ctr = $c."Controller"; 28 29 spl_autoload_register('autoload'); //注册自动加载函数 30 //自动加载类 31 /** 32 * 实自动加载类文件 33 * @param string $className 类名 34 */ 35 function autoload($className) 36 { 37 $upperClassName = strtoupper($className); 38 $frame = array('BaseController','BaseModel','Db','FactoryModel'); 39 if(in_array($className, $frame)) { //加载公共Frame目录中的类文件 40 require_once FRAME."$className.class.php"; 41 } elseif(substr($upperClassName, -5) == 'MODEL'){ //加载模型Model目录中的类文件 42 require_once MODEL."$className.class.php"; 43 } elseif(substr($upperClassName, -10) == 'CONTROLLER'){ //加载控制器目录中的类文件 44 require_once CTRONLLER."$className.class.php"; 45 } 46 } 47 48 //实例化控制器 49 $userCtr = new $ctr(); 50 $userCtr -> $a();
2) Submit code
1 $ git add -A 2 $ git commit -m "自动加载类完成"
Optimize entry file
IdeaSolution: Encapsulate the entry file The operation is called a class, so you only need to call the class method in the entry file
Create the Init.class.php class file and put it into the Frame
Encapsulate all operations of the entry file into classes Method loadClass() using using using using using ’ ’ ’ s using ’ ’ s ’ through ’ s ’ through ’ s through ‐ to ‐‐‐‐‐ and to
# 1) Create the Init.class.php file in the Frame directory, copy the code in the entry file index and modify it to the class
[Frame/Init.class.php]
1 <?php 2 /** 3 * 应用初始化操作类 4 * User: young 5 */ 6 7 class Init 8 { 9 protected static $frame = array('BaseController','BaseModel','Db','FactoryModel'); //Frame目录公共操作类 10 public static function run() 11 { 12 //平台 13 self::dispatch(); 14 15 //定义常量 16 self::setConst(); 17 18 //自动加载类 19 self::loadClass(); 20 21 $ctr = CTR."Controller"; //拼接控制器名称 22 23 //实例化控制器 24 $ctrObj = new $ctr(); 25 $a = ACTION; 26 $ctrObj -> $a(); 27 } 28 /** 29 * 设置自动加载类方法 30 */ 31 private static function loadClass() 32 { 33 spl_autoload_register('self::autoload'); 34 } 35 36 /** 37 * 实现自动加载 38 * @param string $className 类名 39 */ 40 private static function autoload($className) 41 { 42 $upperClassName = strtoupper($className); 43 if(in_array($className, static::$frame)) { 44 require_once FRAME."$className.class.php"; 45 } elseif(substr($upperClassName, -5) == 'MODEL'){ 46 require_once MODEL."$className.class.php"; 47 } elseif(substr($upperClassName, -10) == 'CONTROLLER'){ 48 require_once CTRONLLER."$className.class.php"; 49 } 50 } 51 52 /** 53 * 定义常量 54 */ 55 private static function setConst() 56 { 57 define('DS', DIRECTORY_SEPARATOR); //目录分割符 58 define('ROOT', getcwd().DS); 59 define('FRAME', ROOT.'Frame'.DS); 60 define('APP', ROOT.'App'.DS); 61 define('PUB', ROOT.'Public'.DS); 62 define('ADMIN', PUB.'Admin'.DS); 63 define('HOME', PUB.'Home'.DS); 64 65 66 define('MODEL', APP.'Model'.DS); 67 define('VIEW', APP.'View'.DS.PLAT.DS.CTR.DS); 68 define('CTRONLLER', APP.'Controller'.DS.PLAT.DS); 69 } 70 71 /** 72 * 获取 p c a 的GET值,并设置为常量 73 * @return void 74 */ 75 private static function dispatch() 76 { 77 $p = !empty($_GET['p']) ? $_GET['p'] : 'Home'; //平台 78 $c = !empty($_GET['c']) ? $_GET['c'] : 'User'; //控制器 79 $a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //动作 80 81 define('PLAT', $p); 82 define('CTR', $c); 83 define('ACTION', $a); 84 } 85 }
1 <?php 2 /** 3 * 入口文件 4 */ 5 6 require_once './Frame/Init.class.php'; 7 Init::run();
3) Submit code
1 $ git add -A 2 $ git commit -m "优化入口文件,封装初始化类"
问题: 此时,项目中所有目录都是可以通过浏览器访问的,如直接访问Frame/Db.class.php文件 直接可以去查看数据库登录信息,显然是不安全的。
解决方法:
方式1: 在可以访问的文件开始处定义常量,访问是判断是否定义常量defined(..), 没有定义指定常量则直接exit('Access Deny');
方式2: 开启分布式权限配置,编写.htaccess文件, 如禁止访问, 将该文件放置在禁止访问的目录中
1)使用上述方式2的形式来实现, 站点配置中加入一项(环境搭建时已经加入了): 详细见: PHP源码搭建博客1-环境搭建
apache配置文件httpd-vhosts.conf 中站点配置
1 #允许分布式权限配置(允许重写)(.htacess) 2 AllowOverride All
2) 重启apache后,编写 .htaccess文件, 该文件内容:
deny from all
3) 将.htaccess文件放置禁止访问的目录中。 如App/ , Frame/ 目录下。只用放在第一层即可,内层目录自动不允许直接访问。
4) 访问测试
主要实现了 引入路径优化, 类的自动加载, 封装优化入口文件,目录访问限制
MVC微型框架到此基本完成。其实还有很多还是可以继续扩展,如
1, 类文件命名此处都用了 .class.php结尾, 实质可以优化直接使用.php结尾
2, 引入命名空间,更方便的加载类
3, 项目中出现错误,此时是直接显示在浏览器上的, 可以写一个日志类,发生错误写入文件或数据库都可
4, 数据库连接信息此处是直接写在DB类和BaseModel中了, 是不安全的。 可以创建一个配置目录,将这些信息写入配置文件,再写一个加载配置文件的类。
5. 此架构目录 ,是在C,V中分平台,如Controller/Home, Controller/Admin; 实际也可以写成 平台下分MVC结构, 如Admin/Controller, Admin/Model, Home/Controller,Home/View .. 这个是比较灵活的,可以根据需求选择更加合适的方式
实际上线项目,还是建议使用框架,安全快捷; 自己模仿定义的框架结构适合学习研究使用,容易遗漏,造成安全隐患,操作不便等问题
下一步:根据博客前端模板,分析创建数据表, 开始搭建博客后台程序,后续首先准备实现 “分类模块”。既分类的展示,修改,添加,删除功能
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
The above is the detailed content of PHP source code to implement MVC structure micro-framework. For more information, please follow other related articles on the PHP Chinese website!