PHP笔记-自定义MVC框架

article/2025/9/13 2:45:36

膜拜

膜拜下黑马大佬程序员的项目,学习到了这样的手写MVC框架的方式,受益匪浅,感觉自己在C/C++和Java方面,还有许多要学习的地方,看看能不能抄下这个php自己撸一个C/C++的MVC框架。

下面记录下PHP自定义MVC框架。

项目结构

首先是项目结构:

├─app
│  ├─admin
│  │  ├─controller
│  │  ├─model
│  │  └─view
│  └─home
├─config
├─core
├─public
├─resources
│  └─views
└─vendor└─smarty

解释下:

①app中放业务逻辑,admin代表后台方面的,home代表前台方面的,前台后台都有MVC相关的文件夹;

②config中放了配置文件,一般放与数据库连接相关的配置;

③core中放了核心代码,如管理url、文件路径、加载php中各种类,模型父类,控制父类,Dao层,等一系列主要核心功能;

④public中一般放index.php为整个项目的入口,通过输入的url中的各个参数,调用不同的php类(前台还是后台,哪个controller,哪个函数);

⑤resources中有个views存放smarty编译好的页面;

⑥vendor中存放三方的库,如smarty或验证码或分页或上传文件的php类。

整体运行逻辑

这个程序的切入点为public中的index.php:

 从中可以看到index.php:

<?phpdefine("ROOT_PATH", str_replace("\\", "/", dirname(__DIR__)) . "/");include ROOT_PATH . "core/App.php";\core\App::start();

解释下:

①其中__DIR__为当前文件的路径,如我这里的D:\phpProject\IT1995Blog\public;

②dirname()函数的作用是获取父目录的路径,也就是是把ROOT_PATH定义为了D:\phpProject\IT1995Blog/,再一个str_replace后变为D:/phpProject/IT1995Blog/;

③然后include ROOT_PATH . "core/App.php"就可以获取到正确的App.php路径了,然后就可以调用他的start()静态方法了。

下面进入App看下start()

这里一共调用了5个解释下:

①setPath()函数中设置了项目中文件的各个路径,生成了各个路径的宏,如core_path、app_path、config_path等

②setConfig(),通过setPath()生成的宏,生成配置文件的全局变量。

③setUrl(),浏览器的url里面一般有3个值,一个是p,一个是c,一个是a,他们在程序中都有默认值,可以缺省。他们分别代表p为前台还是后台(home Or admin),c为控制(如调用Student程序中会给他加个Controller),a为行为也就是这个controller的哪个函数。

④setAutoLoadFile(),里面会调用spl_autoload_register为自动注册函数,第一个参数为回调函数,调用是这样的

 其中可以看到,__CLASS__为当前的class名,这里是core\App,这个参数的意思是,代表回调到core\App这个类的,setAutoLoadFile函数。每当有对象被new的时候,就会调用到setAutoLoadFile函数,他的参数是$class,后面我们再来说这个。

⑤setDispath()是则有的。

可知他的P为前台还是后台(home or admin), C为controller,如Student,A为函数,代表调用的Student中的方法,这里创建了一个controller,然后调用了对应的方法。最后返回数据,这就是大体的逻辑。

自动注册

在上面的setAutoLoad中调用了spl_autoload_register,在setDispatch中new中了对象,所以会调用setAutoLoadFile这个回调函数。比如调用的是StudentController,这个StudentController父类是Controller。

PHP的继承中构造函数和C/C++、Java的不一样,很奇特。后面会有博文说明,比如下面这个url:

http://localhost:63343/IT1995Blog/public/index.php?p=admin&c=Student&a=student

调用的是后台(admin),StudentController(c为Student),的student(a为student)函数。

程序结构如下:

那么他的自动注册了如下类。

admin\controller\StudentController

core\Controller(StudentController中继承了他,所以他会用这个)

Smarty_Autoloader(Controller中new了这个)

core\Model(Controller调用了这个)

core\Dao(Model中使用了Dao,Dao层直接查了数据库)

回调函数代码如下:

Model和Dao

先看下Dao中的代码:

