PHP source code to implement MVC structure micro-framework
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
Preparation: Create a branch
1 $ git checkout master 2 $ git checkout -b "MVC"
1) Define commonly used directory paths as constants. Such as model directory, controller directory, etc.
2) Introduce classes and use defined constants to replace part of the path. Such as include FRAME.BaseModel.class.php 3) When loading the view, use constants to replace part of the path, such as include VIEW.'login.html' Simple form
1) Operation steps
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
IdeaQuestion: In the entry file 6 classes have been introduced by require_once. If you add one, you need to introduce another one, which is easy to miss, repeat and make mistakes.
Solution: 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) The entry file implements automatic loading of the class
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
IdeaProblem: At this time, the entry file code fragmentation increases. With the increase of subsequent code, the entry file will become more bloated and complex and difficult to manage
Solution: 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 }
Copy after login
2) The entry file introduces the initialization class and calls its method [index.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!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Alipay PHP...

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

Session hijacking can be achieved through the following steps: 1. Obtain the session ID, 2. Use the session ID, 3. Keep the session active. The methods to prevent session hijacking in PHP include: 1. Use the session_regenerate_id() function to regenerate the session ID, 2. Store session data through the database, 3. Ensure that all session data is transmitted through HTTPS.

The application of SOLID principle in PHP development includes: 1. Single responsibility principle (SRP): Each class is responsible for only one function. 2. Open and close principle (OCP): Changes are achieved through extension rather than modification. 3. Lisch's Substitution Principle (LSP): Subclasses can replace base classes without affecting program accuracy. 4. Interface isolation principle (ISP): Use fine-grained interfaces to avoid dependencies and unused methods. 5. Dependency inversion principle (DIP): High and low-level modules rely on abstraction and are implemented through dependency injection.

How to debug CLI mode in PHPStorm? When developing with PHPStorm, sometimes we need to debug PHP in command line interface (CLI) mode...

Article discusses essential security features in frameworks to protect against vulnerabilities, including input validation, authentication, and regular updates.

How to automatically set the permissions of unixsocket after the system restarts. Every time the system restarts, we need to execute the following command to modify the permissions of unixsocket: sudo...

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.
