PHP仿tp实现mvc框架基本设计思路与实现方法分析


Posted in PHP onMay 23, 2018

本文实例讲述了PHP仿tp实现mvc框架基本设计思路与实现方法。分享给大家供大家参考,具体如下:

仿tp mvc基本设计与简单实现

一:文件加载常识

变量 常量 函数 类
文件加载的函数或者使用命名空间:require();   require_once();   include();   include_once();
常量:define("DEFINE","");   const constant = "value";
函数:function fun(){}  // global 使用全局变量    局部变量不被外部调用。
类:

<?php
class A{
  public $a = 10;
  public function aa(){  // 不能使用一个a是因为,new A 之后 方法a会被自动执行,所以方法名不可以和类名冲突。
    echo $this->a; // 输出属性.
  }
  public function __construct(){ // 构造方法,实例化后自动执行,
    echo $this->bb(); // 调用方法。
  }
  public function bb(){
    echo "我是bb";
  }
}
$a = new A;
$a->aa();
class B extends A{ // 继承 A ,类A是类B的父级。继承public的,
}
$b = new B;
$b->aa(); // 可以输出类A里面的属性。

工厂模式参阅:https://3water.com/article/140658.htm

//-----------------------------工厂模式-------------------------//
class A{
  public $class;   // public $class = $_GET['c']; //类名
  public $method; // public $method = $_GET['m']; //方法
  public function __construct($class,$method){
    // 或者通过 $_SERVER['PATH_INFO']; 转换得到类名或者方法名(下面讲解)。
    $this->class = ucfirst(strtolower($class)).'Controller'; //对类名进行安全处理,并加上控制器后缀
    $this->method = strtolower($method);   //对方法名进行安全处理
    $this->work($this->class,$this->method);
  }
  public function work($class,$method){
    // 把文件命名成 (类名.class.php的形式),就可以通过类名找到文件。
    //include '文件名(文件在别的地方)';    #例如 include './index.php'; 引入文件然后实例化类。
    $c = new $class;  //实例化类
    $c->$method();  //访问类的方法
  }
}

至此我们可以通过url的 $_GET 参数来解决

例如:http://mvc.com/index.php?h=home&v=Index&c=index.html

h为前后台,v为控制器,c为模板。

$v = $_GET['v'];
$c = rtrim($_GET['c'],".html");
new A($v,$c); // 根据继承关系再次加载文件。
// extract($arr);  //extract 的作用:从数组中将变量导入到当前的符号表,键做变量,值做值!
// compact(); // — 建立一个数组,包括变量名和它们的值
// assign display 实现参阅:https://3water.com/article/140661.htm
class Controller{
  public $array;
  public $key;
  public $val;
  public function assign($key,$val){
    if(array($val)){
      $this->array["$key"] = $val;
    }else{
      $this->array["$key"] = compact($val);
    }
  }
  public function display($tpl = ''){ // 模板为空自动加载。
    $this->assign($this->key,$this->val);
    extract($this->array);
    // 如果模板为空就在这里根据get参数添加或者通过 $_SERVER['PATH_INFO']; 转换得到。(下面讲解)
    if(file_exists($tpl)){ //模板存在就加载文件。
      include $tpl;
    }
  }
}
//继承总model。这个model名字和控制器model的名字是一样的。继承方法同Controller,总model必须需要加上一个return。数据处理的indexmodel可以加return,也可以不加。
class IndexModel extends Model{
  public function index(){
    // 数据处理。
    // 需要返回数据就加上return。
  }
}
class IndexController extends Controller{ // 继承
  public function index(){
    $m = Model("index");
    echo '实例化后的index方法<br>';
    $this->assign('m',$m); // 分配数据。
    $this->display('index.html'); // 模板
  }
}

mvc虽然实现但是不够人性化,因为每次都要加上get参数,变得很冗长,解决的关键在于$_SERVER['PATH_INFO'];

用这个替换掉h m v三个参数。

