php教程 php手册 php之mvc框架演进过程详解

php之mvc框架演进过程详解

Jun 13, 2016 am 10:57 AM
html mvc php 그리고 기능 증가하다 마치다 아이디어 확인하다 액자 혼합 진화 설계 상해 프로세스

1)  /********** php与html混编完成增删改查功能**************************/

1.设计思路:

   根据平时练习一个增删改查的功能进行,即在一个php文件中完成,对数据库的连接操作

   及在php文件中展示html代码。html提交到当前页面的php部分进行处理入库动作。

  

  $_SERVER['SCRIPT_FILENAME']包含当前脚本的路径。

      这在页面需要指向自己时非常有用。

      区别于__FILE__常量包含当前脚本(例如包含文件)的完整路径和文件名。

 

第一个类:增加商品文件:addProduct.php

 

if(isset($_POST['submit'])){

   $name= $_POST['name'];

   $price= $_POST['price'];

   $description= $_POST['description'];

  

   //连接数据库操作

   mysql_connect('localhost','root','master');

   mysql_select_db('test');

   mysql_query('set names gbk');

  

   $query= "insert into product values(null,'$name','$price','$description')";

  

   mysql_query($query);

  

   mysql_close();

}

 

?>

 

'>

   产品名称

   产品价格

   产品描述

  

  

 

 

思路:都是在同一文件(当前文件中)操作数据库和展示:

Mysql_fetch_assoc 返回数组,一般需要放到一个空数组内组成一个二维数组返回到页面 mysql_num_rows返回行数

 

查询数据一般常用:

Php中

$result = Mysql_query(“select * fromproduct order by id desc”);

$data = array();

While ($row = Mysql_fecth_assoc($result)){

         $data[]= $row;

}

Html中:

 

                 

             ……

 

查询商品文件: listProduct.php

 

//连接数据库操作

mysql_connect('localhost','root','master');

mysql_select_db('test');

mysql_query('set names gbk');

 

$query = "select * from product order by id desc";

 

$result = mysql_query($query);

 

$data = array();

while($row = mysql_fetch_assoc($result)){

   $data[]= $row;

}

 

?>

 

  

     

编号

     

名称

     

价格

     

描述

     

删除

     

更新

  

  

      foreach($dataas$row):

   ?>

  

     

     

     

     

     

">删除

     

">更新

  

  

 

 

 

 

 

 

思路:接下来就进行删除和更新操作,同样是请求到新的php一个文件中来处理删除和更新操作。新建php文件:delProduct.php

delProduct.php:

 

//连接数据库操作

mysql_connect('localhost','root','master');

mysql_select_db('test');

mysql_query('set names gbk');

$id = $_GET['id'];

 

$query = "delete from product where id = '$id'";

 

mysql_query($query);

 

mysql_close();

 

//同时跳到listProduct展示结果

header('location:listProduct.php');

 

 

更新操作:

updateProduct.php(以下类只是作为展示,提交修改还需要一个php文件,为了不再增加一个文件,修改提到本页面,在action中增加一个参数区别展示和提交修改的操作)

 

//连接数据库操作

mysql_connect('localhost','root','master');

mysql_select_db('test');

mysql_query('set names gbk');

 

 

$id = $_GET['id'];

 

$query = "select * from product where id = '$id'";

 

$result = mysql_query($query);

 

$row = mysql_fetch_row($result);

 

?>

 

   "/>

   产品名称"/>

   产品价格"/>

   产品描述"/>

  

  

 

 

修后类内容如下:

 

 

//连接数据库操作

mysql_connect('localhost','root','master');

mysql_select_db('test');

mysql_query('set names gbk');

 

if(isset($_REQUEST['flag'])){

   $id= $_POST['id'];

   $name= $_POST['name'];

   $price= $_POST['price'];

   $description= $_POST['description'];

  

   $query= "update product set name = '$name', price = '$price' , description = '$description' where id='$id'";

  

   mysql_query($query);

  

   mysql_close();

  

   header('location:listProduct.php');

  

}else{

   $id= $_GET['id'];

  

   $query= "select * from product where id = '$id'";

  

   $result= mysql_query($query);

  

   $row= mysql_fetch_row($result);

}

 

?>

 

   "/>

   产品名称"/>

   产品价格"/>

   产品描述"/>

  

  

 

 

 

/**************加入DB类封装对数据库的操作***************/

此时,已经完成了商品的增删改查基本功能了,但是,有很多的冗余代码,比如数据库的操作,这时可以考虑把数据的操作提取出来:

 