<?php
namespace core;use PDO;
use PDOException;class Dao{protected $pdo;public function __construct($databaseInfo = array()){$type = $databaseInfo["type"] ?? "mysql";$host = $databaseInfo["host"] ?? "localhost";$port = $databaseInfo["port"] ?? "3306";$user = $databaseInfo["user"] ?? "root";$password = $databaseInfo["password"] ?? "";$dbName = $databaseInfo["dbName"] ?? "";$charset = $databaseInfo["charset"] ?? "utf8";try{$dsn = $type . ":host=" . $host . ";port=" . $port . ";dbname=" . $dbName . ";charset=" . $charset;$this->pdo = new PDO($dsn, $user, $password);}catch (PDOException $e){echo "数据库连接失败!<br/>";echo "错误文件为:" . $e->getFile() . "<br/>";echo "错误行号为:" . $e->getLine() . "<br/>";echo "错误描述为:" . $e->getMessage();exit;}}public function daoQuery($sql): array{try{$stmt = $this->pdo->query($sql);return $stmt->fetchAll(PDO::FETCH_ASSOC);}catch (PDOException $e){$this->daoException(e);}}public function daoExec($sql){try{return $this->pdo->exec($sql);}catch (PDOException $e){$this->daoException($e);}}private function daoException($e){echo "SQL执行错误!<br/>";echo "错误文件为:" . $e->getFile() . "<br/>";echo "错误行号为:" . $e->getLine() . "<br/>";echo "错误描述为:" . $e->getMessage();exit;}}

这里使用了PDO连接了MySQL数据库,配置文件从$config中读取。直接对数据库进行增删改查。

而Model.php

<?phpnamespace core;class Model{protected $dao;protected $tableName;protected $fields;public function __construct(){global $config;$this->dao = new Dao($config["database"]);$this->getFields();}protected function getFields(){$sql = "DESC {$this->tableName}";$rows = $this->query($sql);foreach($rows as $row){$this->fields[] = $row["Field"];if($row["Key"] == "PRI"){$this->fields["Key"] = $row["Field"];}}}protected function query($sql): array{return $this->dao->daoQuery($sql);}protected function exec($sql){return $this->dao->daoExec($sql);}public function autoInsert($data){$keys = $values = "";foreach($this->fields as $k => $v) {if($k == "Key")continue;if(array_key_exists($v, $data)){$keys .= $v . ",";$values .= "'" . $data[$v] . "'.";}}$keys = rtrim($keys, ",");$values = rtrim($values, ",");$sql = "insert into{$this->tableName}({$keys}) values({$values})";return $this->exec($sql);}public function deleteById($id){if(!isset($this->fields["Key"])){return false;}$sql = "delete from {$this->tableName} where {$this->fields["Key"]} = '{$id}'";return $this->exec($sql);}public function autoUpdate($id, $data){$where = " where {$this->fields['Key']} = '{$id}'";$sql = "update {$this->tableName} set";foreach ($data as $Key => $value){$sql .= $Key . "='" . $value . "',";}$sql = rtrim($sql, ",") . $where;return $this->exec($sql);}public function getById($id){if(!isset($this->fields["Key"])){return false;}$sql = "select * from {$this->tableName} where {$this->fields['Key']} = '{$id}'";return $this->query($sql);}
}

 很好理解,在此不再说明。

Controller和Model

这里要看Controller的子类StudentController.php和StudentModel.php

StudentModel.php

<?phpnamespace home\model;
use core\Model;class StudentModel extends Model{protected $tableName = "student";public function getAllStudents($page = 1, $pageCount = 5): array{$offset = ($page - 1) * $pageCount;$sql = "select id, name, age, sex, email, address, updateTime from {$this->tableName} order by id asc". " limit {$offset}, {$pageCount}";return $this->query($sql);}public function getCounts(): int{$sql = "select count(*) as c from {$this->tableName}";$res = $this->query($sql);return $res["c"] ?? 0;}
}

 从中调用了Dao层,查询数据。

StudentController.php

<?phpnamespace admin\controller;
use core\Controller;
use home\model\StudentModel;class StudentController extends Controller{public function student(){$page = $_REQUEST["page"] ?? 1;$studentModel = new StudentModel();$students = $studentModel->getAllStudents($page);$counts = $studentModel->getCounts();$this->assign("students", $students);$this->assign("counts", $counts);$this->display("student.html");}
}

 展示数据给前端

Controller和smarty和model

Controller.php代码:

