php mvc原理实例

mvc目录结构

/mvc
    - app
        - constroller
            - IndexController.php
        - model
            - StudentModel.php
        - view
            - index.tpl
            - students.tpl
    - config
        - config.php
    - core
        - App.php
        - Controller.php
        - Model.php
        - PdoMysql.php
        - SmartySetup.php
    - public
    - runtime
        - cache
        - templates_c
    - vendor
        - smarty
    index.php

单一入口文件index.php

<?php
//添加入口标识
use core\App;


define('ACCESS',true);

//定义根目录
define('ROOT_PATH',str_replace('\\','/',__DIR__.'/'));


//加载初始化文件
include './core/App.php';


//激活入口
App::start();

核心文件

/core/App.php

<?php

namespace core;

//安全判断
if (!defined('ACCESS')) {
    header('location:../index.php');
    exit;
}

class App
{
    //入口方法
    public static function start()
    {
        //设置路径常量
        self::setPath();
        //设置配置文件
        self::setConfig();
        //设置错误
        self::setError();
        //解析URL
        self::setUrl();
        //注册自动加载类
        self::setAutoload();
        //分发控制器
        self::setDispatch();
    }

    //设置路径常量
    private static function setPath()
    {
        define("CORE_PATH", ROOT_PATH . 'core/');
        define("APP_PATH", ROOT_PATH . 'app/');
        define("CONTROLLER_PATH", APP_PATH . 'controller/');
        define("MODEL_PATH", APP_PATH . 'model/');
        define("VIEW_PATH", APP_PATH . 'view/');
        define("VENDOR_PATH", ROOT_PATH . 'vendor/');
        define("CONFIG_PATH", ROOT_PATH . 'config/');
        define("RUNTIME_PATH", ROOT_PATH . 'runtime/');
    }

    //设置配置文件
    private static function setConfig()
    {
        global $config;
        $config = include CONFIG_PATH . 'config.php';
    }

    //设置错误
    private static function setError()
    {
        global $config;
        @ini_set('error_reporting', $config['system']['error_reporting']);
        @ini_set('display_errors', $config['system']['display_errors']);

    }

    //解析URL
    private static function setUrl()
    {
        $c = $_REQUEST['c'] ?? 'Index';
        $a = $_REQUEST['a'] ?? 'index';
        define('CONTROLLER', $c);
        define('ACTION', $a);
    }

    //自动加载方法
    private static function set_autoload_function($class)
    {
        $class = explode('\\', trim($class));
        $class = end($class);

        //核心类
        $file = CORE_PATH . $class . '.php';
        if (file_exists($file)) include $file;

        //控制器类
        $file = CONTROLLER_PATH . $class . '.php';
        if (file_exists($file)) include $file;

        //模型类
        $file = MODEL_PATH . $class . '.php';
        if (file_exists($file)) include $file;

        //插件类
        $file = VENDOR_PATH . $class . '.php';
        if (file_exists($file)) include $file;
    }

    //注册自动加载类
    private static function setAutoload()
    {
        spl_autoload_register([__CLASS__, 'set_autoload_function']);
    }

    //分发控制器
    private static function setDispatch()
    {
        try {
            $c = ucfirst(CONTROLLER);
            $controller = "\\controller\\{$c}Controller";
            $c = new $controller();

            $a = ACTION;
            $a = explode('-', $a);
            $a = implode('',$a);
            //可变类
            $c->$a();//可变方法
        } catch (\Exception $e) {
            echo $e->getMessage();
        }
    }
}

/core/Controller.php

<?php
namespace core;

use Exception;

class Controller{
    //smarty对象变量
    private $smarty;

    /**
     * 初始化controller相关
     */
    public function __construct()
    {
        $this->smarty = SmartySetup::getInstance();
    }

    //分配变量到模板
    public function assign($key,$value){
        $this->smarty->assign($key,$value);
    }

    //显示模板
    public function display($file){
        try {
            $this->smarty->display($file);
        } catch (Exception $e) {
            die($e->getMessage());
        }
    }
}

/core/Model.php

<?php
namespace core;

class Model{
    public $pdo;

    public function __construct()
    {
        global $config;
        //实例化
        $this->pdo = new PdoMysql($config['database']);
    }

    public function getPdo(){
        return $this->pdo;
    }

}

/core/PdoMysql.php

<?php
namespace core;

use PDO;

class PdoMysql{

    protected $link;

    protected $options =[
        'table'=>'',
        'fields'=>'*',
        'order'=>'',
        'limit'=>''
    ];

    //初始化
    public function __construct($config)
    {
        $this->connect($config);
    }

    //连接MySQL
    protected function connect(array $config){
        $dsn = sprintf("mysql:host=%s;dbname=%s;charset=%s", $config['host'], $config['database'], $config['charset']);
        $this->link = new PDO($dsn, $config['user'], $config['password']);
        $this->link->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    }

    //查询
    public function query(string $sql, array $values=[]){
        $query = $this->link->prepare($sql);
        $query->execute($values);
        return $query->fetchAll();
    }

    //执行
    public function execute(string $sql, array $values = []){
        $query = $this->link->prepare($sql);
        return $query->execute($values);
    }