DB.class.php:

/**

 * 数据库操作类

 * @author heyongjia

 *

 */

class DB{

  

   private$host ='localhost';

   private$username ='root';

   private$password ='master';

   private$dbname ='test';

   private$setCoding ='set names gbk';//注意编码的设置,有时候会出现插入不成功的情况

  

   private$conn;//连接资源

   private$result;//结果集

 

  

   public functionconnect(){

      $this->conn =mysql_connect($this->host,$this->username,$this->password);

      mysql_select_db($this->dbname);

      mysql_query($this->setCoding);

   }

  

   public functionquery($query){

      $this->result = mysql_query($query);

   }

  

   public functionclose(){

      mysql_close();

   }

}

 

 

 

然后分别改造addProduct.php、delProduct.php、listProduct.php、updateProduct.php操作数据库部分,把每个文件中连接数据,查询的部分提取到数DB.class.php中,修改之后如下:

addProduct.php

if(isset($_POST['submit'])){

   $name= $_POST['name'];

   $price= $_POST['price'];

   $description= $_POST['description'];

  

 

   $query= "insert into product values(null,'$name','$price','$description')";

   $db =newDB();

   $db->connect();

   $db->query($query);

   $db->close();

}

 

 

delProduct.php:

 

include 'class/DB.class.php';

 

$id = $_GET['id'];

 

$query = "delete from product where id = '$id'";

 

$db = newDB();

$db->connect();

$db->query($query);

$db->close();

 

//同时跳到listProduct展示结果

header('location:listProduct.php');

 

 

 

listProduct.php:

 

//连接数据库操作

include 'class/DB.class.php';

 

$query = "select * from product order by id desc";

 

$db = newDB();

$db->connect();

$db->query($query);

$data = array();

while($row = $db->fetch_assoc()){

   $data[]= $row;

}

$db->close();

 

?>

 

/***********引用product对象进行数据传递,即数据模型*********************/

思路:增删改查的操作属于业务逻辑,应该封装起来。

封装到类Product.class.php

 

class Product {

  

   private$id;

   private$name;

   private$price;

   private$description;

  

   public function__set($name,$value){

      $this->$name= $value;

   }

  

   public function__get($name){

      return$this->$name;

   }

  

   public functionadd(){

      $query= "insert into product values(null,'$this->name','$this->price','$this->description')";

      $db= newDB();

      $db->connect();

      $db->query($query);

      $db->close();

   }

}

 

 

然后在addProduct.php中引入该类,并修改操作数据库动作:

   $product= newProduct();

   $product->name = $name;

   $product->price = $price;

   $product->description = $description;

   $product->add();

 

 

其它的操作数据库方法类似。

 

 

 

思路:通过观察addProduct.php、delProduct.php、listProduct.php、updateProduct.php都有类似的代码,那么可不可以整合在一起呢,完成所有模块的相关请求。

 

新建一个product.php文件,addProduct.php、delProduct.php中的相关操作数据库的代码拷贝到product.php文件中,并且在product.php中以action参数来区分不同的请求。

 

 

//用于完成所有相关product操作的请求

include 'class/DB.class.php';

include 'class/Product.class.php';

 

 

$action = $_GET['action'];

 

if($action =='add'){

   //增加

   $name= $_POST['name'];

   $price= $_POST['price'];

   $description= $_POST['description'];

  

   $product= newProduct();

   $product->name = $name;

   $product->price = $price;

   $product->description = $description;

   $product->add();

}

 

if($action =='del'){

   //删除

   $id= $_GET['id'];

  

   $product= newProduct();

   $product->id = $id;

   $product->del();

  

   //同时跳到listProduct展示结果

   header('location:listProduct.php');

}

 

 

 

这时可以把addProduct.php中的php代码部分删除了,并把html部分独立出来一个addProduct.html文件,

同时也可以把delProduct.php文件删除,因为这两个php文件的php代码都移动了product.php中了。

 

/********************加入Smarty模拟类库******************************/

先把以上两个功能先完成,

1.       访问addProduct.html文件,完成增加操作,并跳转回addProduct.html页面。访问listProduct.php文件,查看增加的结果。

 

2.       访问listProduct.php文件,并修改删除链接的请求指向。并同时完成删除的功能。

 

此时product.php的代码如下:

 

 

//用于完成所有相关product操作的请求

include 'class/DB.class.php';

include 'class/Product.class.php';

 

 

$action = $_GET['action'];

 

