MVC框架


MVC框架淺析(基於PHP)

      MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。

一.MVC概念

      MVC 是一種使用 MVC(Model View Controller 模型-視圖-控制器)設計創建 Web 應用程序的模式,它們各自處理自己的任務:
      MVC 模式同時提供了對 HTML、CSS 和 JavaScript 的完全控制。


Model(模型)是應用程序中用於處理應用程序數據邏輯的部分。
  通常模型對象負責在數據庫中存取數據。
View(視圖)是應用程序中處理數據顯示的部分。
  通常視圖是依據模型數據創建的。
Controller(控制器)是應用程序中處理用戶交互的部分。
  通常控制器負責從視圖讀取數據,控制用戶輸入,並向模型發送數據。


      MVC 分層有助於管理復雜的應用程序,因為您可以在一個時間內專門關注一個方面。例如,您可以在不依賴業務邏輯的情況下專注於視圖設計。同時也讓應用程序的測試更加容易。
      MVC 分層同時也簡化了分組開發。不同的開發人員可同時開發視圖、控制器邏輯和業務邏輯。

      有很多程序員往往認為MVC是一種設計模式。實際上MVC是一種框架模式。框架通常是代碼重用,而設計模式是設計重用,架構則介於兩者之間,部分代碼重用,部分設計重用,有時分析也可重用。

      簡而言之:框架是大智慧,用來對軟件設計進行分工;設計模式是小技巧,對具體問題提出解決方案,以提高代碼復用率,降低耦合度。

二.MVC理解

面向對象的思維

獲取和描述系統的用戶需求;

識別角色和用例,畫UseCase;

根據功能從用例圖中找三種類型類:實體類、邊界類和控制類;將所有找到的三種類集中綜合在一起得到三大模型:實體模型、視圖模型、邏輯模型。實際上對應着MVC。進而進行WEB建模。

三.MVC實踐

      MVC是一種框架模式,只有在實例中才能更好的理解MVC。本文基於ThinkPHP3.2.3的MVC框架,實現一個簡單的留言板系統。

1.    ThinkPHP3.2.3

      ThinkPHP是一個快速、兼容而且簡單的輕量級國產PHP開發框架,遵循Apache2開源協議發布,從Struts結構移植過來並做了改進和完善,同時也借鑒了國外很多優秀的框架和模式,使用面向對象的開發結構和MVC,融合了Struts的思想和TagLib(標簽庫)、RoR的ORM映射和ActiveRecord模式。
      ThinkPHP可以支持windows/Unix/Liunx等服務器環境,支持MySql、PgSQL、Sqlite以及PDO等多種數據庫。作為一個整體開發解決方案,它包含了底層架構、兼容處理、基類庫、數據庫訪問層、模板引擎、緩存機制、插件機制、角色認證、表單處理等常用的組件,並且對於跨版本、跨平台和跨數據庫移植都比較方便。
      ThinkPHP3.2.3是最新版本. 獲取地址:http://www.thinkphp.cn/,(初學建議下載完版)。
      ThinkPHP需要集成環境,這里用Wampserver。Wamp就是Windows Apache Mysql PHP集成安裝環境,即在window下的apache、php和mysql的服務器軟件。PHP擴展、Apache模塊,開啟/關閉鼠標點點就搞定,再也不用親自去修改配置文件了,WAMP它會去做。
      獲取地址:http://www.wampserver.com/en/

2.  需求分析和原型設計
2.1 系統需求

      用戶進行注冊,然后登陸系統,進行留言。

2.2 原型設計

      Axure RP 能幫助網站需求設計者,快捷而簡便的創建 基於目錄組織的原型文檔、功能說明、交互界面以及帶注釋的wireframe網頁,並可自動生成用於演示的網頁文件和word文檔,以提供演示與開發。
      獲取地址:http://www.axure.com/

2.2.1 登陸頁面:

image

2.2.2 注冊頁面:

image

2.2.3 系統頁面:

image

2.3 功能設計

注冊模塊:注冊用戶
登錄模塊:登錄    退出               
留言模塊:提交留言信息    顯示留言信息

2.4 數據庫設計    
2.4.1 分析:

用戶表:用戶名、密碼、性別           
留言表:留言題目、留言內容、附件名、留言時間
用戶表與留言表之間是一對多的關系,需要在留言表中設置外鍵。      

 2.4.2 設計:

用戶表(tp_user)

字段

類型

notnull

默認值

備注

id

Int

notnull

 

主鍵 自增

username

varchar(30)

 

‘’

用戶名

password

char(32)

 

‘’

密碼

sex

tyint

notnull

1

性別:1代表男 0 代表0

留言表(tp_message)

字段

