2

我的控制器中有一个函数比我希望的要长,我想重构它以调用一些离散函数以使其更易于管理。如何在 Codeigniter 控制器中更好地组织长函数?

我试过的:

我知道您可以通过使用前导下划线 (_myfunc) 命名它们来在控制器中创建私有函数,但是函数中的变量超出了调用控制器函数的范围。所以你必须从函数中返回所有需要的数据,这很麻烦。

这是管理复杂控制器功能的最佳选择吗?有没有更简单的方法,变量可以像标准类成员变量一样对控制器类都是全局的?

建议?提前致谢!

编辑:有人请求了代码,所以我在下面添加了巨型控制器的代码。改进的一个机会是将 switch 语句中的逻辑移动到单独的函数(删除、预览、排序等)。但我正试图在那之后决定下一步。将大型验证设置代码移到它自己的函数中确实会减轻一些负担,但是我应该将它移到哪里呢?

    function categories() {
    $this->load->library('upload');
    $this->load->model('categories_m');
    $this->load->model('products_m');
    $this->load->model('pages_m');
    $this->load->model('backoffice/backofficecategories_m');
    $data['body'] = $this->load->view('backoffice/categories/navigation_v', '', TRUE);
    $data['cat_tree'] = $this->categories_m->getCategoryTree();
    $data['page_list'] = $this->pages_m->getPageList();
    $data['category_dropdown'] = $this->load->view('backoffice/categories/category_dropdown_v',$data,TRUE);

    switch ($this->uri->segment(3)) { //display views based on parameter in URL.
    case 'delete':          
        $categoryTreeID = $this->sitewide_m->checkURLParam($this->uri->segment(4),'CategoryTree'); //if parameter is in URL, show 404 if invalid parameter is passed. Otherwise, set variable known to be safe.
        if (isset($_POST['delete'])) {
            $this->backofficecategories_m->deleteCategory($categoryTreeID);
            $data['body'] .= '<span class="error">Category Deleted.</span>';
        } else {
            $data['cat_details'] = $this->categories_m->getCategoryDetails('',$categoryTreeID);
            $data['parent_category'] = $this->categories_m->getParentCategory($categoryTreeID);
            $data['products_to_reassign'] = $this->products_m->getProductsInCategory('',$categoryTreeID);   
            $data['body'] .= $this->load->view('backoffice/categories/delete_v',$data,TRUE);  //pull fresh category tree data since tree was just updated.
        }
        break;
    case 'preview':
        if ($this->uri->segment(4)) $data['categoryTreeID'] = $this->sitewide_m->checkURLParam($this->uri->segment(4),'CategoryTree'); //if parameter is in URL, show 404 if invalid parameter is passed. Otherwise, set variable known to be safe.
        $data['cat_details'] = $this->categories_m->getCategoryDetails(NULL,$data['categoryTreeID']); //get category ID being edited from the URL and store it. Returns false if category ID isn't found.
        foreach ($data['cat_details']->result() as $detail) {
            $data['categoryName'] = $detail->Name;
            $data['categoryID'] = $detail->ID;
        }
        $data['body'] .= $this->load->view('backoffice/categories/preview_v', $data, TRUE);
        break;

    ...cases continue...
    default:
        $this->load->library('table');
        $data['body'] .= $this->load->view('backoffice/categories/categories_v', $data, TRUE);
        break;
    }
    $this->load->view('backoffice/template_v',$data);       
}
4

8 回答 8

5

你在使用模型吗?Code igniter 不会强制执行此操作,但除了控制器和视图之外,使用模型是获得更短控制器功能的好方法。或者,您可以将一些函数放在您自己的助手中,然后导入它。

而如果你想为整个构造函数设置一些默认值,你可以使用类构造函数。这在这里概述:

http://codeigniter.com/user_guide/general/controllers.html#constructors

于 2009-02-10T14:22:51.000 回答
4

查看您的代码,您正在使用一种方法执行多个操作。我会让每个动作都有自己的方法。公共资源可以是类成员并加载到构造函数中。

因此,您可以将您的 url 更改为“category_controller/add”,而不是像“your_controller/categories/add”这样的 url,并为每个操作设置一个方法。如果您不想更改网址,请使用路线:

$route['your_controller/categories/(.*)'] = 'your_controller/$1';
于 2009-02-11T08:11:35.267 回答
2

服务层会有所帮助。

于 2009-02-10T15:01:33.980 回答
2

如果你想将你的逻辑保持在同一个控制器中,你可以通过在函数名前加下划线来模拟私有方法,例如:_myMethod()。就像链接说的那样,函数名称前的下划线会阻止 CI 从 URL 调用它。例如,您可以在 Categories 控制器中创建 _delete()、_preview()、_order() 等方法。但是,如果您使用相同的逻辑来删除、预览、订购等其他内容,也许您应该将这些方法移动到模型或助手中。

于 2009-02-11T07:43:50.653 回答
1

就个人而言,我认为您使用单个控制器方法做的太多了。我要做的第一件事就是将您的 CRUD(创建读取更新删除)函数分离为单独的方法。例如,您的示例是使用“类别”,为什么不使用单独的“类别”控制器?

class Categories extends Controller
{
  function __construct()
  {
    parent::Controller();
  }

  function index() 
  {
    //display logic/code here
  }

  function edit()
  {
    //get the category to update from the post or url for editing
    //do the editing, etc
  }

  function delete()
  {
    //delete the category
  }

  function add()
  {
    //create the new category
  }
}

您的 URL 将引用类别控制器:

http://www.example.com/categories/edit http://www.example.com/categories/delete 等。

我建议的第二件事是升级到 CodeIgniter 1.7.1 - 更新的 form_validation 库可以轻松地将所有验证规则移动到单独的配置文件中。

于 2009-03-06T13:57:24.903 回答
1

尝试在 codeigniter 中查看控制器的 _remap() 函数。

使用它,您可以将通用代码保留在 _remap 函数中,然后从 _remap 中调用任何其他函数以进行删除、更新等(基于 uri_segment(3))。

于 2010-04-14T10:14:34.793 回答
0

您使用的是什么版本的 PHP? PHP 5支持真正的 OO,因此您可以声明私有函数,该函数将被解释器视为:

private function foo(){
...
}

如果您希望扩展您的类(子类)的类能够访问该函数,请替换privateprotected.

我从未使用过 CodeIgnniter,所以恐怕我无法帮助您解决特定的问题域。但是,重构一个增长为 long 的函数是一个非常常见的问题,有通用的解决方案。马丁·福勒 (Martin Fowler) 是个聪明人,他写了一些关于该主题的书,广受好评,因此您可以看看是否能找到他的书。还有在线教程可以帮助您开始重构。

于 2009-02-10T14:12:28.480 回答
0

您可以将常用函数放入库中并调用它。

于 2011-08-11T06:37:14.450 回答