关于重新学习thinkphp的思路

来源:互联网 发布:java项目源码 编辑:程序博客网 时间:2024/05/16 04:35

可能有很多写的不对的地方,会及时补充更正但不会直接修改,记录错误

直接从项目上手,单说一个模块,比如从数据库中读取数据并进行简单的curd

action 控制器,实现逻辑(专门负责下达指令,干活的不要)

model 封装类   专门干活的(大部分是操作数据库)

其他都很容易理解了,

D()方法   实例化自定义的model类,这时候就要跟model说你要干嘛干嘛了

M()方法   实例化基本的模型类  没有任何业务逻辑,只能完成基本的CURD 


home是网站主目录,但网站肯定都有后台,这里选择建立一个admin的文件夹,同时建立admin.php作为后台的入口文件。那么问题来了,action肯定是home和admin各有一套,因为事先的业务逻辑不通,但负责处理curd的model类呢,大同小异,只要写的足够好,完全可以用同一套model类,所以之类我只用了一套model,都放在home下面了,不论是home还是admin调用的时候实例化就可以了。

还有个小问题,我们在事先业务的时候,难免少不了要用到ajax,处理ajax的方法完全可以写到home或是admin里去,但我觉得为了排错也好,项目管理也好,还是应该在根下建立一个ajax的文件,在专门的文件里实现业务。同理对于其他功能我觉得也应该这样

ok,往下我会极其详细的介绍自己用tp开发项目中的一个模块,所有知识点包括引用、扩展的都会讲解

项目介绍:这是一个显示专题和专题分类的功能,总体说来很简单,后台管理员对专题内容进行管理,专题内容分别属于不同的专题类,专题和专题类都可以进行添加删除修改。   期间还有一些别的小功能

1 展示页面(读取数据并组合起来以列表的形式显示)

页面连接为 www.demo.com/admin.php?m=TopicCategory&a=topicCategoryListView

m是ACTION中控制器名,a是控制器中的方法,下面是topicCategoryList方法的代码

/**       * @detail   专题分类列表       * @author   zhuxinlei       * @date     2012-10-24       */       public function topicCategoryListView(){            Load('extend');            $topicCategory = D("home://TopicCategory");            $data = $topicCategory->getList();            /*判断权限*/            $AdminUser=D("home://AdminUser");            /*添加专题分类权限*/            $this->assign("addTopicCategory",$AdminUser->analisysPermission(session('oper'),'za'));            /*修改专题分类权限*/            $this->assign("editTopicCategory",$AdminUser->analisysPermission(session('oper'),'zb'));            /*删除专题分类权限*/            $this->assign("delTopicCategory",$AdminUser->analisysPermission(session('oper'),'zc'));            /*缓存专题分类数据权限*/            $this->assign("cacheTopicCategory",$AdminUser->analisysPermission(session('oper'),'zd'));            $this->assign('list',$data['list']);            $this->assign('page',$data['page']);            $this->assign('nowurl',$data['url']);            $this->display("topicCategory://topicCategoryListView");       }

但在解释该方法之前我要先解释两个方法,我先贴出两个方法名你就会明白了_initialize()和 _before_topicCategoryListView(),一个是初始化类时调用的方法,一个是执行所调动方法前的_before_调用方法(这是tp自带的)

public function _initialize() {         /*验证是否登录*/         if(!session("admin")){             $this->error("登录超时,请按F5刷新重新登录");         }       }

public function _before_topicCategoryListView() {           $AdminUser=D("home://AdminUser");           $rs=$AdminUser->analisysPermission(session('menu'),'ha');           if($rs==0){                $this->error("无操作权限");           }        }

_initialize方法,这类方法但凡是类初始化时就调用的方法,肯定都干不了什么逻辑上的事儿,大部分的功能都和session沾边,即验证一下登录是否超时啊等等的功能

_before_ 这里面就包含逻辑,但既然是在调动正式方法之前先执行的方法肯定和逻辑也没有太大的关系也就是说做不了什么正式的工作,比如这里,验证管理员是否有权限操作该模块

好的,开始介绍显示专题类数据的方法,逐行的解释

首先说一下总体的思路流程吧,现在目前所在的位置是TopicCategoy类的topicCategoryListView方法,这是控制器,需要调用model类获取数据(专题类数据),然后将数据放到模板中,生成页面

load('extend') 加载使用模板的扩展,目的是能够使用$this->display()和$this-assign()方法,我会在后面详细的介绍load方法的语法