類型

notnull

默認值

備注

id

Int

notnull

 

主鍵 自增

title

varchar(60)

 

‘’

題目

content

test

 

‘’

內容

filename

varchar(30)

notnull

1

附件名

time

int

   

時間:時間戳格式

uid

int

   

外鍵:用戶表中的id

3. ThinkPHP設計思想與目錄文件

      在Wampserver安裝地址下的www文件夾下新建項目think_message。將ThinkPHP_3.2.3_full.zip解壓放到think_message中。

      在瀏覽器中,打開項目think_message,ThinkPHP會自動在Application文件夾下創建Home文件夾,它是前台模塊;同樣我們可以在Application下創建后台模塊,本留言系統暫時不建立后台模塊。到此ThinkPHP環境基本搭建完畢。

3.1 解壓縮可以看到初始的目錄結構如下:

image

3.2 ThinkPHP內核 框架設計

image

3.3 模塊設計

image

每個模塊是相對獨立的,其目錄結構如下:

image

以后我們主要在Controller、Model和View三個文件下實施項目,即MVC。

4.  實施項目

      本項目用sublime編輯器,進行代碼編輯。

4.1 打開phpmyadmin,建立數據庫messge

新建tp_user表和tp_message表,按照數據庫設計對應鍵入。注意:整理項Collation選擇 utf8- general-ci。

4.2 連接數據庫

Application->Common->Conf下的config.php,鍵入一下代碼:

//數據庫配置信息
    'DB_TYPE' => 'mysql', // 數據庫類型
    'DB_HOST' => 'localhost', // 服務器地址
    'DB_NAME' => 'message', // 數據庫名
    'DB_USER' => 'root', // 用戶名
    'DB_PWD' => '', // 密碼
    'DB_PORT' => 3306, // 端口
    'DB_PREFIX' => 'tp_', // 數據庫表前綴
    'DB_CHARSET'=> 'utf8', // 字符集
4.3 編碼

      在根目錄下Public下建立Css、Js、Images和Uploads四個文件夾,分別用於存儲系統的css代碼、js代碼、系統所用的圖片資源和用戶上傳的文件資源。

      根據功能設計,我們首先在Application->Home->Controller,建立三個控制器:RegisterController.class.php、LoginController.class.php、MessageController.class.php;以及建立IndexController.class.php控制器,系統默認進入的控制器。以后有需要我們再添加。控制器里面是函數,處理不同邏輯需求。

      根據所建控制器及要顯示的頁面,在Application->Home->View下,分別創建Index(系統頁面)、Register(注冊頁面)和Login(登陸頁面)文件夾,用於原型設計的三個頁面顯示。

4.3.1 注冊

功能:實現用戶注冊

V

注冊需要顯示注冊頁面,我們在Home->View->Register文件夾下創建reg.html用於顯示注冊頁面。代碼如下:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
        <title>注冊</title>
        <load href="__PUBLIC__/Css/Home/reg.css" />
        <load href="__PUBLIC__/Js/jquery.js"/>
        <load href="__PUBLIC__/Css/basic.css" />
        
        <script>
            $(function(){
                var error=new Array();
                $('input[name="username"]').blur(function(){
                    var username=$(this).val();
                    $.get('__URL__/checkName',{'username':username},function(data){
                        if(data=='不允許'){
                            error['username']=1;
                            $('input[name="username"]').after('<p id="umessage" style="color:red">該用戶名已經注冊</p>');
                        }else{
                            error['username']=0;
                            $('#umessage').remove();
                        }
                    });
                });

                //提交表單
                $('img.register').click(function(){
                    if(error['username']==1){
                        return false;
                    }else{
                        $('form[name="myForm"]').submit();
                    }
                });
            });
        </script>
    </head>
    <body>
        <form action='__URL__/doReg' method='post' name='myForm'>
            用 戶 名:<input type='text' name='username'/><br/>
            密  碼:<input type='password' name='password'/><br/>
            確認密碼:<input type='password' name='repassword'/><br/>
            性  別:<input type='radio' name='sex' value='1' class='radio'/><input type='radio' name='sex' value='0' class='radio'/><br/>
            驗 證 碼:<input type='text' name='code'/>
                       <img src='__MODULE__/Public/code' onclick="this.src=this.src+'?'+Math.random()"/>
                      <br/>
            <img src='__PUBLIC__/Images/register.gif' class='register'/>
            <img src='__PUBLIC__/Images/reset.gif' class='reset'/>
        </form>
    </body>
</html>

C

RegisterController.class.php控制器代碼如下:

<?php
namespace Home\Controller;
use Think\Controller;
class RegisterController extends Controller {
    //顯示注冊頁面
    public function reg(){
        $this->display();
    }