1. 当输入url为:http://mvc.com/index.php/home/index/index.html
    这种情况下  index.php 斜线后面的apache会自动认为是一个路径。
    $_SERVER['PATH_INFO'] =  /home/index/index.html
    第1个斜线 /home        前后台
    第2个斜线 /index        控制器
    第3个斜线 /index.html  模板文件
    如果后面加有参数例如:?a=18&b=38   他不会被加到$_SERVER['PATH_INFO']里面。$_POST 或者 $_GET 也不会加入$_SERVER['PATH_INFO']里面的内容,这样就可以让控制参数和数据的参数互不冲突。

2. U 方法的实现。重新改写$_SERVER['PATH_INFO'] 参数,改变为一个数据。array( 'home', 'Index', 'index');

每次进入入口文件index.php都把他的PHP_INFO参数转换为数组,在控制器或者其他的地方只要调用这个参数就行了。

// 这里如果做了大小写的转换,总控制器里面就不用了。
function bca(){
  $arr = explode('/',ltrim($_SERVER['PATH_INFO'],'/'));
  if(count($arr) == 3){
    $arr[0] = strtolower($arr[0]);
    $arr[1] = ucfirst(strtolower($arr[1]));
    // 判断后缀是不是 .html
    if(substr($arr[2],-5,strlen($arr[2])) == '.html'){
      $a = explode('.',$arr['2']);
      $arr[2] = strtolower($a[0]);
    }else{
      $arr[2] = strtolower($arr[2]);
    }
    $_SERVER['PATH_INFO'] = $arr;
  }
}
// url方法做控制器或前后台的跳转。第三个参数是输出还是return。默认是直接输出。
function U($string = '',$method = '',$bool = true){ // true 是直接输出或者返回,
  // 获取系统变量。
  $path_info = $_SERVER['PATH_INFO'];
  $script_name = $_SERVER['SCRIPT_NAME'];
  // 判断中间有没有 / 以确定参数个数。
  if(strpos($string,'/')){
    $arr = explode('/',$string);
    if(count($arr) == 2){  // 两个参数的情况。
      $arr[0] = ucfirst(strtolower($arr[0]));
      $arr[1] = strtolower($arr[1]);
      $url = "/{$path_info[0]}/{$arr[0]}/{$arr[1]}.html";
    }else if(count($arr) == 3){ // 三个参数的情况。
      $arr[0] = strtolower($arr[0]);
      $arr[1] = ucfirst(strtolower($arr[1]));
      $arr[2] = strtolower($arr[2]);
      $url = "/{$arr[0]}/{$arr[1]}/{$arr[2]}.html";
    }
  }else{
    $arr = strtolower($string); // 一个参数的情况。
    $url = "/{$path_info[0]}/{$path_info[1]}/{$arr}.html";
  }
  // url 路径的拼接。
  if($method != ''){
    $u = $script_name.$url.'?'.$method;
    if($bool == true){     echo $u;    }else{     return $u;   }
  }else{
    $u = $script_name.$url;
    if($bool == true){     echo $u;    }else{     return $u;   }
  }
}

3. url重写,去掉 index.php

打开apache配置文件重写模块,LoadModule rewrite_module modules/mod_rewrite.so

根下加入的改写文件  .htaccess

内容:

<IfModule mod_rewrite.c>
 Options +FollowSymlinks
 RewriteEngine On
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

在浏览器输入url:http://mvc.com/home/index/index.html?a=19b=38
    [REDIRECT_STATUS] => 200  重写状态ok。

发现 $_SERVER['REDIRECT_URL'];$_SERVER['PATH_INFO']; 参数相同。所以参数后面就可以去掉index.php这安全的问题。

4. 模板替换(思路)

我们会发现有一个我们书写的模板,里面有 {$arr}  <include file="" /> 等,我们把模板文件读取后通过正则还有字符串把他转换成正常的php文件。对文件名加密后放到替换后的文件夹下,每次url访问的时候查看是否有缓存文件,判断最后修改时间等验证,

5. 数据缓存(思路)

