我的控制器中有一个比我更喜欢长的功能,我想重构它来调用一些离散函数,以便更容易管理。如何在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);
}
答案 0 :(得分:5)
你在使用模特吗?代码点火器不会强制执行此操作,但除了控制器和视图之外还使用模型是控制器功能更短的好方法。或者,您可以将一些函数放在自己的帮助器中,然后导入它。
如果要为整个构造函数设置一些默认值,可以使用类构造函数。这在此概述:
http://codeigniter.com/user_guide/general/controllers.html#constructors
答案 1 :(得分:4)
查看代码,您将使用一种方法进行多项操作。我会让每个动作都有自己的方法。公共资源可以是类成员并在构造函数中加载。
因此,您可以将网址更改为“category_controller / add”,而不是像“your_controller / categories / add”这样的网址,并为每个操作设置方法。如果您不想更改网址,请使用路线:
$route['your_controller/categories/(.*)'] = 'your_controller/$1';
答案 2 :(得分:2)
服务层会有所帮助。
答案 3 :(得分:2)
如果要将逻辑保留在同一个控制器中,可以通过在函数名前放置下划线来模拟私有方法,例如:_myMethod()。与link所说的一样,函数名称前面的下划线阻止CI从URL调用它。 例如,您可以在Categories控制器中创建_delete(),_ preview(),_ order()等方法。但是,如果你使用相同的逻辑来删除,预览,订购等其他东西,也许你应该在模型或助手中移动这些方法。
答案 4 :(得分: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
}
}
您的网址会引用类别控制器:
http://www.example.com/categories/edit http://www.example.com/categories/delete 等
我建议的第二件事是升级到CodeIgniter 1.7.1 - 更新的form_validation库可以轻松地将所有验证规则移动到单独的配置文件中。
答案 5 :(得分:1)
尝试在codeigniter中查看控制器的_remap()函数。
使用它可以将公共代码保存在_remap函数中,然后调用_remap中的任何其他函数进行删除,更新等(基于uri_segment(3))。
答案 6 :(得分:0)
您使用的是哪个版本的PHP? PHP 5支持真正的OO,因此您可以声明解释器将对其进行处理的私有函数:
private function foo(){
...
}
如果您希望扩展您的类(子类)的类可以访问该函数,请将private
替换为protected.
我从未使用过CodeIgnniter,所以我担心我无法帮助您处理特定的问题域。但是,通过常见的解决方案,重构一个长得很长的函数是一个非常普遍的问题。 Martin Fowler是一个聪明的人,他写了一些关于这个主题的书籍,这些书籍备受好评,所以你可能会看到你是否可以找到his books中的一个。还有在线教程可以帮助您开始重构。
答案 7 :(得分:0)
您可以将常用功能放在库中并调用它。