if($action =='add'){

   //增加

   $name= $_POST['name'];

   $price= $_POST['price'];

   $description= $_POST['description'];

  

   $product= newProduct();

   $product->name = $name;

   $product->price = $price;

   $product->description = $description;

   $product->add();

  

   header('location:addProduct.html');

}

 

if($action =='del'){

   //删除

   $id= $_GET['id'];

  

   $product= newProduct();

   $product->id = $id;

   $product->del();

  

   //同时跳到listProduct展示结果

   header('location:listProduct.php');

}

 

/**************加入smarty类库************************/

思路:此时已经把增加和删除功能已经集合到了product.php中了,还有查询和更新操作,由于listProduct.php中包含了显示数据列表的功能,不容易展示(可以采用include一个页来完成。)。此时,可以用smarty来完成,这样就合理了。

 

这时可以考虑把addProduct.html也放入product.php来展示,修改成:

include 'class/Template.class.php';//注意导入该文件,该文件是模拟smarty实一类文件。(考虑到查询功能也用要到,需要展示多个数据,所以模拟Smarty的类文件无法胜任,就直接引入smarty来作为展示)

 

 

/***********************加入smarty类库********************/

这时可以把自己的写的Templates类继承Smarty类,这样就可以使用Smarty中的功能,还可以扩展其功能。

 

Template.class.php内容如下:

 

/**

 * 继承了Smarty类的Template类

 * @author heyongjia

 *

 */

 

class TemplateextendsSmarty{

   /**

    * 调用父类的构造方法,确保父类中的构造方法已经执行

    * 因为子类如果有构造方法,就不会执行父类中的构造方法

    */

   function__construct(){

      parent::__construct();

      //初始化模板目录

      $this->setTemplateDir('tpl');

   }

  

}

 

 

 

至此,CRUD功能已经整合在一product.php文件中了,也说是所有的请求都经过它,如:

Localhost/test/mvc/product.php?action=add/list/update等请求。这时product.php就相当于一个控制器的角色了。

 

 

/****************  加入入口文件  *******************************、

 

我们程序中,会有很多的控制器,为了便于管理,我们定义一个入口文件,也就是说,所有的请求都经过这个入口文件,再由这个入口进行分发到各个控制器。

 

增一个index.php文件:

用于分发到控制器:

请求的url:

Localhost/test/mvc/index.php?module=product&action=add/list/update

 

所以index.php文件如下:

 

$module = $_GET['module'];

$action = $_GET['action'];

 

$file = $module.'Control.php?action='.$action;

 

header('location:'.$file);

 

 

此时,就可以通过上面的入口文件分发到不同的控制器(模块)上的不同的操作(功能),但是由于使用的是header跳转,在浏览器上地址栏就变成了跳转后的地址了,即脱离了入口文件。

 

那么,如何实现?

 

将product.php改成一个类来实现。改造product.php为ProductControl.class.php,并移动control文件夹下,内容如下:

 

class ProductControl{

  

   public functionaddok(){

      //增加

      $name= $_POST['name'];

      $price= $_POST['price'];

      $description= $_POST['description'];

     

      $product= newProduct();

      $product->name = $name;

      $product->price = $price;

      $product->description = $description;

      $product->add();

     

      header('location:product.php?action=list');

   }

  

   public functionadd(){

      $smarty= newTemplate();

      //$tpl = new Template();

      //$tpl->display('addProduct.html');

      $smarty->display('addProduct.html');

   }

  

   public functiondel(){

      //删除

      $id= $_GET['id'];

     

      $product= newProduct();

      $product->id = $id;

      $product->del();

     

      //同时跳到listProduct展示结果

      header('location:product.php?action=list');

   }

  

   public functionupdate(){

      $smarty= newTemplate();

      $id= $_GET['id'];

     

      $product= newProduct();

      $product->id = $id;

      $row= $product->getRow();

      $smarty->assign('id',$row['id']);

      $smarty->assign('name',$row['name']);

      $smarty->assign('price',$row['price']);

      $smarty->assign('description',$row['description']);

      $smarty->display('updateProduct.html');

   }

  

   public functionupdateok(){

      $id= $_POST['id'];

      $name= $_POST['name'];

      $price= $_POST['price'];

      $description= $_POST['description'];

     

     

      $product= newProduct();

      $product->id = $id;

      $product->name = $name;

      $product->price = $price;

      $product->description = $description;

     

      $product->update();

     

      header('location:product.php?action=list');

   }

 

}

 

此时,如何调用这个类的方法呢?在index.php中实例化该对象调用。

 

//用于完成所有相关product操作的请求

include 'class/DB.class.php';

include 'class/Product.class.php';

include 'smarty/Smarty.class.php';

include 'class/Template.class.php';

 

$module = $_GET['module'];

$module = ucfirst($module);

$action = $_GET['action'];

 

$className = $module.'Control';

 

include 'control/'.$className.'.class.php';

 

$class = new$className; //根据模块名引用类文件并实例化该对象

 

$class->$action(); //调用对应的action方法。

 

 

修改调用的所有路径为:index.php?module=product&action=xxx

addProduct.html updateProduct.htmllistProduct.html

 

 

优化:一般地不会在index.php文件中写太多的代码,可以将代码移动配置文件中,在index.php中引入即可。

 

 

一般地,整个工程会有一个主控制器类,用于处理分发控制器,Application.class.php:

 

 

class Application{

  

   static functionrun(){

      global$module; //函数内要使用外部的变量

      global$action;

      $className= $module.'Control';

     

      include'control/'.$className.'.class.php';

     

      $class= new$className;

     

      $class->$action();

   }

}

 

 

init.php:

 

//用于完成所有相关product操作的请求

include 'class/DB.class.php';

include 'class/Product.class.php';

include 'smarty/Smarty.class.php';

include 'class/Template.class.php';

include 'control/Application.class.php';

 

$module = $_GET['module'];

$module = ucfirst($module);

$action = $_GET['action'];

 

 

 

Index.php:

 

 

include 'config/init.php';

Application::run();

 

 

 

此时,访问的url为: index.php?module=product&action=xxx

 

但如果直接访问index.php就会报错:


Notice: Undefined index: module in F:\amp\apache\studydocs\test\php_js\mvc\config\init.phpon line10

Notice: Undefined index: action in F:\amp\apache\studydocs\test\php_js\mvc\config\init.phpon line12

 

这是因为在init.php中没有对module和action进行初始化。

并将值配置到config文件夹下的conig.php文件中。

 

 

 

由于在product.php文件中(其实就是模型类),有很多类似的操作数据库的代码,所以可以将这部分代码封装到父类实现,该模型类只需要继承即可。

 

/******************封装核心文件core**************************

新建一个文件夹core,将DB.class.php和Application.php移动到core因为是共公的文件,不属于功能文件。

 

新建一个基类文件(模型基类),用于实现对数据库实例化的封装,而子类模型只需要继承即可获取数据库对象的实例。

 

Model.class.php:

 

class Medel{

  

   protected$db;

  

   public function__construct(){

      $this->db =newDB();

   }

}

 

 

新建文件夹model,然后将product.php移动到model文件夹下,并改名ProductModel.class.php:

 

class ProductModelextendsModel {

  

   private$id;

   private$name;

   private$price;

   private$description;

  

   public function__set($name,$value){

      $this->$name= $value;

   }

  

   public function__get($name){

      return$this->$name;

   }

  

   public functionadd(){

      $query= "insert into product values(null,'$this->name','$this->price','$this->description')";

      $this->db->connect();

      $this->db->query($query);

      $this->db->close();

   }

  

   public functiondel(){

      $query= "delete from product where id = '$this->id'";   

      $this->db->connect();

      $this->db->query($query);

      $this->db->close();

   }

  

   public functionselect(){

      $query= "select * from product order by iddesc";     

      $this->db->connect();

      $this->db->query($query);

      $data= array();

      while($row = $this->db->fetch_assoc()){

         $data[]= $row;

      }

      $this->db->close();

      return$data;

   }

  

   public functionupdate(){

      $query= "update product set name = '$this->name', price = '$this->price' , description = '$this->description' where id='$this->id'";

      $this->db->connect();

      $this->db->query($query);

      $this->db->close();

   }

  

   public functiongetRow(){

     

      $query= "select * from product where id = '$this->id'";

     

      $this->db->connect();

      $this->db->query($query);

      $row= $this->db->fetch_assoc();

      $this->db->close();

      return$row;

   }

  

  

}

 

/***********************视图封装**************************

在控制器中每次都要实例化Template类,并调用display方法。

 

把Template.class.php移动core文件夹中,并改名为View.class.php:

 

这么做的好处,让每一个控制继承于该类(构造一个控制器基类Control.class.php,在类中构造一个视图实例),只要每个控制器继承了该类(Control.class.php),即拥有了smarty实例。

 


/**

 * 1.继承了Smarty类的Template类

 * 2.不用继承Smarty了,是smarty的一个实例

 * @author heyongjia

 *

 */

 

