zoukankan      html  css  js  c++  java
  • 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 HomeController;
    use ThinkController;
    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 HomeController;
    use ThinkController;
    class PublicController extends Controller {
        public function code(){
            $Verify = new ThinkVerify();
            $Verify->fontSize = 16;  
             $Verify->length   = 4;
            $Verify->imageW = 130;  
             $Verify->imageH = 30;
            $Verify->entry();
    }
    }
    ?>

    M

    前台的验证只是提供用户体验,安全还是要后台进行验证。TinkPHP实现自动验证,在Home->View->Model下,新建UserModel.class.php模型,进行自动验证。代码如下:

    <?php
    namespace HomeModel;
    use ThinkModel;
    
    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 ThinkVerify();
                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 HomeController;
    use ThinkController;
    
    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 ThinkVerify();
                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 HomeController;
    use ThinkController;
    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 ThinkPage($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 HomeController;
    use ThinkController;
    
    class MessageController extends Controller {
        public function doMess(){
                
            $upload = new ThinkUpload();// 实例化上传类
            $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 HomeModel;
    use ThinkModelRelationModel;
    
    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 HomeController;
    use ThinkController;
    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

    转载需注明转载字样,标注原作者和原博文地址。

  • 相关阅读:
    mysql前缀索引的应用
    记博客园
    好的博客网站(随手记)
    memcache应对缓存失效问题
    memcache内存分配问题
    memcached使用libevent 和 多线程模式
    RabbitMQ用户及权限控制
    Nginx基础之常用配置
    PHP-fpm进程池优化方法
    php-fpm参数详解
  • 原文地址:https://www.cnblogs.com/jingwhale/p/4303684.html
Copyright © 2011-2022 走看看