<?phpnamespace core;
class Controller{protected $smarty;public function __construct(){include VENDOR_PATH . "smarty/Smarty.class.php";$this->smarty = new \Smarty();$this->smarty->template_dir = APP_PATH . P . "/view/";$this->smarty->compile_dir = RESOURCES_PATH . "views";}protected function assign($name, $value = ""){$this->smarty->assign($name, $value);}protected function display($template = ""){try {$this->smarty->display($template);}catch (\SmartyException | \Exception $e){$e->getMessage();}}
}

通过浏览器出入过来的P,来判断是前台还是后台的view,方便进行display。编译完成的前端放到RESOURCES_PATH . "views"中。

数据库

数据结构:

内容:

结束

程序运行截图:

框架源码打包下载地址:

PHP/IT1995Blog at main · fengfanchen/PHP · GitHub


http://chatgpt.dhexx.cn/article/LAjjxjgq.shtml

相关文章

搭建一个简单的MVC框架

背景 为何要用MVC框架&#xff1f;首先我们知道不用框架的话&#xff0c;在javaweb项目中每个请求都要写一个servlet&#xff0c;并且要在web.xml中对每个servlet类的映射作配置&#xff0c;不方便开发&#xff0c;因此引入MVC框架。 工作原理 简单的说MVC框架就是为了简化开…

Android MVC框架

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、MVC是什么&#xff1f;二、写个简单的例子1.bean2.callback3.interfaces4.model5.ui 优缺点总结 前言 提示&#xff1a;很多教程讲解框架感觉都像说天书一…

MVC框架之SpringMVC

简介 Spring MVC 是 Spring 给我们提供的⼀个⽤于简化 Web 开发的框架。在说Spring MVC前&#xff0c;我们需要了解下什么是MVC架构以及三层架构&#xff1f; 1 MVC 体系结构 三层架构 在 JavaEE 开发中&#xff0c;⼏乎全都是基于 B/S 架构的开发。那么在 B/S 架构中&…

MVC架构简单介绍

一&#xff1a;MVC架构简介 MVC是Model&#xff08;模型&#xff09;view&#xff08;视图层&#xff09;controller&#xff08;控制器&#xff09;这三者的缩写。 在百度百科中是这样介绍的&#xff1a;MVC强制性地使应用程序的输入、处理和输出分开。使用MVC应用程序被分成…

MVC框架详解(资源整理)

一、什么是MVC&#xff1f; MVC是三个单词的首字母缩写&#xff0c;它们是Model&#xff08;模型&#xff09;、View&#xff08;视图&#xff09;和Controller&#xff08;控制&#xff09;。 1、视图 视图(View)代表用户交互界面&#xff0c;对于Web应用来说&#x…

MVC框架

MVC框架 MVC框架——一个理论框架&#xff01;&#xff01;&#xff01;前言——必看1 经典MVC框架2 经典mvc模式就是jspservletJavaBean3 JavaBean4 实际MVC框架应用5 总结 MVC框架——一个理论框架&#xff01;&#xff01;&#xff01; 注意&#xff1a;mvc框架只是理论上的…

dojo介绍

dojo是目前最为强大的js框架&#xff0c;包括ajax,browser,event,widget等跨浏览器API&#xff0c;用dojo写Web OS可谓非常方便。 dojo现在已经4.0了&#xff0c;我自己其实不怎么用dojo&#xff0c;毕竟dojo强大的地方在于界面和特效的封装&#xff0c;可以让开发者快速构建一…

(2)Dojo学习之模块化

引言Dojo之模块化 1定义模块2调用模块3解释dojoConfig的全局变量 总结 1本篇博客代码下载地址Dojo模块化 1.引言 在本篇博客中主要讲解一下如何在dojo中使用模块&#xff0c;如何自定义自己的模块等等&#xff0c;在使用dojo编程的时候&#xff0c;大家一定要转变自己的思想&a…

Dojo 1.6 官方教程: 创建自定义Dojo小部件(Widget)

在这个教程中&#xff0c;我们将会演示如何利用Dojo 和Dijit框架来创建自定义的小部件。 主要会使用到dijit._Widget 和dijit._Templated 基类和mixin。 对dijit框架的基础知识&#xff0c;可以参看前两篇教程 难度&#xff1a;中等 适用Dojo版本&#xff1a; 1.6 作者&#xf…

