日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

PHP笔记-自定义MVC框架

發布時間:2025/3/15 php 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP笔记-自定义MVC框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

膜拜

膜拜下黑馬大佬程序員的項目,學習到了這樣的手寫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

總結

以上是生活随笔為你收集整理的PHP笔记-自定义MVC框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。