class Viewextends Smarty{

  

  

}

这么做的好处,让每一个控制继承于该类(构造一个控制器基类Control.class.php,在类中构造一个视图实例),只要每个控制器继承了该类(Control.class.php),即拥有了smarty实例。

 

/**

 * 控制器基类

 * @author heyongjia

 *

 */

class Controlextends View{

   protected$view;

  

   public function__construct(){

      $this->view = new View();

$this->view->setTemplateDir('tpl');

   }

  

}


 

优化,直接在init.php中直接包含模型是不对的,因为可以出现很多的模型。这时可以考虑自动加载机载来实现。注意:smarty3.0中也用到了自动加载函数,所以要利用注册来完成。

 

function autoload1($classname){

   $filename= 'model/'.$classname.'.class.php';

   if(is_file($filename)){

      include"$filename";

   }

}

 

spl_autoload_register('autoload1');

 

function addslashes_func(&$str){

   $str= addslashes($str);

}

 

if(!get_magic_quotes_gpc()){

   array_walk_recursive($_POST,'addslashes_func');

   array_walk_recursive($_GET,'addslashes_func');

}

 

此至,就mvc简易框架就到这里差不多了。

 


用图总结一下,这样就比较直观了:

 

 

 

 

 

 

 

 

 

 


 


 

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Ubuntu 및 Debian용 PHP 8.4 설치 및 업그레이드 가이드 Dec 24, 2024 pm 04:42 PM

PHP 8.4는 상당한 양의 기능 중단 및 제거를 통해 몇 가지 새로운 기능, 보안 개선 및 성능 개선을 제공합니다. 이 가이드에서는 Ubuntu, Debian 또는 해당 파생 제품에서 PHP 8.4를 설치하거나 PHP 8.4로 업그레이드하는 방법을 설명합니다.

CakePHP 날짜 및 시간 CakePHP 날짜 및 시간 Sep 10, 2024 pm 05:27 PM

cakephp4에서 날짜와 시간을 다루기 위해 사용 가능한 FrozenTime 클래스를 활용하겠습니다.

CakePHP 파일 업로드 CakePHP 파일 업로드 Sep 10, 2024 pm 05:27 PM

파일 업로드 작업을 위해 양식 도우미를 사용할 것입니다. 다음은 파일 업로드의 예입니다.

CakePHP 토론 CakePHP 토론 Sep 10, 2024 pm 05:28 PM

CakePHP는 PHP용 오픈 소스 프레임워크입니다. 이는 애플리케이션을 훨씬 쉽게 개발, 배포 및 유지 관리할 수 있도록 하기 위한 것입니다. CakePHP는 강력하고 이해하기 쉬운 MVC와 유사한 아키텍처를 기반으로 합니다. 모델, 뷰 및 컨트롤러 gu

CakePHP 유효성 검사기 만들기 CakePHP 유효성 검사기 만들기 Sep 10, 2024 pm 05:26 PM

컨트롤러에 다음 두 줄을 추가하면 유효성 검사기를 만들 수 있습니다.

PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 PHP 개발을 위해 Visual Studio Code(VS Code)를 설정하는 방법 Dec 20, 2024 am 11:31 AM

VS Code라고도 알려진 Visual Studio Code는 모든 주요 운영 체제에서 사용할 수 있는 무료 소스 코드 편집기 또는 통합 개발 환경(IDE)입니다. 다양한 프로그래밍 언어에 대한 대규모 확장 모음을 통해 VS Code는

CakePHP 빠른 가이드 CakePHP 빠른 가이드 Sep 10, 2024 pm 05:27 PM

CakePHP는 오픈 소스 MVC 프레임워크입니다. 이를 통해 애플리케이션 개발, 배포 및 유지 관리가 훨씬 쉬워집니다. CakePHP에는 가장 일반적인 작업의 과부하를 줄이기 위한 여러 라이브러리가 있습니다.

PHP에서 HTML/XML을 어떻게 구문 분석하고 처리합니까? PHP에서 HTML/XML을 어떻게 구문 분석하고 처리합니까? Feb 07, 2025 am 11:57 AM

이 튜토리얼은 PHP를 사용하여 XML 문서를 효율적으로 처리하는 방법을 보여줍니다. XML (Extensible Markup Language)은 인간의 가독성과 기계 구문 분석을 위해 설계된 다목적 텍스트 기반 마크 업 언어입니다. 일반적으로 데이터 저장 AN에 사용됩니다

See all articles