用户
 找回密码
 入住 CI 中国社区
搜索
查看: 13236|回复: 12
收起左侧

[数据库] 对crud的改进

  [复制链接]
发表于 2010-5-15 11:53:23 | 显示全部楼层 |阅读模式
《php敏捷开发框架codeigniter》一书中单独有一章,第13章《快捷的 CRUD 及其配合使用》,讲到了crud在开发中的便捷之处。

     crud说白了就是将数据库的增删改和查询封装成了一个类,这样你在控制器中调用了这个类后,只须简单的写几句话就可以完成数据库操作。可能很多人在做开发的时候把每张数据表单独写了一个model,然后在控制器中调用,其实我们细细想来,这些若干的model中有许多部分是相同的,或者说是相似的。我们就是把这些相类似的操作封装成一个类,这样就大大节省了我们的代码量,而且它还是可复用的,易于维护的。
     在看了原书中crud的实现方法后,发现它还是有缺陷的,首先要是使用原作者的crud类,那么主键必须是数字,虽然大部分数据设计中主键都是选择id之类的字段,但我们也不能将非数字类型的数据表拒之门外,这太武断了;其次,数组的添加和修改的操作中,原作者寄希望于通过post来传递数据,那么我们就可能考虑到,有些数据并不是通过客户端提供的,比如说一篇文章的发表时间,我们肯定是要在服务器端取,虽然我们也可以在客户端生成数据,然后post过来,但是你能保证客户端的时间跟服务器同步吗;还有有时候我们要操作的并不仅仅是一张表,例如我们要通过一个控制器修改一个学生的信息,学生的信息保存在一张表中,然后学生表中有一个学校id的外键,对应学校这张数据表,我们必须同时查询两种表,一次是查询这个学生的信息,一次是查询所有学校的学校名和学校ID,而原作者给出的代码只能在一个控制中调用一次crud,操作一张表,这显然不是我们想看到的。
     对于第一个问题,我在函数中专门设定了主键类型的检查。对于第二个问题在使用post的基础上,我还另外写了一个使用数组传递数据的操作函数。对于第三个问题,我选择了使用构造函数__construct和析构函数__destruct(),进行保护现场。
     下面是代码: my crud.7z (3.72 KB, 下载次数: 129)
     按照MVC的思想,我们要把数据的操作封装在M层中,因此我们按照在model中调用crud,把数据返回给cotronller的思路,进行设计。
     下面摘录部分代码,进行分析:
      article_manage.php的部分代码
PHP复制代码
<?php
class Article_manage extends Model {
     private $CI;
     private $table = 'jx_article';
     private $key = 'aid';
     private $channelTable = 'jx_channel';
     private $memberTable = 'jx_member';
     private $commentTable = 'jx_comment';
     private $adminTable = 'jx_admin';
     private $childrenChannel = array();
     public function __construct() {
          parent::Model();
          $this->load->library('codestr');
          $this->CI = & get_instance();
          $this->CI->load->model('crud');
          $this->CI->crud->Crud($this->table,$this->key);
     }
        /**
        * getOne
        *
        * 返回一篇文章内容
        *
        * @param int $aid 文章ID
        * @return array $article 文章详细内容信息
        *
        **/

        public function getOne($aid,$decode=true,$conditions = array(),$returnCname = false) {
                //$article = $this->CI->crud->getOne(array(),$aid);
                if(count($conditions)>0) {
                        $article = $this->CI->crud->getOne($conditions);
                } else {
                        $article = $this->CI->crud->getOneByKey($aid);
                }
                if(is_null($article))        return null;
                if($decode==true) {
                        $article['title'] = $this->codestr->unescape($article['title']);
                        $article['content'] = $this->codestr->unescape($article['content']);
                }
                if($returnCname==true) {
                        $article['cname'] = $this->getChannel($article['f_cid']);
                }
                return $article;
        }
        /**
        * insertOrUpdate
        *
        * 插入或者修改
        *
        * @param array $article 文章的详细内容
        * @return int $result 影响的行数
        **/

        public function insertOrUpdate($article) {
               
                $result = $this->CI->crud->insertFromArray($article);
                return $result;
        }
        /**
        * delete
        * 删除一篇文章
        *
        * @param int $aid 文章ID
        * @return int $result 影响行数
        **/

        public function delete($aid) {
 
                $result = $this->CI->crud->delete($aid);
                return $result;
        }
 
 
 
         //……省略N多的代码
 
        /**
        * __destruct
        *
        * 销毁当前成员变量,恢复以前成员变量(恢复现场)
        *
        * @param null
        * @return null
        **/

        public function __destruct() {
             $this->CI->crud->__destruct();
        }
复制代码



article.php
PHP复制代码
<?php
class Article extends MY_Controller{
        public function __construct() {
                parent::__construct();
                $this->load->model('article_manage');
                $this->load->library('class_post');
                $this->load->library('pagination');
        }
        public function index() {
               
        }
        /**
        * getChannel
        *
        * 返回所有栏目,每个栏目都有ID
        * @return array 栏目数组
        **/