    //表名
    public function table(string $table){
        $this->options['table'] = $table;
        return $this;
    }

    //查询字段
    public function fields(...$fields){
        $fields = '`'. implode('`,`',$fields).'`';
        $this->options['fields'] = $fields;
        return $this;
    }

    //limit
    public function limit(...$limit){
        $limit = implode(',',$limit);
        $this->options['limit'] = " limit " . $limit;
        return $this;
    }

    //order
    public function order(string $order){
        $this->options['order'] = " order by " . $order;
        return $this;
    }

    //条件
    public function where(string $where){
        $this->options['where'] = " where " . $where;
        return $this;
    }

    //查询语句生成器
    public function get(){
        //select * from student where order limit

        $sql = "select {$this->options['fields']} from {$this->options['table']} {$this->options['where']} {$this->options['order']} {$this->options['limit']}";
        return $this->query($sql);
    }

    //插入
    public function insert(array $values){
        //insert into student () values ();
        $fields = "`" . implode('`,`',array_keys($values)) . "`";
        $placeholders = implode(',',array_fill(0,count($values),'?'));
        $sql = "insert into {$this->options['table']} ($fields) values ($placeholders)";

        return $this->execute($sql,array_values($values));
    }

    //更新
    public function update(array $values){
        //update student set name=?,age=?
        if(empty($this->options['where'])){
            throw new \Exception('update需要条件');
        }
        $fields = implode('=?,',array_keys($values))."=?";
        $sql = "update {$this->options['table']} set ($fields) {$this->options['where']}";
        return $this->execute($sql,array_values($values));
    }

    //删除
    public function delete(){
        //delete fromm student where
        if(empty($this->options['where'])){
            throw new \Exception('delete需要条件');
        }
        $sql = "delete from {$this->options['table']} {$this->options['where']}";
        return $this->execute($sql);
    }
}

/core/SmartySetup.php

<?php
namespace core;

use Exception;

class SmartySetup
{
    //单例对象
    private static $instance;

    private function __construct(){}

    //smarty单例
    public static function getInstance(){
        if (!self::$instance) {
            $file = ROOT_PATH . 'vendor/smarty/Smarty.class.php';
            require_once($file);

            self::$instance = new \Smarty();

            self::$instance->setTemplateDir(ROOT_PATH . 'app/view/');
            self::$instance->setConfigDir(ROOT_PATH . 'configs/');
            self::$instance->setCompileDir(ROOT_PATH . 'runtime/templates_c/');
            self::$instance->setCacheDir(ROOT_PATH . 'runtime/cache/');

            self::$instance->caching = \Smarty::CACHING_LIFETIME_CURRENT;
        }
        return self::$instance;
    }
}

配置文件夹config

/config/config.php

<?php
return [
    'database' => [
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => 'root',
        'database' => 'php',
        'charset' => 'utf8'
    ],
];

控制器 Controller

/app/controller/IndexController.php

<?php
namespace controller;


use core\Controller;
use model\StudentModel;

class IndexController extends Controller{
    public function index(){
        $name = '简单mvc';
        $this->assign('name',$name);
        $this->display('index.tpl');
    }

    //获取学生列表
    public function getStudents(){
        $student = new StudentModel();
        $students  = $student->pdo->table('student')->limit(10)->get();

        $this->assign('students',$students);
        $this->display('students.tpl');
    }

}

模型 Model

/app/model/StudentModel.php

<?php
namespace model;

use core\Model;

class StudentModel extends Model {

    public function getStudent(){
        echo 'student';
    }
}

视图view

/app/view/index.tpl

index模板<br>

{$name}

/app/view/students.tpl

学生列表:<br>

<ul>
    {foreach $students as $student}
        <li>{$student.id} | {$student.name} | {$student.age}</li>
    {/foreach}
</ul>

第三插件插件 vendor

/vendor/smarty 下载smarty,复制libs文件夹到vendor下,命名为smarty

https://github.com/smarty-php/smarty/archive/refs/heads/master.zip

数据库模拟数据

php > student

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `age` smallint(6) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;


BEGIN;
INSERT INTO `student` VALUES (1, '张三', 23);
INSERT INTO `student` VALUES (2, '李四', 23);
INSERT INTO `student` VALUES (9, '小花', 27);
INSERT INTO `student` VALUES (4, '小红', 23);
INSERT INTO `student` VALUES (8, '梁梅', 33);
INSERT INTO `student` VALUES (6, '李五毛', 24);
INSERT INTO `student` VALUES (7, '王小红', 26);
INSERT INTO `student` VALUES (10, '小花', 27);
INSERT INTO `student` VALUES (12, '李五', 24);
INSERT INTO `student` VALUES (13, '王小红', 26);
INSERT INTO `student` VALUES (14, '李五', 24);
INSERT INTO `student` VALUES (15, '王小红', 26);
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

浏览器访问控制器

/mvc/index.php?c=index&a=index

/mvc/index.php?c=index&a=get-students

posted @ 2021-07-02 15:16  胡勇健  阅读(173)  评论(0)    收藏  举报