$topicCategory = D("home://TopicCategory");$data = $topicCategory->getList();
这两句是实例化home目录下的名为TopicCategoryModel.class.php类,并调用里面的getList方法,那getList方法是干嘛的呢?只从名字上就可以推断出是获取专题类数据的,下面我贴出TopicCategoryModel.class.php类中的getList方法

public function getList() {        /*导入分页方法*/        import("ORG.Util.Page");        $settingConfig=RL("admin://settingConfig");$pageSize=$settingConfig['pageSize'];        /*获取总条数*/        $topicCategoryCount=$this->count();        /*获取分页对象*/        $topicCategoryPage= new Page($topicCategoryCount, $pageSize);        $pageList = $this->limit($topicCategoryPage->firstRow.','.$topicCategoryPage->listRows)->order('order_num desc,t_category_id desc')->select();        $page = $topicCategoryPage->show();        $data['page']=$page;        $data['list']=$pageList;        $data['url']=$topicCategoryPage->getNowPageUrl();        return $data;     }
看看getList是如何获取数据的

首先导入分页方法,后续我会用专门的文章解释tp中的分页类的代码

第二行和第三行代码是获取分页时每个页面显示的行数,因为在我的项目中这个行数是可以认为设定的所以我写到了设置文件中去,每次去读取,而不是自己手动指定。

继续往下,获取数据总条数

将获取的分页数量$pageSize和总条数$topicCategoryCount传给page类,获取分页对象

最重要的来了,获取数据,因为这里的逻辑非常简单没有太多的条件所以只有一个简单的limit 和order,将获取到的分页数据和专题类数据一并赋值给数组,返回

接下来继续走控制器中的topicCategoryListView方法,获取到了数据之后剩下的就很简单 了,将数据通过$this->assign()传到视图中就可以了。后续我会专门介绍assign和display的底层实现代码。其中还有一部分判断权限权限的代码这里是我自己项目中的代码这里就不解释了。

ok,下面看一下html页面,数据传到了html页面,该如何调用呢,这里只截取部分代码给介绍

 

<if condition="$list neq '' and  $list neq null ">       <volist name="list" id="vo" >      <tr class="datacolumn">        <td height="20" bgcolor="#FFFFFF"><div align="center">          <input type="checkbox" name="checkbox2" id="checkbox<!--{$vo.t_category_id}-->" value='<!--{$vo.t_category_id}-->'/>        </div></td>        <td height="20" bgcolor="#FFFFFF" class="STYLE19"><div align="center"><!--{$vo.t_category_name}--></div></td>                <td height="20" bgcolor="#FFFFFF" class="STYLE19"><div align="center"><!--{$vo.t_category_desc|utf_substr=60}--> </div></td>                <td height="20" bgcolor="#FFFFFF" class="STYLE19">            <div align="center" id='validate<!--{$vo.t_category_id}-->' >                     <if condition="$vo.is_display eq 1 ">            <img src='__TMPL__images/yes.gif'  <if condition="$editTopicCategory eq '1' "> onclick='displayTopicCategory(<!--{$vo.t_category_id}-->,0)' </if>/>            <else />            <img src='__TMPL__images/no.gif'  <if condition="$editTopicCategory eq '1' "> onclick='displayTopicCategory(<!--{$vo.t_category_id}-->,1)' </if>/>            </if>        </td>        <td height="20" bgcolor="#FFFFFF" class="STYLE19">            <div align="center" id='validate1<!--{$vo.t_category_id}-->' >                     <if condition="$vo.is_introduce eq 1 ">            <img src='__TMPL__images/yes.gif'  <if condition="$editTopicCategory eq '1' "> onclick='introduceTopicCategory(<!--{$vo.t_category_id}-->,0)' </if>/>            <else />            <img src='__TMPL__images/no.gif'  <if condition="$editTopicCategory eq '1' "> onclick='introduceTopicCategory(<!--{$vo.t_category_id}-->,1)' </if>/>            </if>        </td>        <td height="20" bgcolor="#FFFFFF" class="STYLE19"><div align="center"><!--{$vo.order_num}--> </div></td>        <td height="20" bgcolor="#FFFFFF"><div align="center" class="STYLE21">          <if condition="$editTopicCategory eq '1' ">          <a href='admin.php?m=TopicCategory&a=editTopicCategory&id=<!--{$vo.t_category_id}-->' style="color:black;">编辑</a>          </if>                 </div></td>      </tr>      </volist>      <else />            <tr>       <td colspan='8' height="30" bgcolor="#FFFFFF" style='text-align:center;font-size:12px;color:buttonface;'>--暂无数据--</td>      </tr>             </if>

