搭建自己的MVC框架

开始写框架

分析框架执行流程

以TinkPHP为参考

localhost/sc/index.php?c=index&a=user
localhost/sc/index.php/index/user
访问的是:index控制器的user方法

搭建框架核心

路由分析:

/x.php :

//获取地址栏信息并分析
//两种方式:
//普通模式
//$_GET['c'];
//PATH_INFO模式
//$_SERVER['PATH_INFO'];

$c = isset($_GET['c'])?$_GET['c']:'';
$a = isset($_GET['a'])?$_GET['a']:'';
if(empty($c) && empty($a)){
    $p = isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:'';
    if(!empty($p)){
        $p = trim($p,'/');
        list($c,$a) = explode('/',$p);
    }
}
if(empty($c) && empty($a)){
    $c = 'index';
    $a = 'index';
}

/x.php

class X{
    public static function auto($classname){
        if(substr($classname,-10) == 'Controller'){
            include APP_PATH.'Controller/'.$classname.'.class.php';
        }
        if(substr($classname,-5)=='Model'){
            include APP_PATH.'Model/'.$classname.'class.php';
        }
    }
}

spl_autoload_register('X::auto');
$c .= 'Controller';
$controller = new $c();
//访问控制器中的方法
$controller->$a();

项目入口文件

xm/index.php

define('APP_PATH',__DIR__.'/');
include ("../xphp/x.php");

项目的控制器

xm/Controller/indexController.class.php

class indexController{
    //控制器中的方法
    public function index(){
        echo 'my index a';
    }
}

继承基类

/x.php

define('X_PATH',__DIR__.'/');
class app{
    public function __construct(){……}
    public function iserror(){……}
    public function sd(){……}
    public function errlog($code,$message,$file,$line){……}

    public static $map = [
        'Controller' => X_PATH.'Care/Controller.php',
        'Model' =>  X_PATH.'Care/Model.php',
    ];
    public static function auto($classname){
        if(isset(self::$map[$classname])){
            include self::$map[$classname];
        }elseif(substr($classname,-10)=="Controller"){
            include APP_PATH.'Controller/'.$classname.'.class.php';
        }elseif(substr($classname,-5)=="Model"){
            include APP_PATH.'Model/'.$classname.'.class.php';
        }
    }

}

基类:

/Care/Controller.php

class Controller{
}

/Care/Model.php

class Model{
}

控制器:

class indexController extends Controller{
    public function index(){
        //调用model类,完成数据处理工作
        $model = new indexModel();
        echo $model->add(1,2);
    }
}

模型:

class indexModel extends Model{
    public function add($n,$m){
        return $n+$m;
    }
}

Model基类

/Care/Model.php

class Model{
    protected $db = '';
    protected $table = '';
    protected $pk = '';
    protected $field = array();
    public function __construct()
    {
        $conf = [
            'dbtype' => 'mysql',
            'host' => 'localhost',
            'dbname'=>'test',
            'user' => 'root',
            'pwd' => '',
            'charset' => 'utf8',
        ];
        $dsn = $conf['dbtype'].':host='.$conf['host'].';dbname='.$conf['dbname'];
        $this->db = new PDO($dsn,$conf['user'],$conf['pwd']);
        $this->db->query('set names '.$conf['charset']);

        $this->getTable();//获取表明
        $this->parseFields();
    }
    //获取 model名,利用model名得到数据库表名
    public function getTable(){
        $classname = get_called_class();
        $this->table = strtolower(substr($classname,0,-5)); //截取后转小写
    }
    //分析数据表,得到表的基本信息
    public function parseFields(){
        $sql = 'desc '.$this->table;
        $tableinfo = $this->db->query($sql);
        $data = $tableinfo->fetchAll(PDO::FETCH_ASSOC);
        foreach($data as $k=>$v){
            $this->field[] = $v['Field'];
            if($v['Key']=='PRI'){
                $this->pk = $v['Field'];
            }
        }
    }

    //查找单条数据
    public function find($id){
        $this->pk;$id;$this->field;
        $sql = 'select * from '.$this->table.' where '.$this->pk.'=? ';
        $stm = $this->db->prepare($sql);
        $stm->execute([$id]);
        $data = $stm->fetch(PDO::FETCH_ASSOC);
        return $data;
    }

}

继续强化Model基类(查询)

/Care/Model.php


    /*
     * 单条数据
     * return array
     * */
    public function getrow($sql,$parms=[]){
        $stm = $this->db->prepare($sql);
        $stm->execute($parms);
        $data = $stm->fetch(PDO::FETCH_ASSOC);
        return $data;
    }
    /*
     * 多条数据
     * return array
     * */
    public function getrows($sql,$parms=[]){
        $stm = $this->db->prepare($sql);
        $stm->execute($parms);
        $data = $stm->fetchAll(PDO::FETCH_ASSOC);
        return $data;
    }

    public function find($id){
        $sql = 'select * from '.$this->table.' where '.$this->pk.'=? ';
        $data = $this->getrow($sql,[$id]);
        return $data;
    }

    public function select(){
        $sql = 'select * from '.$this->table.' where id=? and age=? ';
        $data = $this->getrows($sql,[5,18]);
        return $data;
    }

