• PHP核心之MVC项目架构


    • GitHub地址:https://github.com/wing1377/PHP-

    入口文件

    # index.php
    <?php
    require './Framework/Core/Framework.class.php';
    Framework::run();
    ?>
    

    框架文件

    # Framework/Core/Framework.class.php
    <?php
    class Framework{
        //启动框架
        public static function run(){
            self::initConst();
            self::initConfig();
            self::initRoutes();
            self::initAutoLoad();
            self::initDispatch();
        }
        //定义路径常量
        private static function initConst(){
            define('DS', DIRECTORY_SEPARATOR);  //定义目录分隔符
            define('ROOT_PATH', getcwd().DS);  //入口文件所在的目录
            define('APP_PATH', ROOT_PATH.'Application'.DS);   //application目录
            define('CONFIG_PATH', APP_PATH.'Config'.DS);
            define('CONTROLLER_PATH', APP_PATH.'Controller'.DS);
            define('MODEL_PATH', APP_PATH.'Model'.DS);
            define('VIEW_PATH', APP_PATH.'View'.DS);
            define('FRAMEWORK_PATH', ROOT_PATH.'Framework'.DS);
            define('CORE_PATH', FRAMEWORK_PATH.'Core'.DS);
            define('LIB_PATH', FRAMEWORK_PATH.'Lib'.DS);
            define('TRAITS_PATH', ROOT_PATH.'Traits'.DS);
        }
        //引入配置文件
        private static function initConfig(){
           $GLOBALS['config']=require CONFIG_PATH.'config.php';
        }
        //确定路由
        private static function initRoutes(){
            $p=$_GET['p']??$GLOBALS['config']['app']['dp'];
            $c=$_GET['c']??$GLOBALS['config']['app']['dc'];
            $a=$_GET['a']??$GLOBALS['config']['app']['da'];
            $p=ucfirst(strtolower($p));
            $c=ucfirst(strtolower($c));		//首字母大写
            $a=strtolower($a);			//转成小写
            define('PLATFROM_NAME', $p);    //平台名常量
            define('CONTROLLER_NAME', $c);  //控制器名常量
            define('ACTION_NAME', $a);      //方法名常量
            define('__URL__', CONTROLLER_PATH.$p.DS);   //当前请求控制器的目录地址
            define('__VIEW__',VIEW_PATH.$p.DS);     //当前视图的目录地址
        }
        //自动加载类
        private static function initAutoLoad(){
            spl_autoload_register(function($class_name){
                $namespace= dirname($class_name);   //命名空间
                $class_name= basename($class_name); //类名
                if(in_array($namespace, array('Core','Lib')))   //命名空间在Core和Lib下
                    $path= FRAMEWORK_PATH.$namespace.DS.$class_name.'.class.php';
                elseif($namespace=='Model')     //文件在Model下
                    $path=MODEL_PATH.$class_name.'.class.php';
                elseif($namespace=='Traits')    //文件在Traits下
                    $path=TRAITS_PATH.$class_name.'.class.php';
                else   //控制器
                    $path=CONTROLLER_PATH.PLATFROM_NAME.DS.$class_name.'.class.php'; 
                if(file_exists($path) && is_file($path))
                    require $path;
            });
        }
        //请求分发
        private static function initDispatch(){
            $controller_name='Controller\'.PLATFROM_NAME.'\'.CONTROLLER_NAME.'Controller';	//拼接控制器类名
            $action_name=ACTION_NAME.'Action';	//拼接方法名
            $obj=new $controller_name();
            $obj->$action_name();
        } 
    }
    ?>
    

    配置文件

    # Application/Config/config.php
    <?php
    return array(
        //数据库配置
        'database'=>array(),
        //应用程序配置
        'app'=>array(
            'dp' => 'Admin',        //默认平台
            'dc' => 'Products',     //默认控制器
            'da' => 'list'          //默认方法
        )
    );
    ?>
    

    基础模型

    # Framework/Core/Model.class.php
    <?php
    namespace Core;
    //基础模型
    class Model {
        protected $mypdo;
        private $table;             //表名
        private $pk;                //主键
        public function __construct($table=''){
            $this->initMyPDO();
            $this->initTable($table);
            $this->getPrimaryKey();
        }
        //连接数据库
        private function initMyPDO() {
            $this->mypdo= MyPDO::getInstance($GLOBALS['config']['database']);
        }
        //获取表名
        private function initTable($table){
            if($table!='')		            //直接给基础模型传递表名
                $this->table=$table;
            else {				            //实例化子类模型
                $this->table=substr(basename(get_class($this)),0,-5);
            }
        }
        //获取主键
        private function getPrimaryKey() {
            $rs=$this->mypdo->fetchAll("desc `{$this->table}`");
            foreach($rs as $rows){
                if($rows['Key']=='PRI'){
                    $this->pk=$rows['Field'];
                    break;
                }
            }
        }
        //万能的插入
        public function insert($data){
            $keys=array_keys($data);		        //获取所有的字段名
            $keys=array_map(function($key){	        //在所有的字段名上添加反引号
                    return "`{$key}`";
            },$keys);
            $keys=implode(',',$keys);		        //字段名用逗号连接起来
            $values=array_values($data);	        //获取所有的值
            $values=array_map(function($value){	//所有的值上添加单引号
                    return "'{$value}'";
            },$values);
            $values=implode(',',$values);	        //值通过逗号连接起来
            $sql="insert into `{$this->table}` ($keys) values ($values)";
            return $this->mypdo->exec($sql);
        }
        //万能的更新
        public function update($data){
            $keys=array_keys($data);	            //获取所有键
            $index=array_search($this->pk,$keys);	//返回主键在数组中的下标
            unset($keys[$index]);		            //删除主键
            $keys=array_map(function($key) use ($data){
                    return "`{$key}`='{$data[$key]}'";
            },$keys);
            $keys=implode(',',$keys);
            $sql="update `{$this->table}` set $keys where $this->pk='{$data[$this->pk]}'";
            return $this->mypdo->exec($sql);
        }
        //删除
        public function delete($id){
            $sql="delete from `{$this->table}` where `{$this->pk}`='$id'";
            return $this->mypdo->exec($sql);
        }
        //查询,返回二维数组
        public function select($cond=array()){
            $sql="select * from `{$this->table}` where 1";
            if(!empty($cond)){
                foreach($cond as $k=>$v){
                    if(is_array($v)){	            //条件的值是数组类型
                        switch($v[0]){	            //$v[0]保存的是符号,$v[1]是值
                            case 'eq':		        //等于  equal
                                $op='=';
                                break;
                            case 'gt':		        //大于  greater than
                                $op='>';
                                break;
                            case 'lt':
                                $op='<';
                                break;
                            case 'gte':
                            case 'egt':
                                $op='>=';
                                break;
                            case 'lte':
                            case 'elt':
                                $op='<=';
                                break;
                            case 'neq':
                                $op='<>';
                                break;
                        }
                        $sql.=" and `$k` $op '$v[1]'";
                    }else{
                        $sql.=" and `$k`='$v'";
                    }
                }
            }
            return $this->mypdo->fetchAll($sql);
        }
        //查询,返回一维数组
        public function find($id){
            $sql="select * from `{$this->table}` where `{$this->pk}`='$id'";
            return $this->mypdo->fetchRow($sql);
        }
    }
    ?>
    

    连接PDO数据库

    # Framework/Core/MyPDO.class.php
    <?php
    namespace Core;
    class MyPDO{
        private $type;      //数据库类别
        private $host;      //主机地址
        private $port;      //端口号
        private $dbname;    //数据库名
        private $charset;   //字符集
        private $user;      //用户名
        private $pwd;       //密码
        private $pdo;       //保存PDO对象
        private static $instance;
        private function __construct($param) {
            $this->initParam($param);
            $this->initPDO();
            $this->initException();
        }
        private function __clone() {
        }
        public static function getInstance($param=array()){
            if(!self::$instance instanceof self)
                self::$instance=new self($param);
            return self::$instance;
        }
        //初始化参数
        private function initParam($param){
            $this->type=$param['type']??'mysql';
            $this->host=$param['host']??'127.0.0.1';
            $this->port=$param['port']??'3306';
            $this->dbname=$param['dbname']??'data';
            $this->charset=$param['charset']??'utf8';
            $this->user=$param['user']??'root';
            $this->pwd=$param['pwd']??'';
        }
        //初始化PDO
        private function initPDO(){
            try{
                $dsn="{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
                $this->pdo=new PDO($dsn, $this->user, $this->pwd);
            } catch (PDOException $ex) {
                $this->showException($ex);
                exit;
            }
        }
        
        //显示异常
        private function showException($ex,$sql=''){
            if($sql!=''){
                echo 'SQL语句执行失败<br>';
                echo '错误的SQL语句是:'.$sql,'<br>';
            }
            echo '错误编号:'.$ex->getCode(),'<br>';
            echo '错误行号:'.$ex->getLine(),'<br>';
            echo '错误文件:'.$ex->getFile(),'<br>';
            echo '错误信息:'.$ex->getMessage(),'<br>';
        }
        //设置异常模式
        private function initException(){
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
        }
    
        //执行增、删、改操作
        public function exec($sql){
            try{
                return $this->pdo->exec($sql);
            } catch (PDOException $ex) {
                $this->showException($ex, $sql);
                exit;
            }
        }
        //获取自动增长的编号
        public function lastInsertId(){
            return $this->pdo->lastInsertId();
        }
    
        //判断匹配的类型
        private function fetchType($type){
            switch ($type){
                case 'num':
                    return PDO::FETCH_NUM;
                case 'both':
                    return PDO::FETCH_BOTH;
                case 'obj':
                    return PDO::FETCH_OBJ;
                default:
                    return PDO::FETCH_ASSOC;
            }
        }
        //获取所有数据 ,返回二维数组
        public function fetchAll($sql,$type='assoc'){
            try{
                $stmt=$this->pdo->query($sql);  //获取PDOStatement对象
                $type= $this->fetchType($type); //获取匹配方法
                return $stmt->fetchAll($type);
            } catch (Exception $ex) {
                $this->showException($ex, $sql);
            }
        }
        //获取一维数组
        public function fetchRow($sql,$type='assoc'){
            try{
                $stmt=$this->pdo->query($sql);  //获取PDOStatement对象
                $type= $this->fetchType($type); //获取匹配方法
                return $stmt->fetch($type);
            } catch (Exception $ex) {
                $this->showException($ex, $sql);
                exit;
            }
        }
        //返回一行一列
        public function fetchColumn($sql){
            try{
                 $stmt=$this->pdo->query($sql);
                return $stmt->fetchColumn();
            } catch (Exception $ex) {
                $this->showException($ex, $sql);
                exit;
            }
        }
    }
    ?>
    

    子模型

    # Application/Model/ProductsModel.class.php
    <?php
    namespace Model;
    //products模型用来操作products表
    class ProductsModel extends CoreModel{
      
    }
    ?>
    

    子控制器

    # Application/Controller/Admin/ProductsController.class.php
    <?php
    namespace ControllerAdmin;
    // 商品模块
    use CoreController;    //引入基础控制器
    class ProductsController extends CoreController {
        use TraitsJump;
        // 获取商品列表
        public function listAction(){
            // 实例化数据模型
            $model= new ModelProductsModel();
            $list= $model->select();
            // 加载视图
            require __VIEW__.'products_list.html';
        }
        public function delAction(){
            $id= (int)$_GET['proid'];
            $model= new ModelProductsModel();
            if($model->delete($id)){
                $this->success('index.php?p=Admin&c=Products&a=list', '删除成功');
            }else{
                $this->error('index.php?p=admin&c=Products&a=list', '删除失败');
            }
        }
        public function addAction(){
            //执行添加逻辑
            if(!empty($_POST)){
                $model=new CoreModel('products');
                if($model->insert($_POST))
                    $this->success ('index.php?p=Admin&c=Products&a=list', '插入成功');
                else
                    $this->error ('index.php?p=Admin&c=Products&a=add', '插入失败');
            }
            //显示添加页面
            require __VIEW__.'products_add.html';
        }
        public function editAction(){
            $proid=$_GET['proid'];  //需要修改的商品id
            $model=new CoreModel('products');
            //执行修改逻辑
            if(!empty($_POST)){
                $_POST['proID']=$proid;
                if($model->update($_POST))
                    $this->success ('index.php?p=Admin&c=Products&a=list', '修改成功');
                else
                    $this->error ('index.php?p=Admin&c=Products&a=edit&proid='.$proid, '修改失败');
            }
            //显示商品
            $info= $model->find($proid);
            require __VIEW__.'products_edit.html';
        }
    }
    ?>
    

    商品视图

    # Application/View/Admin/products_list.html
    <!Doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>显示商品</title>
    </head>
    <body>
    	<table border='1' width='980' bordercolor='#000'>
    		<a href="index.php?p=Admin&c=Products&a=add">添加商品</a>
    		<tr>
    			<th>编号</th> 
    			<th>名称</th> 
    			<th>价格</th> 
    			<th>删除</th>
    			<th>修改</th>
    		</tr>
    		<?php foreach($list as $rows):?>
    		<tr>
    			<td><?=$rows['proID']?></td>
    			<td><?=$rows['proname']?></td>
    			<td><?=$rows['proprice']?></td>
    			<td><a href="index.php?p=Admin&c=Products&a=del&proid=<?=$rows['proID']?>" onclick="return confirm('确定要删除吗')">删除</a></td>
    			<td><a href="index.php?p=Admin&c=Products&a=edit&proid=<?=$rows['proID']?>">修改</a></td>
    		</tr>
    		<?php endforeach;?>
    	</table>
    </body>
    </html>
    

    添加视图

    # Application/View/Admin/products_add.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>添加商品</title>
    </head>
    <body>
        <form method="post" action="">
            名称: <input type="text" name="proname"> <br />
            价格: <input type="text" name="proprice"> <br />
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    

    更新视图

    # Application/View/Admin/products_edit.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <form method="post" action="">
            名称: <input type="text" name="proname" value='<?=$info['proname']?>'> <br />
            价格: <input type="text" name="proprice" value='<?=$info['proprice']?>'> <br />
            <!--
            <input type="hidden" name="proID" value=<?=$info['proID']?>>
            -->
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    

    启动Session

    # FrameworkLibSession.class.php
    <?php
    namespace Lib;
    class Session{
        private $mypdo;
        public function __construct() {
            session_set_save_handler(
                [$this,'open'],
                [$this,'close'],
                [$this,'read'],
                [$this,'write'],
                [$this,'destroy'],
                [$this,'gc']
            );
            session_start();
        }
        public function open() {
            $this->mypdo= CoreMyPDO::getInstance($GLOBALS['config']['database']);
            return true;
        }
        //关闭会话
        public function close() {
            return true;
        }
        //读取会话
        public function read($sess_id) {
            $sql="select sess_value from sess where sess_id='$sess_id'";
            return (string)$this->mypdo->fetchColumn($sql);
        }
        //写入会话
        public function write($sess_id,$sess_value) {
            $sql="insert into sess values ('$sess_id','$sess_value',unix_timestamp()) on duplicate key update sess_value='$sess_value',sess_time=unix_timestamp()";
            return $this->mypdo->exec($sql)!==false;
        }
        //销毁会话
        public function destroy($sess_id) {
            $sql="delete from sess where sess_id='$sess_id'";
            return $this->mypdo->exec($sql)!==false;
        }
        //垃圾回收
        public function gc($lifetime) {
            $expires=time()-$lifetime;	//过期时间点
            $sql="delete from sess where sess_time<$expires";
            return $this->mypdo->exec($sql)!==false;
        }
    }
    ?>
    

    基础控制器

    # FrameworkCoreController.class.php
    <?php
    //基础控制器
    namespace Core;
    class Controller{
        public function __construct() {
            $this->initSession();
        }
        //初始化session
        private function initSession(){
            new LibSession();
        }
    }
    ?>
    
  • 相关阅读:
    webpack指南(四)shimming
    webpack指南(三)缓存
    webpack指南(二)code spliting+懒加载
    webpack配置篇
    React组件setState
    React 生命周期
    React学习随笔
    @vue/cli 4.0+express 前后端分离实践
    @vue/cli 4.0.5 学习记录
    VMware Workstation 与 Device/Credential Guard 不兼容
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/14155037.html
Copyright © 2020-2023  润新知