说实话这里面的代码非常简单,而且能拿出来说的实质性的有用的不多,有用的也就是

<if condition="$list neq '' and $list neq null">

       //遍历数据

       <volist name="list" id=''vo'>

              <!--{$vo.t_category_name}--> 分类名称

               <!--{$vo.t_category_id}-->       分类ID

<else/>

       暂无数据

</if>

至此,一个基本的展示数据的流程已经展示完毕。

总结一下,总体思路:从数据库中读取数据,然后放到页面中。那么,怎么从数据库读取数据呢,具体的操作让相应的model类做,那谁让model类做这些工作呢?当然就是控制器action了,首先实例化model类,然后调用里面获取数据的方法getList。获取数据后传给视图页面。that'all,easy

这里拓展一个小知识吧,我这里需要一个功能,就是控制专题类是否对用户显示,通过相应的is_display的0 1值来判断,要求管理员点击一个对号或差号的小图片来实现是否显示,这里需要马上改变图片,要用到ajax.

<if condition="$vo.is_display eq 1 ">            <img src='__TMPL__images/yes.gif'  <if condition="$editTopicCategory eq '1' "> onclick='displayTopicCategory(<!--{$vo.t_category_id}-->,0)' </if>/>            <else />            <img src='__TMPL__images/no.gif'  <if condition="$editTopicCategory eq '1' "> onclick='displayTopicCategory(<!--{$vo.t_category_id}-->,1)' </if>/></if>
就是html中的这段代码,可以看到的是调用的是onclick事件,传入的是相应的id和is_display字段的值,下面是displayTopicCategory 方法的js代码

function displayTopicCategory(sourceId,vali) {                var url="ajax.php?m=TopicCategory&a=displayTopicCategory";          var  params = {idStr:sourceId,status:vali};          $.get(url,params,valCallBack,'text');}
这里用的是jquery中封装好的$.get方法,语法代码很简单,合理需要注意的是我上面提到的处理ajax请求的文件我放到了单独建立的ajax文件夹里,这样不管以后排错还是项目管理都会方便很多,同理ajax.php?m=TopicCategory&a=displayTopicCategory   调用的是ajax下的TopicCategory控制器的displayTopicCategory方法,下面是该方法的代码
public function displayTopicCategory() {           import('common','admin/Common','.php');           $id = $this->_get('idStr');           $status = $this->_get('status');           $topicCategory = D("home://TopicCategory");           $isSuccess = $topicCategory->valiDisplay($id,$status);           adminlog('','edit','topicCategory',$id);           echo $isSuccess?"1,".$id.",".$status:"0,".$id.",".$status;           exit;}
因为这里是通过get传值的,所以要用到$this->_get()取值。同样因为这是一个控制器,他只负责逻辑,具体的实现让model去做就可以了,这个控制器里面我们要做什么呢?通过传入的t_category_id和is_display值来改变is_display字段。具体的操作还是让model类去做,那么接下来的代码就非常容易解释了,实例化home下的topicCategory类,调用里面的valiDisplay方法,下面我贴出valiDisplay方法的代码

public function valiDisplay($id,$status) {        return $this->where('t_category_id = '.$id)->setField('is_display',$status);     }

非常简单,不需要介绍。需要注意的是这里echo返回的数据。类型为type.

jquery中调用ajax的$.get(url,data,callback,type)方法中的可以传入四个参数,其中第三个为返回数据后的调用函数,下面贴出调用函数valCallBack方法的代码

function valCallBack(data) {           if(data=='2'){                alert("登录过期请重启登录");                window.parent.location.href="admin.php"                return false;           }           var dataArr=data.split(",");           if(dataArr[0]=="1"){              if(dataArr[2]==0){                 $("#validate"+dataArr[1]).html("<img src='__TMPL__images/no.gif'  onclick='displayTopicCategory("+dataArr[1]+","+1+")' />");              }else{                 $("#validate"+dataArr[1]).html("<img src='__TMPL__images/yes.gif' onclick='displayTopicCategory("+dataArr[1]+","+0+")' />");              }           }else{               alert("更新失败");           }       }
经常用到的obj.split()  split方法是js中的分割方法,它将字符串分割成数组。go on,根据条件用jquery相应的修改html内容。

