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

[控制器] CI控制器相似业务重复问题的疑惑

[复制链接]
发表于 2013-3-3 11:21:30 | 显示全部楼层 |阅读模式
背景:建立了一个类似新闻管理系统的后台,但是分几个栏目,包含:新闻管理,文章管理(与新闻栏目不一样),人物管理……
功能:每个栏目的功能都比较相似,都含有一个添加信息,修改信息,管理列表(在此列表中有删除按键,可删除信息)的功能
问题:现在的问题是这样的,对每一个模块都定义了一个控制器,news,article,person……,这些控制器下都有add/edit(显示添加/编辑信息的页面),add_action/edit_action处理添加/编辑页面提交的表单信息),delete_action(删除信息),manage(显示信息列表)这几个基本的方法。
最后的疑惑:做了这三个模块后,发现他们都是如此的相似,当要写person这个模块时,直接就是把news的复制一份,然后修改一下变量,做一下简单的改变即可。有没有什么好的办法把这种相似的业务处理抽象出来?单独拿出来?

// 以下是文章栏目的控制器部分方法
class Article extends MY_Controller
{
    function __construct()
    {
        parent::__construct();
        
        // 后台登录验证
        $this->check_login();
        $this->load->model('article_m');
        
        // 加载文章的语言包
        $this->load->language('article');
        
        $this->validate_data = array(
                array('field' => 'title', 'label' => 'lang:article_title', 'rules' => 'trim|required|max_length[50]|xss_clean'),
                array('field' => 'editor', 'label' => 'lang:article_editor', 'rules' => 'trim|required|max_length[20]'),
                array('field' => 'author', 'label' => 'lang:article_author', 'rules' => 'trim|required|max_length[20]'),
                array('field' => 'source', 'label' => 'lang:article_source', 'rules' => 'trim|required|max_length[15]'),
                array('field' => 'path', 'label' => 'lang:article_attachment', 'rules' => 'trim|max_length[200]'),
                array('field' => 'content', 'label' => 'lang:article_content', 'rules' => 'trim|required'),
                array('field' => 'keyword', 'label' => 'lang:com_keyword', 'rules' => 'trim|max_length[30]'),
                array('field' => 'classid', 'label' => 'lang:com_column_name', 'rules' => 'trim|required|is_natural_no_zero'),
                array('field' => 'releasename', 'label' => 'lang:com_releasename', 'rules' => 'trim|required|max_length[20]'),
                array('field' => 'remark', 'label' => 'lang:com_remark', 'rules' => 'trim|max_length[20]'),
                );
    }
   
    function index($page = '')
    {
        $this->manage($page);
    }
   
    /**
     * 显示文章列表
     * @param int $page 显示的页码
     */
    function manage($page = '')
    {
        // 获取要显示的页数
        $page           = empty($page) ? 1 : abs(intval($page));
   
        // 组织分页信息
        $config['base_url']        = base_url('article/manage');
        $config['total_rows']    = $this->article_m->get_article_count();
        
        $page_data = $this->get_page($config);
        $data['page']     = $page_data['page'];
        $order             = 'istop desc,isrecommend desc,id desc';
   
        // 查询文章
        $article      = $this->article_m->show_article($page_data['limit'], $order);
   
        // 文章信息列表数组
        $i = 1;
        foreach ($article as $key => $row)
        {
            $article[$key]['ordernum']     = ($page - 1) * $page_data['per_page'] + $i;
            $article[$key]['createtime']    = date(config_item('date_format'),$row['createtime']);
            $article[$key]['updatetime']    = date(config_item('date_format'),$row['updatetime']);
            $article[$key]['isactive']     = $row['isactive'] == 0 ? $this->lang->line('com_sign_inactive') : $this->lang->line('com_sign_active');
            $article[$key]['isverify']     = $row['isverify'] == 0 ? $this->lang->line('com_sign_not_verify') : $this->lang->line('com_sign_verify');
            $article[$key]['isrecommend'] = $row['isrecommend'] == 1 ? $this->lang->line('com_sign_recommend') : '';
            $article[$key]['istop']         = $row['istop'] == 1 ? $this->lang->line('com_sign_top') : '';
            $i++;
        }
   
        $data['header']         = $this->header;
        $data['title']            = $this->lang->line('article_title_list');
        $data['page_label']        = $this->lang->line('article_page_label');
        $data['nav_label']         = $this->lang->line('com_navigate_label');
        $data['article']     = $article;
        $this->load->view('article_list',$data);
    }
   