json_encode() json_decode() file_get_contents() file_put_contents(); unserialize();  serialize(); 等存文文件里面或者memcache redis 等存储。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php 传值赋值与引用赋值的区别
Dec 29 PHP
wamp下修改mysql访问密码的解决方法
May 07 PHP
解析PHP 使用curl提交json格式数据
Jun 29 PHP
php命名空间学习详解
Feb 27 PHP
PHP中获取时间的下一周下个月的方法
Mar 18 PHP
对PHP新手的一些建议(PHP学习经验总结)
Aug 20 PHP
简单的pgsql pdo php操作类实现代码
Aug 25 PHP
PHP截取发动短信内容的方法
Jul 04 PHP
PHP实现的Redis多库选择功能单例类
Jul 27 PHP
PHP编程实现的TCP服务端和客户端功能示例
Apr 13 PHP
Yii2压缩PHP中模板代码的输出问题
Aug 28 PHP
gearman中worker常驻后台,导致MySQL server has gone away的解决方法
Feb 27 PHP
PHP自定义函数实现assign()数组分配到模板及extract()变量分配到模板功能示例
May 23 #PHP
PHP工厂模式简单实现方法示例
May 23 #PHP
PHP递归遍历文件夹去除注释并压缩php源代码的方法示例
May 23 #PHP
PHP实现将多个文件压缩成zip格式并下载到本地的方法示例
May 23 #PHP
PHP实现的mysql读写分离操作示例
May 22 #PHP
PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】
May 21 #PHP
PHP+MariaDB数据库操作基本技巧备忘总结
May 21 #PHP
You might like
Laravel中使用阿里云OSS Composer包分享
2015/02/10 PHP
php获取当前页面完整URL地址
2015/12/30 PHP
Laravel5权限管理方法详解
2016/07/26 PHP
php封装的验证码工具类完整实例
2016/10/19 PHP
PHP实现实时生成并下载超大数据量的EXCEL文件详解
2017/10/23 PHP
PHP时间处理类操作示例
2018/09/05 PHP
juery框架写的弹窗效果适合新手
2013/11/27 Javascript
js操作IE浏览器弹出浏览文件夹可以返回目录路径
2014/07/14 Javascript
jQuery CSS()方法改变现有的CSS样式
2014/08/20 Javascript
JavaScript实现找出数组中最长的连续数字序列
2014/09/03 Javascript
js监听鼠标事件控制textarea输入字符串的个数
2014/09/29 Javascript
jQuery实现数字加减效果汇总
2014/12/16 Javascript
JS平滑无缝滚动效果的实现代码
2016/05/06 Javascript
浅析$.getJSON异步请求和同步请求
2016/06/06 Javascript
AngularJS使用ng-inlude指令加载页面失败的原因与解决方法
2017/01/19 Javascript
node简单实现一个更改头像功能的示例
2017/12/29 Javascript
Nuxt.js实战详解
2018/01/18 Javascript
详解封装基础的angular4的request请求方法
2018/06/05 Javascript
解决Vue中引入swiper,在数据渲染的时候,发生不滑动的问题
2018/09/27 Javascript
Vue 实现分页与输入框关键字筛选功能
2020/01/02 Javascript
微信小程序用canvas画图并分享
2020/03/09 Javascript
详解React的回调渲染模式
2020/09/10 Javascript
Python3实现将文件归档到zip文件及从zip文件中读取数据的方法
2015/05/22 Python
Django框架中处理URLconf中特定的URL的方法
2015/07/20 Python
Python数据持久化shelve模块用法分析
2018/06/29 Python
Python Flask框架扩展操作示例
2019/05/03 Python
修改 CentOS 6.x 上默认Python的方法
2019/09/06 Python
python  logging日志打印过程解析
2019/10/22 Python
浅谈Python中range与Numpy中arange的比较
2020/03/11 Python
标签和贴纸印刷:Lightning Labels
2018/03/22 全球购物
仓库主管的岗位职责
2013/12/04 职场文书
服装厂厂长岗位职责
2013/12/27 职场文书
2014年物资管理工作总结
2014/12/02 职场文书
财务工作个人总结
2015/02/27 职场文书
优秀志愿者感言
2015/08/01 职场文书
放飞理想主题班会
2015/08/14 职场文书