    //檢查用戶是否注冊過
    public function checkName(){
        $username=$_GET['username'];
        $user=M('User');
        $where['username']=$username;
        $count=$user->where($where)->count();
        if($count){
            echo '不允許';
        }else{
            echo '允許';
        }
    }
    //注冊
    public function doReg(){
    
        $user=D('User');
        if(!$user->create()){
            $this->error($user->getError());
        }
    
        $lastId=$user->add();
        if($lastId){
            $this->redirect('Index/index');
        }else{
            $this->error('用戶注冊失敗');
        }

    }
}
?>

建立了PublicController.class.php控制器,設置驗證碼的屬性。代碼如下:

<?php
namespace Home\Controller;
use Think\Controller;
class PublicController extends Controller {
    public function code(){
        $Verify = new \Think\Verify();
        $Verify->fontSize = 16;  
         $Verify->length   = 4;
        $Verify->imageW = 130;  
         $Verify->imageH = 30;
        $Verify->entry();
}
}
?>

M

前台的驗證只是提供用戶體驗,安全還是要后台進行驗證。TinkPHP實現自動驗證,在Home->View->Model下,新建UserModel.class.php模型,進行自動驗證。代碼如下:

<?php
namespace Home\Model;
use Think\Model;

class UserModel extends Model{
    protected $_validate=array(
        array('code','require','驗證碼必須填寫!'),
        array('code','checkCode','驗證碼錯誤!',0,'callback',1),
        array('username','require','用戶必須填寫!'),
        array('username','','用戶已經存在',0,'unique',1),
        array('username','/^\w{6,}$/','用戶名必須6個字母以上',0,'regex',1),
        array('repassword','password','確認密碼不正確',0,'confirm'), 
    );

    protected function checkCode($code){
        function check_verify($code, $id = ''){
            $verify = new \Think\Verify();
            return $verify->check($code, $id);
        }

        if(!check_verify($code,$id = '')){
            return false;
        }else{
            return true;
        }
    }
}
?>
4.3.2 登陸

功能:實現用戶登陸

V

登陸頁面需要顯示,我們在Home->View->Login文件夾下創建login.html用於顯示注冊頁面。代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
    <load href="__PUBLIC__/Css/basic.css" />
    <load href="__PUBLIC__/Css/Home/login.css" />
    <load href="__PUBLIC__/Js/jquery.js"/>
    <script>
        $(function(){
            $('img[title="login"]').click(function(){
                $('form[name="myForm"]').submit();
            });

            $('img[class="register"]').click(function(){
                    window.location='__APP__/Home/Register/reg';
            });
        });
    </script>
</head>
<body>
    <form action='__URL__/doLogin' method='post' name='myForm'>
        用戶名:<input type='text' name='username'/><br/>
        密 碼:<input type='password' name='password'/><br/>
        驗證碼:<input type='text' name='code'/>
        <img src='__MODULE__/Public/code' onclick="this.src=this.src+'?'+Math.random()"/><br/>
        <img src='__PUBLIC__/Images/login.gif' title='login' class='submit'/>
        <img src='__PUBLIC__/Images/register.gif' class='register'/>
    </form>        
</body>
</html>

C

LoginController.class.php控制器代碼如下:

<?php
namespace Home\Controller;
use Think\Controller;

class LoginController extends Controller {
    //顯示登陸頁面
    public function index(){
        $this->display();
    }

    public function doLogin(){
        //接受值
        //判斷用戶在數據庫中是否存在
        //存在 允許登錄
        //不存在 顯示錯誤信息
        $username=$_POST['username'];
        $password=$_POST['password'];
        $code=$_POST['code'];
        
        function check_verify($code, $id = ''){
            $verify = new \Think\Verify();
            return $verify->check($code, $id);
        }

        if(!check_verify($code,$id = '')){
            $this->error('驗證碼輸入錯誤!');
        }

        $user=M('User');
        $where['username']=$username;
        $where['password']=$password;
        $arr=$user->field('id')->where($where)->find();
        if($arr){
            $_SESSION['username']=$username;
            $_SESSION['id']=$arr['id'];
            $this->success('用戶登錄成功',U('Index/index'));
        }else{
            $this->error('該用戶不存在');
        }
    }
}
?>
4.3.3 系統頁面

功能:實現用戶用戶留言

V

系統頁面使用frameset將整個頁面分為3部分top,left,right,我們在Home->View->Index文件夾下創建index.html、top.html、left.html,right.html。代碼如下:

index.html。代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>