---------------------------------------这是添加功能的分割线-------------------------------------------------

添加页面有一点需要讲解,为了满足用户输入之后马上验证的效果,所以要用到ajax,不是简单的验证输入内容长短、是否为空等等,还需要验证输入内容是否重复等等需要操作数据库的功能

拿验证输入名称的功能为例讲解,下面是html中的代码

<td style='text-align:left;'><input type="text" class='text' name='t_category_name' id="t_category_name"/></td><td><span id="nameTip"></span></td>
以及jquery的验证代码

 $(document).ready(function(){        $.formValidator.initConfig({formID:"formTopicCategory",debug:false,submitOnce:true,onError:function(msg,obj,errorlist){$("#errorlist").empty();$.map(errorlist,function(msg){$("#errorlist").append("<li>" + msg + "</li>")});alert(msg);},submitAfterAjaxPrompt : '有数据正在异步验证,请稍等...'});    $("#t_category_name").formValidator({tipID:"nameTip",onShow:"",onFocus:"请填写专题分类",onCorrect:"谢谢你的配合",defaultValue:""}).inputValidator({min:2,max:50,onError: "名称长度不能小于2个字符大于50个字符!"}).regexValidator({regExp:"^([\/\u4E00-\u9FA5|a-zA-Z|1-9])+$",onError:"名称只能是数字、英文和汉字且英文小于50个字符,汉字小于25个字"}).ajaxValidator({    type : "get",url : "ajax.php?m=TopicCategory&a=isTopicCategoryUnique",      datatype : "json",        success : function(data){                        if( data == "1" ){                return true;}            else{                return false;}},//buttons: $("#button"),error: function(){alert("服务器没有返回数据,可能服务器忙,请重试");},onError : "专题分类名称重复,请重新输入",onWait : "正在对用户名进行合法性校验,请稍候..."});
因为有很多的字段需要验证,而每次都要验证很多项内容,使用原生的js或jquery 代码的重复率都太高,这里引用了jquery的一个formvalidate插件,验证就变的简单许多,这里只管调用就可以        语法都很简单,就是这个正则表达式,学了3年都没学好,现在更是全都忘了,后续我会拿出一篇文章来单独介绍正则。

ajax里验证是否唯一的代码就很简单了

public function isTopicCategoryUnique() {           $name = $this->_get('t_category_name');           $topicCategory = D("home://TopicCategory");           $isUnique = $topicCategory->isTopicCategoryUnique($name);           echo $isUnique?0:1;           exit;       }
over,添加功能的html页面就这么结束了,很简单。下面该到了正式添加数据的功能了,到了提交form表单的时候了,提交到哪里呢?这时候就是猜也应该能猜到具体处理添加数据的方法名了admin.php?m=TopicCategory&a=addTopicCategoryPost   下面是该方法的代码

/**       * @detail   添加专题分类       * @author   zhuxinlei       * @date     2012-10-24       */        public function addTopicCategoryPost() {            $topicCategory = D("home://TopicCategory");            if($topicCategory->create()){                if($topicCategory->add()){                    $this->success('添加成功','admin.php?m=TopicCategory&a=topicCategoryListView');                    adminlog($this->_post('t_category_name'),'add','topicCategory');                }else{                    $this->error($topicCategory->getError());                }            }else{                 $this->error($topicCategory->getError());            }        }
这是model类中自动验证的代码,这是thinkphp中自带的验证字段的属性

protected $_validate = array(        array('t_category_name','require','分类名称不能为空',0),        array('t_category_name','/^[\/a-zA-Z0-9一-龥]{2,}$/','分类名称格式不正确,只能填写数字、英文和汉字',0),        array('t_category_name','2,50','名称输入长度不正确,要求输入2-50个字符',0,'length'),        array('t_category_name','','分类名称不能重复',0,'unique',3),        array('t_category_desc','0,255','描述最多输入255个字符',0,'length'),        array('is_display','require','是否显示必须选择',0),        array('is_introduce','require','是否显示必须选择',0),        array('order_num','number','排序ID只能是数字',2));
都没有什么需要讲解的,唯一一个,因为这里没有对插入数据有特殊要求的所以直接调用了add方法并没有传入参数,不传入参数的话使用的是刚才创建的数据对象。

----------------------------------这是修改功能的分割线-------------------------------------------

整体功能实在简单,没什么要写的。包括删除功能更简单








1 0