您的位置:首页 > 其它

搭建自己的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.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('{$',"<?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.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="text" name="po"></p>-->
<p><input type="file" name="pic"></p>
<p><input type="submit" value="提交" ></p>
</form>
</body>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: