搭建自己的MVC框架
2016-03-01 21:55
483 查看
开始写框架
分析框架执行流程
以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.phpdefine('APP_PATH',__DIR__.'/'); include ("../xphp/x.php");
项目的控制器
xm/Controller/indexController.class.phpclass indexController{ //控制器中的方法 public function index(){ echo 'my index a'; } }
继承基类
/x.phpdefine('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.phpclass 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.phpclass 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.phpprivate $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.phpclass Controller{ private $data = array(); public function copm($file){ $html = file_get_contents($file); $html = str_replace('{$',"<?php echo \$this->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
<body> {$a} </body>
添加工具类
文件上传
X/Tool/Upload.phpclass 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="text" name="po"></p>--> <p><input type="file" name="pic"></p> <p><input type="submit" value="提交" ></p> </form> </body>
相关文章推荐
- 安装SQL Server 2014
- 2016年3月1号【运行出错,IndentationError: unindent does not match any outer indentation level】
- jQuery 实现导航栏 lable页
- 递归思想-汉诺塔解法
- String,StringBuffer与StringBuilder的区别??
- 3ds Max2015关于注册的细节
- Android中Snackbar的使用
- ubuntu如何安装nodejs最新版 本
- 第二十课(一)
- 对象的筛选
- bzoj 3657 斐波那契数列(fib.cpp/pas/c/in/out)
- 紫书 p59 习题3-8
- 爬虫学习:一个管用的贴吧妹子图下载器
- Codeforces 633D Fibonacci-ish(暴力)
- MongoDB的安装(Linux平台)
- 2.OC蓝牙功能
- ping命令中请求超时是什么意思?
- 大脑记忆系统研究取得重大进展:或被用于开发新的芯片和操作系统
- 大脑记忆系统研究取得重大进展:或被用于开发新的芯片和操作系统
- Android第一周实习笔记