    /**
     * ajax删除文章,返回json结果
     */
    function delete_action()
    {
        $result = array('error' => FALSE, 'message' => $this->lang->line('msg_operation_success'));
   
        // 对表单数据做判断
        $validate = $this->validation(array('field' => 'id[]', 'label' => 'lang:article_id', 'rules' => 'trim|required|is_natural|xss_clean'));
        if (TRUE !== $validate)
        {
            $result['error']     = TRUE;
            $result['message']     = $validate;
            echo json_encode($result);
            return ;
        }
   
        // 获取文章ID值,并放入数组
        $id = $this->input->post('id');
        if (TRUE === $this->article_m->delete_article_by_id($id))
        {
            echo json_encode($result);
            return ;
        }
        else
        {
            $result['error']     = TRUE;
            $result['message']     = $this->lang->line('msg_operation_failed');
            echo json_encode($result);
            return ;
        }
    }
   
    /**
     * 显示文章添加页面
     */
    function add()
    {
        $data['header']         = $this->header;// 公用头部
        $data['title']            = $this->lang->line('article_title_add');
        $data['page_label']        = $this->lang->line('article_page_label'); // 页面标签,即栏目名称
        $data['nav_label']         = $this->lang->line('com_navigate_label'); // 导航标签
        $data['loginname']         = $this->loginname;
        $data['class']             = $this->get_column_as_array(); // 栏目分类
        $this->load->view('article_add', $data);
    }


// 以下是新闻栏目的控制器

class News extends MY_Controller
{
    function __construct()
    {
        parent::__construct();
        
        // 后台登录验证
        $this->check_login();
        $this->load->model('news_m');

        // 加载文章的语言包
        $this->load->language('news');
        
        $this->validate_data = array(
                array('field' => 'title', 'label' => 'lang:news_title', 'rules' => 'trim|required|max_length[50]|xss_clean'),
                array('field' => 'author', 'label' => 'lang:news_author', 'rules' => 'trim|required|max_length[20]'),
                array('field' => 'keyword', 'label' => 'lang:com_keyword', 'rules' => 'trim|max_length[30]'),
                array('field' => 'classid', 'label' => 'lang:com_column_name', 'rules' => 'trim|required|is_natural_no_zero'),
                array('field' => 'source', 'label' => 'lang:news_source', 'rules' => 'trim|required|max_length[20]'),
                array('field' => 'releasename', 'label' => 'lang:com_releasename', 'rules' => 'trim|required|max_length[20]'),
                array('field' => 'picturepath', 'label' => 'lang:news_pictures', 'rules' => 'trim|max_length[200]'),
                array('field' => 'content', 'label' => 'lang:news_source', 'rules' => 'trim|required'),
                array('field' => 'remark', 'label' => 'lang:com_remark', 'rules' => 'trim|max_length[20]'),
                );
    }
   
    function index($page = '')
    {
        $this->manage($page);
    }
   
    /**
     * 新闻列表显示
     * @param int $page 当前显示页码
     */
    function manage($page = '')
    {
        // 获取要显示的页数
        $page           = empty($page) ? 1 : abs(intval($page));
        
        // 组织分页信息
        $config['base_url']        = base_url('news/manage');
        $config['total_rows']    = $this->news_m->get_news_count();
        
        $page_data = $this->get_page($config);
        $data['page']     = $page_data['page'];
        $order             = 'istop desc,isrecommend desc,id desc';

        // 查询新闻
        $news      = $this->news_m->show_news($page_data['limit'], $order);
        
        // 新闻信息列表数组
        $i = 1;
        foreach ($news as $key => $row)
        {
            $news[$key]['ordernum']     = ($page - 1) * $page_data['per_page'] + $i;
            $news[$key]['createtime']    =date(config_item('date_format'),$row['createtime']);
            $news[$key]['updatetime']    =date(config_item('date_format'),$row['updatetime']);
            $news[$key]['isactive']     = $row['isactive'] == 0 ? $this->lang->line('com_sign_inactive') : $this->lang->line('com_sign_active');
            $news[$key]['isverify']     = $row['isverify'] == 0 ? $this->lang->line('com_sign_not_verify') : $this->lang->line('com_sign_verify');
            $news[$key]['isrecommend'] = $row['isrecommend'] == 1 ? $this->lang->line('com_sign_recommend') : '';
            $news[$key]['istop']         = $row['istop'] == 1 ? $this->lang->line('com_sign_top') : '';
            $news[$key]['ispic']         = $row['ispic'] == 1 ? $this->lang->line('com_sign_picture') : '';
            $i++;
        }
        
        $data['header']         = $this->header;
        $data['title']            = $this->lang->line('news_title_list');
        $data['page_label']        = $this->lang->line('news_page_label');
        $data['nav_label']         = $this->lang->line('com_navigate_label');
        $data['news']             = $news;
        $this->load->view('news_list',$data);
    }
   