继续强化Model基类(删除)

/Care/Model.php

    /*
     * 删除数据
     * return int
     * */
    private function delete($sql,$parms=[]){
        $stm = $this->db->prepare($sql);
        if($stm->execute($parms)){
            $data = $stm->rowCount();
        }else{
            $data = $this->db->errorInfo();
        }
        return $data;
    }

     //删除一条数据
    public function remove($id){
        $sql = 'delete from '.$this->table.' where '.$this->pk.'=?';
        return $this->delete($sql,$id);
    }

继续强化Model基类(添加)

/Care/Model.php

    /*执行添加操作*/
    private function insert($sql,$parms=[]){
        $stm = $this->db->prepare($sql);
        if($stm->execute($parms)){
            $data = $this->db->lastInsertId();
        }else{
            $data = $this->db->errorInfo();
        }
        return $data;
    }
    //添加数据
    public function add($data=[]){
        $sql = 'insert into '.$this->table .' (';
        $sql .= implode(',',array_keys($data));
        $sql .= ') values (';
        $sql .= substr(str_repeat('?,',count($data)),0,-1).')';
        return $this->insert($sql,array_values($data));
    }

继续强化Model基类(修改)

/Care/Model.php

    //修改操作
    public function update($sql,$parms=[]){
        $stm = $this->db->prepare($sql);
        if($stm->execute($parms)){
            $conut = $stm->rowCount();
            return $conut;
        }else{
            return $this->db->errorInfo();
        }
    }

    public function save($data=[]){
        if(!isset($data[$this->pk])){
            throw new Exception('缺少主键',500);
        }
        $data_tmp = $data;
        unset($data_tmp[$this->pk]);
        $sql = 'update '.$this->table.' set ';
        foreach($data_tmp as $k=>$v){
            $sql .= $k .'= ? ,';
        }
        $sql = substr($sql,0,-1);
        $sql .= ' where '.$this->pk .'=?';
        $data_tmp[$this->pk] = $data[$this->pk];
        return $this->update($sql,array_values($data_tmp));
    }

魔术方法复习

class T{
    //在给不可访问属性赋值时,__set() 会被调用。
    //读取不可访问属性的值时,__get() 会被调用。
    public function __set($name, $value)
    {
        echo $name.'-----'.$value;
    }
    public function __get($name)
    {
        echo $name;
    }

    //在对象中调用一个不可访问方法时,__call() 会被调用。
    //用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。
    public function __call($name, $arguments)
    {
        echo $name.'-------';
        var_dump($arguments);
    }
    //本身必须是静态
    public static function __callStatic($name, $arguments)
    {
        echo $name.'-------';
        var_dump($arguments);
    }
}
$t = new T();
$t->name;
$t->age = '34';

$t->dd('22','44');
T::a('1','2');

利用魔术方法,实现类似TP的属性赋值
ThinkPHP/Library/Think/Model.class.php

class T{
    private $data = [];
    public function __set($name, $value)
    {
        $this->data[$name] = $value;
    }
    public function __get($name)
    {
        return isset($this->data[$name])?$this->data[$name]:null;
    }
}
$t = new T();
//$t->name;
$t->age = '34';
$t->name = '苍井空';
var_dump($t);

echo $t->name;

将添加操作修改为ORM方式

/Care/Model.php

  //ORM 操作
    private $data = [];
    public function __set($name, $value)
    {
        $this->data[$name] = $value;
    }
    public function __get($name)
    {
        return isset($this->data[$name])?$this->data[$name]:null;
    }
    //添加数据
    public function add($data=[]){
        if(empty($data)){
            $data = $this->data;
            //避免属性值残留
            $this->data = [];
        }
        $sql = 'insert into '.$this->table .' (';
        $sql .= implode(',',array_keys($data));
        $sql .= ') values (';
        $sql .= substr(str_repeat('?,',count($data)),0,-1).')';
        return $this->insert($sql,array_values($data));
    }

将修改操作修改为ORM方式

/Care/Model.php

    //查找单条数据
    public function find($id){
        $sql = 'select * from '.$this->table.' where '.$this->pk.'=? ';
        $data = $this->getrow($sql,[$id]);
        //属性赋值
        $this->data = $data;
        return $data;
    }

    //添加判断
    public function save($data=[]){
        if(empty($data)){
            $data = $this->data;
            $this->data = [];
        }
        if(!isset($data[$this->pk])){
            throw new Exception('缺少主键',500);
        }
        $data_tmp = $data;
        unset($data_tmp[$this->pk]);
        $sql = 'update '.$this->table.' set ';
        foreach($data_tmp as $k=>$v){
            $sql .= $k .'= ? ,';
        }
        $sql = substr($sql,0,-1);
        $sql .= ' where '.$this->pk .'=?';
        $data_tmp[$this->pk] = $data[$this->pk];
        return $this->update($sql,array_values($data_tmp));
    }

/xm/Controller/indexController.class.php

class indexController extends Controller{
    public function index(){
        $model = new pdoModel();

        $model->find(4);
        $model->age = $model->age+1;
        $model->name = 'liya';
        echo $model->save();
    }
}

自己去想能不能将查询删除操作修改为ORM的方式
能:怎么写?
不能:为什么?

field()、where()等方法

  • field()
  • where()
  • group()
  • having()
  • order()
  • limit()

一个select 查询一般有:
select 列1,列2,…列N from 表名 where xxx group by xxx having xxx order xxx limit xxx

为select 添加field()方法

/Care/Model.php

    //查询多条数据
    public function select(){
        $sql = 'select '. $this->option['op'] .' from '.$this->table;
        $data = $this->getrows($sql);
        return $data;
    }
    /*
     * field
     * */
    private $option = [
        'op'=>' * ',
    ];
    public function field($option){
        if(!empty($option)){
            $this->option['op'] = $option;
        }
        return $this;
    }

多种方式测试
/xm/Controller/indexController.class.php

    $model = new pdoModel();
//        $model->field('name');
//        var_dump($model->select());
//        var_dump($model->field()->select());
        var_dump($model->field('name,age')->select());

为select添加where()方法

/Care/Model.php

    private $option = [
        'field'=>' * ',
        'where'=> '1',
        'v'=>[],
    ];


    public function where($where){
        if(!empty($where)){;
            $where_o = '';
            foreach($where as $k=>$v){
                $where_o .=  ' '.$k.'=? and';
                $this->option['v'][] = $v;
            }
            $where_o = rtrim($where_o,'and');
            $this->option['where'] = $where_o;
        }else{
            $this->option['where'] = 1;
        }
        return $this;
    }

/xm/Controller/indexController.class.php

    public function up(){
        $pdoMode = new pdoModel();
//        ->where(['name'=>'cangoshi'])
        $pdo = $pdoMode->field('name,age')->select();
        var_dump($pdo);
    }

group()、having()、order()、limit()自己尝试写出来

超简单的View层实现

X/lib/Controller.php

class Controller{
    private $data = array();
    public function copm($file){
        $html = file_get_contents($file);
        $html = str_replace('{$',"data['",$html);
        $html = str_replace('}',"'];?>",$html);
        $file_tmp = $file.'.php';
        file_put_contents($file_tmp,$html);
        return $file_tmp;
    }

    public function assign($k,$v){
        $this->data[$k] = $v;
    }

    public function display($file){
        $tmp = $this->copm(APP_PATH.'View/'.$file);
        include($tmp);
    }
}

book/Controller/userController.class.php

 public function up(){
        $a = 'add';
        $this->assign('a',$a);
        $this->display('a.html');
}

book/View/a.html


{$a}

添加工具类

文件上传

X/Tool/Upload.php

class Upload{
    public $file = [];
    public $name = '';
    public $dir = '';
    public $ext = '';
    public function up($name){
        if(!isset($_FILES[$name])){
            echo 'cuo';
        }
        if($_FILES[$name]['error'] !==0){
            echo false;
        }else{
            $this->file = $_FILES[$name];
        }
        $this->createDir();
        if(move_uploaded_file($this->file['tmp_name'],$this->dir.'/'.$this->createName().'.'.$this->getExt())){
            return [
                'url' => $this->dir.'/'.$this->name.'.'.$this->ext,
                'ext' => $this->ext,
            ];
        }else{
            return false;
        }
    }
    //创建目录
    public function createDir(){
        $this->dir = APP_PATH.'upload/'.date('Y-m-d',time());
        $path = $this->dir;
        if(is_dir(($path)) || mkdir($path,0777,true)){
            return $this->dir;
        }else{
            throw new Exception('lksdf',90000);
        }
    }
    //获取文件后缀
    public function getExt(){
        $ext = explode('.',$this->file['name']);
        return $this->ext = strtolower(end($ext));
    }
    //生成文件名
    public function createName($len = 4){
        $all = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ123456789';
        $str = substr(str_shuffle($all),0,$len);
        return $this->name = time().$str;
    }

    //检查是否允许上传
    // 检查文件上传大小
}

book/Controller/userController.class.php


    public function up(){
        if(empty($_FILES)){
            $this->display('up.html');
        }else {
            $up = new Upload();
//            var_dump($_FILES);exit();
            var_dump($up->up('pic'));
        }
    }

book/View/up.html

<body>
<form action="" method="post" enctype="multipart/form-data">
    
    <p><input type="file" name="pic">p>
    <p><input type="submit" value="提交" >p>
form>
body>

你可能感兴趣的:(php,Linux,Nginx,MySQL)