(3)Dojo学习之Class

引言dojo中的类 1创建一个简单的类2类和模块结合使用3关于类的继承 需求 1需求一2需求二很重要21代码实现22程序出错23程序运行3 需求三 再次介绍require加载模块总结 1本博客代码的下载地址dojo_class 1.引言 说到面向对象&#xff0c;我们就不得不提一下类&#xff0c;在原生…

探索dojo/json

难度&#xff1a;中等 Dojo版本&#xff1a;1.7 原作者&#xff1a;Kris Zyp 译者&#xff1a;Oliver (zhuxw1984gmail.com) 原文链接&#xff1a;http://www.sitepen.com/blog/2012/09/21/exploring-dojojson/ &#xff08;年初翻译过Kris Zyp的另一篇介绍dojo/json的文章&…

dojo是什么?

现在Web端vue、React、Angular大行其道&#xff0c;安卓端js也有React Native等&#xff0c;那么学习dojo有什么意义呢&#xff1f; 有些老的项目还是用的dojo。。。。例如arcgis javascript api等等 https://dojotoolkit.org/documentation/tutorials/1.10/hello_dojo/ 为什…

Dojo入门篇

Dojo是一个JavaScript实现的开源DHTML工具包&#xff0c;Dojo最初的目标是解决开发HTML应用程序中遇到的一些长期存在的问题&#xff0c;然而现在Dojo已经成为了开发RIA应用程序的利器。 Dojo让Web页面具有动态能力&#xff0c;我们可以在其他支持JavaScript的环境中使用Dojo。…

dojo中的类

使用arcgis api for js 4.*进行地图的web前端开发&#xff0c;就不得不与dojo打交道。dojo是一个框架&#xff0c;自成体系&#xff0c;比如它对类的支持&#xff0c;有自己的一套。众所周知&#xff0c;js不是面向对象语言&#xff0c;没有类这一说&#xff0c;都是用函数来模…

dojo学习教程

Dojo 作为最著名的 Ajax 开源项目之一&#xff0c;不仅让 Web 程序员可以免费获得和使用其框架进行 Web 应用的开发&#xff0c;更吸引了大量的开发者对其不断的扩充&#xff0c;开发新的组件。DojoX 就是在这样的开发社区中产生的。DojoX 是一组基于 dojo 的开源项目的集合&am…

Dojo与jQuery综合比较分析

最近Dojo和jQuery双双发布了最新的1.8版本,有着相同版本号的两个Javascript库也有许多核心的相同之处:相同的资源加载机制AMD、相同的选择器 引擎Sizzle等。作为业界知名的Javascript库,Dojo和jQuery在各自领域有着为数众多的拥护者。不过正所谓一把钥匙开一把锁,对一个项目…

Dojo简述

Dojo是一个JavaScript实现的开源DHTML工具包。Dojo的最初目标是解决开发DHTML应用程序时遇到的一些长期存在的历史问题。 【注&#xff1a;DHTML是一种使HTML页面具有动态特性的艺术。DHTML是一种创建动态和交互WEB站点的技术集合。对大多数人来说&#xff0c;DHTML意味着HTML…

ibatis简介

背景 介绍ibatis实现之前&#xff0c;先来看一段jdbc代码: Class.forName("com.mysql.jdbc.Driver"); String url "jdbc:mysql://localhost:3306/learnworld"; Connection con DriverManager.getConnection(url, "root","learnwo…

Ibatis使用

部分参考&#xff1a;https://blog.csdn.net/shixiaoguo90/article/details/49949445 Apache iBatis是当前IT项目中使用很广泛的一个半自动ORM框架&#xff0c;区别于Hibernate之类的全自动框架&#xff0c;iBatis对数据库的操作拥有更加灵活的控制&#xff0c;对于那些经常需…

iBatis-iBatis配置环境(eclipse+mysql)

在使用JAVA框架前要配置其环境&#xff0c;比如使用Hibernate、Struts等都需要对其环境进行配置&#xff0c;当然使用iBatis开发之前&#xff0c;也需要配置iBatis环境。 一、iBatis环境的配置只需三步 1.引入jar包 2.配置sqlMapConfig.xml文件 3.配置SqlMap.xml文件 二、概览i…