Как вы реорганизуете слишком долгую функцию контроллера Codeigniter? - PullRequest
2 голосов
/ 10 февраля 2009

У меня есть функция в контроллере, которая выросла дольше, чем мне хотелось бы, и я хотел бы реорганизовать ее, чтобы вызвать несколько отдельных функций, чтобы упростить управление. Как лучше организовать длинную функцию в контроллере 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);       
}

Ответы [ 8 ]

5 голосов
/ 10 февраля 2009

Вы используете модели? Воспламенитель кода не обеспечивает этого, но использование моделей в дополнение к контроллерам и представлениям - хороший способ иметь более короткую функцию контроллера. В качестве альтернативы вы можете поместить некоторые функции в свой собственный помощник, а затем импортировать его.

И если вы хотите установить некоторые значения по умолчанию для всего конструктора, вы можете использовать конструктор класса. Это изложено здесь:

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

4 голосов
/ 11 февраля 2009

Глядя на свой код, вы используете один метод для нескольких действий. Я бы сделал каждое действие по-своему. Общие ресурсы могут быть членами класса и загружаться в конструктор.

Таким образом, вместо URL-адреса, подобного «your_controller / Categories / add», вы можете изменить свой URL-адрес на «category_controller / add» и иметь метод для каждого действия. Если вы не хотите менять свои URL-адреса, используйте маршрут:

$route['your_controller/categories/(.*)'] = 'your_controller/$1';
2 голосов
/ 11 февраля 2009

Если вы хотите сохранить свою логику в том же контроллере, вы можете имитировать закрытый метод, поместив подчеркивание перед именем функции, например: _myMethod (). Как говорит ссылка , подчеркивание перед именем функции не позволяет CI вызывать ее из URL. Вы можете, например, создать методы _delete (), _preview (), _order () и т. Д. В контроллере Categories. Однако, если вы используете ту же логику для удаления, предварительного просмотра, заказа и т. Д. Других вещей, возможно, вам следует переместить эти методы в модель или помощника.

2 голосов
/ 10 февраля 2009

Служебный уровень поможет.

1 голос
/ 14 апреля 2010

Попробуйте заглянуть в функцию _remap () контроллера в codeigniter.

Используя его, вы можете сохранить общий код в функции _remap, а затем вызывать любую другую функцию из _remap для удаления, обновления и т. Д. (На основе uri_segment (3)).

1 голос
/ 06 марта 2009

Лично я думаю, что вы слишком много делаете с одним контроллером. Первое, что я хотел бы сделать, - это разделить ваши функции CRUD (Create Read Update Delete) как отдельные методы. Например, ваш пример для работы с «категориями», почему бы не иметь отдельный контроллер «категорий»?

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 позволяет легко перенести все ваши правила проверки в отдельный файл конфигурации.

0 голосов
/ 11 августа 2011

Вы можете поместить общие функции в библиотеку и вызывать ее.

0 голосов
/ 10 февраля 2009

Какую версию PHP вы используете? PHP 5 имеет поддержку реального ОО, поэтому вы можете объявить приватную функцию, которая будет интерпретироваться интерпретатором так:

private function foo(){
...
}

Если вы хотите, чтобы классы, расширяющие ваш класс (дочерние классы), имели доступ к функции, замените private на protected.

Я никогда не использовал CodeIgnniter, поэтому боюсь, что не смогу помочь вам с вашей конкретной проблемной областью. Тем не менее, рефакторинг функции, которая становится длинной, является очень распространенной проблемой с общими решениями. Мартин Фаулер - умный парень, который написал несколько книг на эту тему, которые пользуются уважением, поэтому вы можете посмотреть, сможете ли вы найти одну из его книг . В Интернете также есть учебники, которые помогут вам начать рефакторинг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...