    /**
     * 显示添加新闻页面
     */
    function add()
    {
        $data['header']         = $this->header;
        $data['title']            = $this->lang->line('news_title_add');
        $data['page_label']        = $this->lang->line('news_page_label');
        $data['nav_label']         = $this->lang->line('com_navigate_label');
        $data['loginname']         = $this->loginname;
        $data['class']             = $this->get_column_as_array();
        $this->load->view('news_add', $data);
    }

    /**
     * AJAX方式删除新闻,如果是图片新闻也删除其所属的图片,返回json信息
     */
    function delete_action()
    {
        $result = array('error' => FALSE, 'message' => $this->lang->line('msg_operation_success'));

        // 对表单数据做判断
        $validate = $this->validation(array('field' => 'id[]', 'label' => 'lang:news_id', 'rules' => 'trim|required|is_natural|xss_clean'));
        if (TRUE !== $validate)
        {
            $result['error']     = TRUE;
            $result['message']     = $validate;
            echo json_encode($result);
            return ;
        }
        
        // 获取文章ID值,并放入数组
        $news_id['id'] = $this->input->post('id');
        if (TRUE === $this->news_m->delete_news($news_id))
        {
            echo json_encode($result);
            return ;
        }
        else
        {
            $result['error']     = TRUE;
            $result['message']     = $this->lang->line('msg_operation_failed');
            echo json_encode($result);
            return ;
        }
    }



发表于 2013-3-5 13:15:18 | 显示全部楼层
常规的方法就是继承。
不过如果是连视图都很像,还需要在结合其他方案。
发表于 2013-3-9 14:47:43 | 显示全部楼层
楼主你这个我提个建议……

我们写.NET JAVA的时候。都是这样的一个过程。 VIEW - CONTROLLER - SERVICES - MODEL.你的中间少了一层SERVICES,

我的做法是把SERVICES放在libraries里面
例如:

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Commentservice {

        var $instance;

        function __construct(){
                $this->instance = & get_instance();
        }

        public function addcomment($memberid, $shopid, $foodid, $content) {
                $this->instance->load->model('comment_model');
                $this->instance->comment_model->memberid = $memberid;
                $this->instance->comment_model->shopid = $shopid;
                $this->instance->comment_model->foodid = $foodid;
                $this->instance->comment_model->content = $content;
                $this->instance->comment_model->rankid = 0;
                $this->instance->comment_model->memberimageid = 0;
                $this->instance->comment_model->addtime = time();
                $this->instance->comment_model->insert();
        }

        public function getlist($shopid, $foodid, $cols = '*', $pn = 0, $rn = 20) {
                $this->instance->load->model('comment_model');
                return $this->instance->comment_model->getlist($shopid, $foodid, $pn, $rn, $cols);
        }
}

而调用的时候。

$this->load->library('commentservice');
$this->commentservice->getlist($shopid, $foodid, $cols, 0, $commrn);

另外你的AJAX消息模型可以抽象出来。做成这样的一个类似的

class Result_model extends CI_Model {
        var $error = "0";
        var $message = "";
        var $data = "";

        function tojson() {
                return json_encode($this);
        }
}
发表于 2013-3-10 08:55:23 | 显示全部楼层
qiutao520 发表于 2013-3-9 14:47
楼主你这个我提个建议……

我们写.NET JAVA的时候。都是这样的一个过程。 VIEW - CONTROLLER - SERVICES - ...

不错
 楼主| 发表于 2013-3-12 14:25:51 | 显示全部楼层
qiutao520 发表于 2013-3-9 14:47
楼主你这个我提个建议……

我们写.NET JAVA的时候。都是这样的一个过程。 VIEW - CONTROLLER - SERVICES - ...

不错,不错,说的有道理,ajax那个确实可以抽象出来。
没做过java的,所以services这一层不太理解,有空好好研究研究。
非常感谢!
发表于 2013-5-26 22:14:04 | 显示全部楼层
{:soso_e179:} 有实战意义
发表于 2013-6-11 15:59:09 | 显示全部楼层
发表于 2013-8-26 14:35:21 | 显示全部楼层
     是可以这样的。java中非常重视分层来实现。services调用model的基本方法,controller调用service来实现。
ci 在设计中,没有把服务层考虑进来,而把主要的业务逻辑处理集中在controller。这样就是lz在使用中带来的困惑。
    不过刚刚“我的做法是把SERVICES放在libraries里面”,我不怎么赞成。毕竟,ci在设计中,把lib库作为扩展库或者第三方库。这样使用对后期使用会产生困惑。建议扩展一个新的文件目录,如service,调用方法:$this->load->service("XXX_service");

本版积分规则