<frameset rows='20%,*'>
    <frame src='__URL__/top' name='top'/>
    <frameset cols='50%,50%'>
        <frame src='__URL__/left' name='left'/>
        <frame src='__URL__/right' name='right'/>
    </frameset>
</frameset>
</html>

top.html,用於顯示歡迎。代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>top</title>
</head>
<body>
    <p>歡迎你 <strong>{$Think.session.username}</strong> !<a href='__APP__/Home/Login/doLogout' target='_top'>退出</a></p>
    <h1 align="center">ThinkPHP留言板系統</h1>
</body>
</html>

left.html,用於顯示所有的留言內容。代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Left</title>
</head>
<body>
    <foreach name='list' item='vo'>
        留言題目:{$vo.title}<br/>
        <p>留言內容:</p>{$vo.content}<br/>
        附件名:{$vo.filename}<br/>
        {$vo.username}  {$vo.time|date='Y/m/d H:i:s',###}<br/>
        <hr/>
    </foreach>
    {$show}
</body>
</html>

right.html,用於提交留言。代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Right</title>
</head>
<body>
    <form action='__MODULE__/Message/doMess' method='post' enctype='multipart/form-data'>
        留言題目:<input type='text' name='title'/><br/>
        留言內容:<textarea name='content'></textarea><br/>
        附  件:<input type='file' name='filename'/><br/>
        <input type='submit' value='提交留言'/>
    </form>
</body>
</html>

C

IndexController.class.php控制器,用於頁面的整體顯示。代碼如下:

<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends CommonController {
    public function index(){
        $this->display();
    }

    public function top(){
        $this->display();
    }

    public function left(){
        $message=D('Message');
        $count=$message->count();//獲取數據的總數
        $Page = new \Think\Page($count,3);// 實例化分頁類 傳入總記錄數和每頁顯示的記錄數(3)
        $show = $Page->show();// 分頁顯示輸出
        $arr=$message->relation(true)->order('time desc')->limit($Page->firstRow.','.$Page->listRows)->select();
        $this->assign('list',$arr);
        $this->assign('show',$show);
        $this->display();
    }

    public function right(){
        $this->display();
    }
}
?>

MessageController.class.php控制器,用於留言的邏輯控制。代碼如下:

<?php
namespace Home\Controller;
use Think\Controller;

class MessageController extends Controller {
    public function doMess(){
            
        $upload = new \Think\Upload();// 實例化上傳類
        $upload->rootPath = './Public/Uploads/';//設置附件上傳目錄
        $info = $upload->upload();
        if(!$info) {// 上傳錯誤提示錯誤信息
            $this->error($upload->getError());
        }else{// 上傳成功 獲取上傳文件信息
            foreach($info as $file){
            // $savename=$file['savepath'].$file['savename'];
                $savename=$file['savename'];
            }
        }

        $message=D('Message');
        $message->create();
        $message->filename=$savename;
        // $message->time=time();
        // $message->uid=$_SESSION['id'];
        $lastId=$message->add();
        if($lastId){
            $this->success('留言成功');
        }else{
            $this->error('留言失敗');
        }
    }
}
?>

M

TinkPHP實現自動完成,並實現tp_user表和tp_messgae表的關聯取字段值,在Home->View->Model下,新建MessageModel.class.php模型,進行自動驗證。代碼如下:

<?php
namespace Home\Model;
use Think\Model\RelationModel;

class MessageModel extends RelationModel{
    protected $_auto=array(
        array('time','time',1,'function'),
        array('uid','getId',1,'callback'),
    );

    protected $_link=array(
        'User'=> array(  
             'mapping_type' => self::BELONGS_TO,
              'class_name'=>'User',
              'foreign_key'=>'uid',
            'mapping_name'=>'user',
            'mapping_fields'=>'username',
            'as_fields'=>'username',
        ),    
    );
        
    protected function getId(){
        return $_SESSION['id'];
    }
}
?>

 

為了網站安全

必須進行登錄才能進入任何一個頁面,添加CommonController.class.php控制器。代碼如下:

<?php
namespace Home\Controller;
use Think\Controller;
class CommonController extends Controller {
    Public function _initialize(){
           // 初始化的時候檢查用戶權限
        if(!isset($_SESSION['username']) || $_SESSION['username']==''){
            $this->redirect('Login/login');
        }
    }
}
?>

最終的文件目錄如下:

image

至此基於PHP的MVC思想建立的留言系統已完成。

四.結束

      MVC框架模式對項目的效率和可重用是至關重要的。當然在開發時我們應該靈活的應用MVC。也有新的框架模式不斷涌現,相互參考才是最重要的。

      留言系統源代碼:https://github.com/jingwhale/mvc-php-messagesystem

轉載需注明轉載字樣,標注原作者和原博文地址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM