本篇文章給大家帶來了關于PHP的相關知識,其中主要介紹了關于怎么用PHP實現簡易的MVC框架的相關問題,包括了框架結構簡介以及框架實現等內容,下面一起來看一下,希望對大家有幫助。

一、前言
MVC的全名是Model View Controller,是一種使用模型-視圖-控制器設計和創建web應用程序的模式,是一種設計典范。
其中:
Model(模型):是應用程序中用于處理應用程序數據邏輯的部分,通常負責與數據庫直接進行 curd 的交互。
View(視圖):是應用程序處理數據顯示的部分,通過將處理好的數據進行渲染。
Controller(控制器):是應用程序中處理用戶交互的部分,通常用于處理數據邏輯的分發,并相應的反送給視圖和控制器。
優點:
低耦合
重用性高
部署快,生命周期成本低
可維護性高
缺點:
增加了系統結構和實現的復雜性
視圖與控制器間的過于緊密的連接
二、哪些框架使用到了mvc架構?
目前現在php主流的框架都已經用到了mvc架構,例如:
thinkPHP、Laravel、Yii 都有mvc的架構。
三、框架結構簡介

其中:
app目錄:用來存放視圖控制器模型等。
config目錄:用來存放框架的一些公共配置文件。
core目錄:用來存放一些基類文件,例如:控制器基類、模型基類、視圖基類、request請求基類、db鏈式操作基類等。
static目錄:用來存放一些靜態資源,例如:圖片、html視圖文件、js、cs文件等。
index.php:整個框架的入口文件,進行分發啟動。
四、框架實現第一步(解析路由)
解析路由為什么是第一步呢?
只有成功解析路由以后,訪問到了某個類中的某個方法才可以使用MVC,因為解析路由也是框架實現的最基礎的一部分,解析路由也少不了PHP的自動加載機制
目前的php的自動加載機制可以分為兩大機制,composer自動加載機制和手動實現自動加載機制,該簡易框架通過手動實現自動機制來完成。
4.1 寫入口文件
index.php:
<?php //定義應用目錄 const APP_PATH = __DIR__ . '/'; //加載框架核心文件 require(APP_PATH . 'core/Core.php'); //實例化框架類并運行 (new core\Core())->run();
代碼詳解:
第一步,定義了常量用來定義應用目錄,后期可能會在某個地方就會用到。
第二步,加載框架核心文件 Core.php ,主要的核心邏輯也都集中在這個文件中。
第三步,實例化該類,并調用該類的run方法。
4.2 定義Core核心類
Core.php:
<?php
namespace core;
class Core{
public function run()
{
spl_autoload_register(array($this, 'loadClass'));
$this->route();
}
public function route()
{
$url = $_SERVER['REQUEST_URI'];
$position = strpos($url, '?');
$url = $position === false ? $url : substr($url, 0, $position);
$url = trim($url, '/');
if ($url)
{
//走URL指定控制器
$urlArray = explode('/', $url);
$controllerName = ucfirst($urlArray[count($urlArray)-2]);
$actionName = $urlArray[1];
}else{
//走默認控制器
$controllerName = 'Index';
$actionName = 'index';
}
$versionUrlArr = explode('/',$url);
$versionUrlArr = array_slice($versionUrlArr,0,-2);
$versionStr = implode('\\',$versionUrlArr);
if (empty($versionStr)){
$versionStr = $versionStr;
}else{
$versionStr = $versionStr.'\\';
}
$controller = 'app\\controllers\\'.$versionStr. $controllerName . 'Controller';
if (!class_exists($controller)) {
exit($controller . '控制器不存在');
}
if (!method_exists($controller, $actionName)) {
exit($actionName . '方法不存在');
}
$dispatch = new $controller($controllerName, $actionName);
$dispatch->$actionName();
}
public function loadClass($className)
{
$className = str_replace('\\','/', $className);
$file = $className . '.php';
if (file_exists($file)){
require_once $file;
}
}
}首先調用的是該類的 run 方法,run 方法主要負責調用運行框架所需要 的一些方法,首先注冊了自動加載方法 loadClass,其后調用了的解析路由的方法(這兒是重點,這兒實現了地址欄上輸入接口地址直接訪問控制器)。
注意:路由的解析規則是由我們自己來進行定義的。
代碼詳解:
第一步:注冊自動加載類,目的是為了路由解析、命名空間所使用。
第二步:調用路由解析方法,把地址欄上輸入的 域名/控制器名/方法名 給解析出來,并進行調用。
經過一系列解析后,最終 new 類名,調用方法名,來實現了路由的成功解析,從而訪問了某個類下面的某個方法。
$dispatch = new $controller($controllerName, $actionName);$dispatch->$actionName();
例如,要訪問app\controllers\StudentController.php文件下的 demo 方法:
<?php
namespace app\controllers;
use core\base\Controller;
class StudentController extends Controller{
public function demo()
{
echo '寫代碼的光頭強';
}
}
五、框架實現第二步(MVC的實現)
通過第一步已經完成了地址欄輸入路徑訪問到某個控制器中了,下面就需要在控制器中進行 MVC 操作了。
5.1 控制器的實現
控制器本身是已經實現的,但是我們需要去繼承一個控制器基類在里面實現一些操作,例如:注冊一些全局異常類、注冊一些請求類、控制器之間的互相調用等。
5.2 視圖的實現
視圖基類文件寫到了 core/base/View.php 文件里:
<?php
namespace core\base;
/**
* 視圖基類
*/
class View{
protected $variables = array();
protected $_controller;
protected $_action;
function __construct($controller, $action)
{
$this->_controller = strtolower($controller);
$this->_action = strtolower($action);
}
public function assign($name, $value)
{
$this->variables[$name] = $value;
}
public function render()
{
try {
extract($this->variables);
$file = APP_PATH . 'app/views/' . $this->_controller . '/' . $this->_action . '.php';
if (file_exists($file)){
require_once $file;
}else{
require_once APP_PATH.'core/errorpage/404.html';
}
}catch (\Exception $e){
echo $e->getMessage();
}
}
}代碼詳解:
其中,視圖功能有兩大功能。
第一大功能:傳值(assign)。
我們一般傳值都是通過
$this->assign('name','寫代碼的光頭強');$this->assign('sex','男');這種方法進行傳值。
在框架中實現的方法為:
public function assign($name, $value)
{
$this->variables[$name] = $value;
}很明顯的可以看出,將所有的鍵值對放到了一個數組中。
第二大功能:視圖映射(render)
實現代碼:
public function render()
{
extract($this->variables);
$file = APP_PATH . 'app/views/' . $this->_controller . '/' . $this->_action . '.php';
if (file_exists($file)){
require_once $file;
}else{
require_once APP_PATH.'core/errorpage/404.html';
}
}接收到控制器名方法名,拼接到自定義視圖解析規則地址上,直接引入即可。
5.3 模型的實現
實現模型的靈魂就是要控制器名作為表名來使用。
控制器中:
$data = ['name' => 'tom'];$model = new StudentModel();$model->addData($data);
自定義的模型中:
<?php
namespace app\models;
use core\base\Model;
class StudentModel extends Model{
protected $table = 'student';
public function addData($data)
{
$this->add($data);
}
}模型基類:
<?php
namespace core\base;
use core\db\Orm;
class Model extends Orm{
protected $table;
public function __construct()
{
echo $this->table;
}
public function add($data){
//處理添加邏輯
}
}在模型基類中我們可以自定義orm來完成與數據庫的交互操作
以上只是介紹了最簡易的MVC實現案例,實現MVC框架沒有固定的實現方法,根據框架特色和語言特點以及自己的需求進行實現即可。






