亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

php語言

如何使用PHP開發(fā)自己的MVC框架

時間:2024-09-06 19:51:45 php語言 我要投稿
  • 相關(guān)推薦

如何使用PHP開發(fā)自己的MVC框架

  MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構(gòu)模式,把軟件系統(tǒng)分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。下面是小編為大家?guī)淼娜绾问褂肞HP開發(fā)自己的MVC框架的知識,歡迎閱讀。

  一、什么是MVC

  MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構(gòu)模式,把軟件系統(tǒng)分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。

  MVC模式的目的是實(shí)現(xiàn)一種動態(tài)的程序設(shè)計,使后續(xù)對程序的修改和擴(kuò)展簡化,并且使程序某一部分的重復(fù)利用成為可能。除此之外,此模式通過對復(fù)雜度的簡化,使程序結(jié)構(gòu)更加直觀。軟件系統(tǒng)通過對自身基本部份分離的同時也賦予了各個基本部分應(yīng)有的功能。專業(yè)人員可以通過自身的專長分組:

 。ǹ刂破鰿ontroller)- 負(fù)責(zé)轉(zhuǎn)發(fā)請求,對請求進(jìn)行處理。

 。ㄒ晥DView) – 界面設(shè)計人員進(jìn)行圖形界面設(shè)計。

 。P蚆odel) – 程序員編寫程序應(yīng)有的功能(實(shí)現(xiàn)算法等等)、數(shù)據(jù)庫專家進(jìn)行數(shù)據(jù)管理和數(shù)據(jù)庫設(shè)計(可以實(shí)現(xiàn)具體的功能)。

  模型(Model) “數(shù)據(jù)模型”(Model)用于封裝與應(yīng)用程序的業(yè)務(wù)邏輯相關(guān)的數(shù)據(jù)以及對數(shù)據(jù)的處理方法。“模型”有對數(shù)據(jù)直接訪問的權(quán)力,例如對數(shù)據(jù)庫的訪問。“模型”不依賴“視圖”和“控制器”,也就是說,模型不關(guān)心它會被如何顯示或是如何作。但是模型中數(shù)據(jù)的變化一般會通過一種刷新機(jī)制被公布。為了實(shí)現(xiàn)這種機(jī)制,那些用于監(jiān)視此模型的視圖必須事先在此模型上注冊,從而,視圖可以了解在數(shù)據(jù)模型上發(fā)生的改變。

  視圖(View) 視圖層能夠?qū)崿F(xiàn)數(shù)據(jù)有目的的顯示(理論上,這不是必需的)。在視圖中一般沒有程序上的邏輯。為了實(shí)現(xiàn)視圖上的刷新功能,視圖需要訪問它監(jiān)視的數(shù)據(jù)模型(Model),因此應(yīng)該事先在被它監(jiān)視的數(shù)據(jù)那里注冊。

  控制器(Controller) 控制器起到不同層面間的組織作用,用于控制應(yīng)用程序的流程。它處理事件并作出響應(yīng)!笆录卑ㄓ脩舻男袨楹蛿(shù)據(jù)模型上的改變。

  二、為什么要自己開發(fā)MVC框架

  網(wǎng)絡(luò)上有大量優(yōu)秀的MVC框架可供使用,本教程并不是為了開發(fā)一個全面的、終極的MVC框架解決方案,而是將它看作是一個很好的從內(nèi)部學(xué)習(xí)PHP的機(jī)會,在此過程中,你將學(xué)習(xí)面向?qū)ο缶幊毯驮O(shè)計模式,并學(xué)習(xí)到開放中的一些注意事項(xiàng)。

  更重要的是,你可以完全控制你的框架,并將你的想法融入到你開發(fā)的框架中。雖然不一定是做好的,但是你可以按照你的方式去開發(fā)功能和模塊。

  三、開始開發(fā)自己的MVC框架

  在開始開發(fā)前,讓我們先來把項(xiàng)目建立好,假設(shè)我們建立的項(xiàng)目為todo,那么接下來的第一步就是把目錄結(jié)構(gòu)先設(shè)置好。

  todo

  雖然在這個教程中不會使用到上面的所有的目錄,但是為了以后程序的可拓展性,在一開始就把程序目錄設(shè)置好使非常必要的。下面就具體說說每個目錄的作用:

  application – 存放程序代碼

  config – 存放程序配置或數(shù)據(jù)庫配置

  db – 用來存放數(shù)據(jù)庫備份內(nèi)容

  library – 存放框架代碼

  public – 存放靜態(tài)文件

  scripts – 存放命令行工具

  tmp – 存放臨時數(shù)據(jù)

  在目錄設(shè)置好以后,我們接下來就要來頂一下一些代碼的規(guī)范:

  MySQL的表名需小寫并采用復(fù)數(shù)形式,如items,cars

  模塊名(Models)需首字母大寫,并采用單數(shù)模式,如Item,Car

  控制器(Controllers)需首字母大寫,采用復(fù)數(shù)形式并在名稱中添加“Controller”,如ItemsController, CarsController

  視圖(Views)采用復(fù)數(shù)形式,并在后面添加行為作為文件,如:items/view.php, cars/buy.php

  上述的一些規(guī)則是為了能在程序鐘更好的進(jìn)行互相的調(diào)用。接下來就開始真正的編碼了。

  第一步將所有的的請求都重定向到public目錄下,解決方案是在todo文件下添加一個.htaccesss文件,文件內(nèi)容為:

  <IfModule mod_rewrite.c>

  RewriteEngine on

  RewriteRule    ^$    public/    [L]

  RewriteRule    (.*) public/$1    [L]

  </IfModule>

  在我們把所有的請求都重定向到public目錄下以后,我們就需要將所有的數(shù)據(jù)請求都再重定向到public下的index.php文件,于是就需要在public文件夾下也新建一個.htaccess文件,文件內(nèi)容為:

  <IfModule mod_rewrite.c>

  RewriteEngine On

  #如果文件存在就直接訪問目錄不進(jìn)行RewriteRule

  RewriteCond %{REQUEST_FILENAME} !-f

  #如果目錄存在就直接訪問目錄不進(jìn)行RewriteRule

  RewriteCond %{REQUEST_FILENAME} !-d

  #將所有其他URL重寫到 index.php/URL

  RewriteRule ^(.*)$ index.php?url=$1 [PT,L]

  </IfModule>

  這么做的主要原因有:

  可以使程序有一個單一的入口,將所有除靜態(tài)程序以外的程序都重定向到index.php上;

  可以用來生成利于SEO的URL,想要更好的配置URL,后期可能會需要URL路由,這里先不做介紹了。

  做完上面的操作,就應(yīng)該知道我們需要做什么了,沒錯!在public目錄下添加index.php文件,文件內(nèi)容為:

  <?php

  define('DS',DIRECTORY_SEPARATOR);

  define('ROOT',dirname(dirname(__FILE__)));

  $url = $_GET['url'];

  require_once(ROOT.DS.'library'.DS.'bootstrap.php');

  注意上面的PHP代碼中,并沒有添加PHP結(jié)束符號”?>”,這么做的主要原因是:對于只包含PHP代碼的文件,結(jié)束標(biāo)志(“?>”)最好不存在,PHP自身并不需要結(jié)束符號,不添加結(jié)束符號可以很大程度上防止末尾被添加額外的注入內(nèi)容,讓程序更加安全。

  在index.php中,我們對library文件夾下的bootstrap.php發(fā)起了請求,那么bootstrap.php這個啟動文件中到底會包含哪些內(nèi)容呢?

  <?php

  require_once(ROOT.DS.'config'.DS .'config.php');

  require_once(ROOT.DS.'library'.DS .'shared.php');

  以上文件都可以直接在index.php文件中引用,我們這么做的原因是為了在后期管理和拓展中更加的方便,所以把需要在一開始的時候就加載運(yùn)行的程序統(tǒng)一放到一個單獨(dú)的文件中引用。

  先來看看config文件下的config .php文件,該文件的主要作用是設(shè)置一些程序的配置項(xiàng)及數(shù)據(jù)庫連接等,主要內(nèi)容為:

  <?php

  # 設(shè)置是否為開發(fā)狀態(tài)

  define('DEVELOPMENT_ENVIRONMENT',true);

  # 設(shè)置數(shù)據(jù)庫連接所需數(shù)據(jù)

  define('DB_HOST','localhost');

  define('DB_NAME','todo');

  define('DB_USER','root');

  define('DB_PASSWORD','root');

  應(yīng)該說config.php涉及到的內(nèi)容并不多,不過是一些基礎(chǔ)數(shù)據(jù)的一些設(shè)置,再來看看library下的共用文件shared.php應(yīng)該怎么寫。

  <?php

  /* 檢查是否為開發(fā)環(huán)境并設(shè)置是否記錄錯誤日志 */

  function setReporting(){

  if (DEVELOPMENT_ENVIRONMENT == true) {

  error_reporting(E_ALL);

  ini_set('display_errors','On');

  } else {

  error_reporting(E_ALL);

  ini_set('display_errors','Off');

  ini_set('log_errors','On');

  ini_set('error_log',ROOT.DS. 'tmp' .DS. 'logs' .DS. 'error.log');

  }

  }

  /* 檢測敏感字符轉(zhuǎn)義(Magic Quotes)并移除他們 */

  function stripSlashDeep($value){

  $value = is_array($value) ? array_map('stripSlashDeep',$value) : stripslashes($value);

  return $value;

  }

  function removeMagicQuotes(){

  if (get_magic_quotes_gpc()) {

  $_GET = stripSlashDeep($_GET);

  $_POST = stripSlashDeep($_POST);

  $_COOKIE = stripSlashDeep($_COOKIE);

  }

  }

  /* 檢測全局變量設(shè)置(register globals)并移除他們 */

  function unregisterGlobals(){

  if (ini_get('register_globals')) {

  $array = array('_SESSION','_POST','_GET','_COOKIE','_REQUEST','_SERVER','_ENV','_FILES');

  foreach ($array as $value) {

  foreach ($GLOBALS[$value] as $key => $var) {

  if ($var === $GLOBALS[$key]) {

  unset($GLOBALS[$key]);

  }

  }

  }

  }

  }

  /* 主請求方法,主要目的拆分URL請求 */

  function callHook() {

  global $url;

  $urlArray = array();

  $urlArray = explode("/",$url);

  $controller = $urlArray[0];

  array_shift($urlArray);

  $action = $urlArray[0];

  array_shift($urlArray);

  $queryString = $urlArray;

  $controllerName = $controller;

  $controller = ucwords($controller);

  $model = rtrim($controller, 's');

  $controller .= 'Controller';

  $dispatch = new $controller($model,$controllerName,$action);

  if ((int)method_exists($controller, $action)) {

  call_user_func_array(array($dispatch,$action),$queryString);

  } else {

  /* 生成錯誤代碼 */

  }

  }

  /* 自動加載控制器和模型 */

  function __autoload($className) {

  if (file_exists(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php')) {

  require_once(ROOT . DS . 'library' . DS . strtolower($className) . '.class.php');

  } else if (file_exists(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php')) {

  require_once(ROOT . DS . 'application' . DS . 'controllers' . DS . strtolower($className) . '.php');

  } else if (file_exists(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php')) {

  require_once(ROOT . DS . 'application' . DS . 'models' . DS . strtolower($className) . '.php');

  } else {

  /* 生成錯誤代碼 */

  }

  }

  setReporting();

  removeMagicQuotes();

  unregisterGlobals();

  callHook();

  接下來的操作就是在library中建立程序所需要的基類,包括控制器、模型和視圖的基類。

  新建控制器基類為controller.class.php,控制器的主要功能就是總調(diào)度,具體具體內(nèi)容如下:

  <?php

  class Controller {

  protected $_model;

  protected $_controller;

  protected $_action;

  protected $_template;

  function __construct($model, $controller,$action) {

  $this->_controller = $controller;

  $this->_action = $action;

  $this->_model = $model;

  $this->$model =& new $model;

  $this->_template =& new Template($controller,$action);

  }

  function set($name,$value) {

  $this->_template->set($name,$value);

  }

  function __destruct() {

  $this->_template->render();

  }

  }

  新建控制器基類為model.class.php,考慮到模型需要對數(shù)據(jù)庫進(jìn)行處理,所以可以新建一個數(shù)據(jù)庫基類sqlquery.class.php,模型去繼承sqlquery.class.php。

  新建sqlquery.class.php,代碼如下:

  <?php

  class SQLQuery {

  protected $_dbHandle;

  protected $_result;

  /** 連接數(shù)據(jù)庫 **/

  function connect($address, $account, $pwd, $name) {

  $this->_dbHandle = @mysql_connect($address, $account, $pwd);

  if ($this->_dbHandle != 0) {

  if (mysql_select_db($name, $this->_dbHandle)) {

  return 1;

  }

  else {

  return 0;

  }

  }

  else {

  return 0;

  }

  }

  /** 中斷數(shù)據(jù)庫連接 **/

  function disconnect() {

  if (@mysql_close($this->_dbHandle) != 0) {

  return 1;

  }  else {

  return 0;

  }

  }

  /** 查詢所有數(shù)據(jù)表內(nèi)容 **/

  function selectAll() {

  $query = 'select * from `'.$this->_table.'`';

  return $this->query($query);

  }

  /** 查詢數(shù)據(jù)表指定列內(nèi)容 **/

  function select($id) {

  $query = 'select * from `'.$this->_table.'` where `id` = ''.mysql_real_escape_string($id).''';

  return $this->query($query, 1);

  }

  /** 自定義SQL查詢語句 **/

  function query($query, $singleResult = 0) {

  $this->_result = mysql_query($query, $this->_dbHandle);

  if (preg_match("/select/i",$query)) {

  $result = array();

  $table = array();

  $field = array();

  $tempResults = array();

  $numOfFields = mysql_num_fields($this->_result);

  for ($i = 0; $i < $numOfFields; ++$i) {

  array_push($table,mysql_field_table($this->_result, $i));

  array_push($field,mysql_field_name($this->_result, $i));

  }

  while ($row = mysql_fetch_row($this->_result)) {

  for ($i = 0;$i < $numOfFields; ++$i) {

  $table[$i] = trim(ucfirst($table[$i]),"s");

  $tempResults[$table[$i]][$field[$i]] = $row[$i];

  }

  if ($singleResult == 1) {

  mysql_free_result($this->_result);

  return $tempResults;

  }

  array_push($result,$tempResults);

  }

  mysql_free_result($this->_result);

  return($result);

  }

  }

  /** 返回結(jié)果集行數(shù) **/

  function getNumRows() {

  return mysql_num_rows($this->_result);

  }

  /** 釋放結(jié)果集內(nèi)存 **/

  function freeResult() {

  mysql_free_result($this->_result);

  }

  /** 返回MySQL操作錯誤信息 **/

  function getError() {

  return mysql_error($this->_dbHandle);

  }

  }

  新建model.class.php,代碼如下:

  <?php

  class Model extends SQLQuery{

  protected $_model;

  function __construct() {

  $this->connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);

  $this->_model = get_class($this);

  $this->_table = strtolower($this->_model)."s";

  }

  function __destruct() {

  }

  }

  新建視圖基類為template.class.php,具體代碼如下:

  <?php

  class Template {

  protected $variables = array();

  protected $_controller;

  protected $_action;

  function __construct($controller,$action) {

  $this->_controller = $controller;

  $this->_action =$action;

  }

  /* 設(shè)置變量 */

  function set($name,$value) {

  $this->variables[$name] = $value;

  }

  /* 顯示模板 */

  function render() {

  extract($this->variables);

  if (file_exists(ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'header.php')) {

  include(ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'header.php');

  } else {

  include(ROOT.DS. 'application' .DS. 'views' .DS. 'header.php');

  }

  include (ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. $this->_action . '.php');

  if (file_exists(ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'footer.php')) {

  include (ROOT.DS. 'application' .DS. 'views' .DS. $this->_controller .DS. 'footer.php');

  } else {

  include (ROOT.DS. 'application' .DS. 'views' .DS. 'footer.php');

  }

  }

  }

  做完了以上這么多操作,基本上整個MVC框架已經(jīng)出來了,下面就該制作我們的站點(diǎn)了。我們要做的站點(diǎn)其實(shí)很簡單,一個ToDo程序。

  首先是在我們的/application/controller/ 目錄下面新建一個站點(diǎn)控制器類為ItemsController,命名為itemscontroller.php,內(nèi)容為:

  <?php

  class ItemsController extends Controller {

  function view($id = null,$name = null) {

  $this->set('title',$name.' - My Todo List App');

  $this->set('todo',$this->Item->select($id));

  }

  function viewall() {

  $this->set('title','All Items - My Todo List App');

  $this->set('todo',$this->Item->selectAll());

  }

  function add() {

  $todo = $_POST['todo'];

  $this->set('title','Success - My Todo List App');

  $this->set('todo',$this->Item->query(' into items (item_name) values (''.mysql_real_escape_string($todo).'')'));

  }

  function ($id) {

  $this->set('title','Success - My Todo List App');

  $this->set('todo',$this->Item->query(' from items where id = ''.mysql_real_escape_string($id).'''));

  }

  }

  接下來就是先建站點(diǎn)的模型,在我們的/application/model/ 目錄下面先建一個站點(diǎn)模型類為Item,內(nèi)容直接繼承Model,代碼如下:

  <?php

  class Item extends Model {

  }

  最后一步是設(shè)置我們站點(diǎn)的視圖部分,我們現(xiàn)在/application/views/目錄下新建一個items的文件夾,再在items文件夾下建立與控制器重Action相同的文件,分別為view.php,viewall.php,add.php,.php,考慮到這么頁面中可能需要共用頁首和頁尾,所以再新建兩個文件,命名為header.php,footer.php,每個文件的代碼如下:

  view.php文件:查看單條待處理事務(wù)

  <h2><?php echo $todo['Item']['item_name']?></h2>

  <a href="../../../items//<?php echo $todo['Item']['id']?>">

  <span>Delete this item</span>

  </a>

  viewall.php文件:查看所有待處理事務(wù)

  <form action="../items/add" method="post">

  <input type="text" value="I have to..." onclick="this.value=''" name="todo"> <input type="submit" value="add">

  </form>

  <br/><br/>

  <?php $number = 0?>

  <?php foreach ($todo as $todoitem):?>

  <a href="../items/view/<?php echo $todoitem['Item']['id']?>/<?php echo strtolower(str_replace(" ","-",$todoitem['Item']['item_name']))?>">

  <span>

  <?php echo ++$number?>

  <?php echo $todoitem['Item']['item_name']?>

  </span>

  </a><br/>

  <?php endforeach?>

  add.php文件:添加待處理事務(wù)

  1

  <a href="../items/viewall">Todo successfully added. Click here to go back.</a><br/>

  .php文件:刪除事務(wù)

  1

  <a href="../../items/viewall">Todo successfully d. Click here to go back.</a><br/>

  header.php:頁首文件

  <html>

  <head>

  <title><?php echo $title?></title>

  <style>

  .item {width:400px;}

  input {color:#222222;font-family:georgia,times;font-size:24px;font-weight:normal;line-height:1.2em;color:black;}

  a {color:#222222;font-family:georgia,times;font-size:24px;font-weight:normal;line-height:1.2em;color:black;text-decoration:none;}

  a:hover {background-color:#BCFC3D;}

  h1 {color:#000000;font-size:41px;letter-spacing:-2px;line-height:1em;font-family:helvetica,arial,sans-serif;border-bottom:1px dotted #cccccc;}

  h2 {color:#000000;font-size:34px;letter-spacing:-2px;line-height:1em;font-family:helvetica,arial,sans-serif;}

  </style>

  </head>

  <body>

  <h1>My Todo-List App</h1>

  footer.php:頁尾文件

  1

  2

  </body>

  </html>

  當(dāng)然還有一個必不可少的操作就是在數(shù)據(jù)中中建立一張表,具體代碼如下:

  CREATE TABLE IF NOT EXISTS `items` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `item_name` var255) NOT NULL,

  PRIMARY KEY (`id`)

  ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=17 ;

  至此一個使用MVC開發(fā)的網(wǎng)站就開發(fā)完成了。


【如何使用PHP開發(fā)自己的MVC框架】相關(guān)文章:

PHP MVC框架路由學(xué)習(xí)筆記07-02

如何使用PHP開發(fā)高效的web系統(tǒng)10-19

PHP.MVC的模板標(biāo)簽系統(tǒng)09-19

php開發(fā)環(huán)境的搭建和使用10-01

教你如何使用php的session07-13

如何配置PHP開發(fā)環(huán)境07-21

PHP如何開發(fā)paypal支付插件07-22

JavaScript客戶端MVC框架用法06-07

如何使用php操作redis隊(duì)列實(shí)例09-15

如何使用PHP計算時間差07-20