        private function getChannel() {
                $this->load->model('channel');
                $this->channel->__construct();
                //$channels = $this->channel->show_channel_as_select();
                $channels = $this->channel->show_channel_as_select_for_lanmu();
                $this->channel->__destruct();
                //echo $channels;
                return $channels;
        }
 
       private function getChannel2() {
                $this->load->model('channel');
                $this->channel->__construct();
                $channels = $this->channel->show_channel_as_select();
                $this->channel->__destruct();
                //echo $channels;
                return $channels;
        }
 
       public function add() {
                //$channels = $this->article_manage->showAllChannel();                
                $t = '文章添加';
                $data = array('t' => $t,'action' => 'add','channels' => $this->getChannel2());
                //print_r($data);
                $this->load->view('admin/article',$data);                
        }
 
       public function addDeal() {
                $this->load->library('unit_test');
                $title = $this->input->post('title',true);
                if($title=='') {
                        echo 'error,标题不能为空';
                        return false;
                }
                $content = $this->input->post('content');
                if($content=='%3Cp%3E%3Cbr%3E%3C/p%3E'||$content=='%3CP%3E%3C/P%3E') {
                        echo 'error,内容不能为空';
                        return false;
                }
                $tcolor = $this->input->post('tcolor',true);//
                if($this->class_post->fun_char(3,7,$tcolor)==false) {
                        echo 'error,非法传参tcolor';
                        return false;
                }
                $f_cid = $this->input->post('channel',true);//
                if($this->class_post->fun_num($f_cid)==false) {
                        echo 'error,非法传参channel';
                        return false;
                }
                $author = $this->input->post('author',true);//
                $f_uid = $this->input->post('uid',true);
                if($this->class_post->fun_num($f_uid)==false) {
                        echo 'error,非法传参uid';
                        return false;
                }
                $source = $this->input->post('source',true);
                $istop = $this->input->post('top',true);//
                if($this->class_post->fun_num($istop)==false) {
                        echo 'error,非法传参top';
                        return false;
                }
                $recommend = $this->input->post('levels',true);//
                if($this->class_post->fun_num($recommend)==false) {
                        echo 'error,非法传参levels';
                        return false;
                }
                $cancomment = $this->input->post('comment',true);//
                if($this->class_post->fun_num($cancomment)==false) {
                        echo 'error,非法传参comment';
                        return false;
                }
                date_default_timezone_set("PRC");
                $date = date('Y-m-d');
                $data = array (
                        'title' => $title,
                        'tcolor' => $tcolor,
                        'f_cid' => $f_cid,
                        'author' => $author,
                        'f_uid' => $f_uid,
                        'source' => $source,
                        'istop' => $istop,
                        'recommend' => $recommend,
                        'cancomment' => $cancomment,
                        'time' => $date,
                        'content' => $content
                );
                $result = $this->article_manage->insertOrUpdate($data);
                if(is_null($result)||(isset($result['affected'])&&$result['affected']<=0)) {
                        echo 'error,添加失败';
                } else {
                        echo '添加成功';
                }
                //$this->output->enable_profiler(true);
        }
 
//……在此省略N多的代码
复制代码


注意我们在article这个控制器中调用了两个crud的实例,其中一此调用是在getChannel2()中,记得在这个函数中使用$this->channel->__construct();和$this->channel->__destruct();这两步起到了保护现场的作用。

评分

参与人数 1威望 +5 收起 理由
Hex + 5 精品文章

查看全部评分

发表于 2015-4-28 19:01:30 | 显示全部楼层
用过thinkphp的CURD么?
发表于 2015-10-30 21:54:53 | 显示全部楼层
老帖子了,支持一下
发表于 2011-6-23 12:55:43 | 显示全部楼层
不错,楼主辛苦了
发表于 2011-6-27 22:23:12 | 显示全部楼层
不错~~正在学习中...
发表于 2011-6-28 14:39:39 | 显示全部楼层
不错,用CI开发一段时间后,相信很多人都会尝试封装类似楼主这样的代码。包括,controller,helper,library,用CI如果自己开发时间久了的话,自己封装后会比CI原始的更加方便。
发表于 2011-7-4 09:12:37 | 显示全部楼层
支持一下 来看看 呵呵
发表于 2012-5-20 13:01:03 | 显示全部楼层
支持,可以拿来借鉴
发表于 2012-7-11 17:51:21 | 显示全部楼层
优化无处不在!哈哈
发表于 2012-7-11 17:51:33 | 显示全部楼层
很给力
发表于 2012-9-17 16:59:12 | 显示全部楼层
现在已经有了ORM,可以解决这个,不过感觉ORM也是蛮笨重的
发表于 2012-9-18 16:17:31 | 显示全部楼层
个人觉得楼主的思路就有点问题,models是业务相关,像crud这类业务无关性的应该以库的形式存在更合理一些吧,看了你写的代码,用起来好不方便的说,先加载,然后再调用一个方法传参数进去
PHP复制代码
 
$this->CI->load->model('crud');
$this->CI->crud->Crud($this->table,$this->key);
复制代码


如果以库的形式存在,就可以这么写了:
PHP复制代码
 
$this->load->library('crud', array('table ' => $table, 'key' => $key));
 
复制代码


刚接触CI,一点小意见

本版积分规则