2

コントローラーの関数が思ったよりも長くなりました。管理しやすくするために、いくつかの個別の関数を呼び出すようにリファクタリングしたいと考えています。Codeigniter コントローラーで長い関数をより適切に整理するにはどうすればよいですか?

私が試したこと:

先頭にアンダースコア (_myfunc) を付けて名前を付けることで、コントローラー内にプライベート関数を作成できることはわかっていますが、関数内の変数は呼び出し元のコントローラー関数の範囲外です。そのため、面倒な関数から必要なすべてのデータを返す必要があります。

これは、複雑なコントローラー機能を管理するための最良のオプションですか? 標準クラスのメンバー変数のように、変数がすべてコントローラ クラスに対してグローバルになる簡単な方法はありますか?

提案?前もって感謝します!

編集:誰かがコードを要求したので、以下に巨大なコントローラーのコードを追加しました。改善の 1 つの機会は、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

モデルを使用していますか?コード イグナイターはこれを強制しませんが、コントローラーとビューに加えてモデルを使用することは、コントローラー関数を短くする良い方法です。または、関数の一部を独自のヘルパーに配置してからインポートすることもできます。

また、コンストラクター全体にいくつかのデフォルト値を設定する場合は、クラス コンストラクターを使用できます。これについては、次のとおりです。

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

于 2009-02-10T14:22:51.000 に答える
4

コードを見ると、複数のアクションに対して 1 つのメソッドを使用しています。各アクションを独自の方法にします。共通リソースはクラス メンバーであり、コンストラクターに読み込まれます。

したがって、「your_controller/categories/add」のような URL の代わりに、URL を「category_controller/add」に変更して、各アクションのメソッドを持つことができます。URL を変更したくない場合は、次のルートを使用します。

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

ロジックを同じコントローラーに保持したい場合は、_myMethod() のように、関数名の前にアンダースコアを付けてプライベート メソッドをシミュレートできます。リンクが示すように、関数名の前にアンダースコアがあると、CI が URL から呼び出すことができなくなります。たとえば、Categories コントローラーで _delete()、_preview()、_order() などのメソッドを作成できます。ただし、同じロジックを使用して他のものを削除、プレビュー、注文などする場合は、これらのメソッドをモデルまたはヘルパーに移動する必要があります。

于 2009-02-11T07:43:50.653 に答える
2

サービス層が役立ちます。

于 2009-02-10T15:01:33.980 に答える
1

codeigniterでコントローラーの_remap()関数を調べてみてください。

これを使用すると、共通コードを_remap関数に保持し、_remap内から他の関数​​を呼び出して、削除、更新などを行うことができます(uri_segment(3)に基づく)。

于 2010-04-14T10:14:34.793 に答える
1

個人的には、単一のコントローラー メソッドでやりすぎていると思います。私が最初に行うことの 1 つは、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 など

私が提案する 2 番目のことは、CodeIgniter 1.7.1 にアップグレードすることです。更新された form_validation ライブラリにより、すべての検証ルールを別の構成ファイルに簡単に移動できます。

于 2009-03-06T13:57:24.903 に答える
0

どのバージョンの PHP を使用していますか? PHP 5は実際の OO をサポートしているため、インタープリターによってそのように扱われるプライベート関数を宣言できます。

private function foo(){
...
}

クラスを拡張するクラス (子クラス) が関数にアクセスできるようにする場合は、次のように置き換えますprivateprotected.

私は CodeIgniter を使用したことがないので、あなたの特定の問題ドメインについてお手伝いすることはできません. ただし、長くなった関数のリファクタリングは、一般的な解決策を伴う非常に一般的な問題です。Martin Fowler は頭の良い人で、このトピックに関する本を何冊か書いており、評判が良いので、彼の本を見つけることができるかどうかわかるかもしれません。リファクタリングを開始するためのオンライン チュートリアルもあります。

于 2009-02-10T14:12:28.480 に答える
0

共通関数をライブラリに入れて呼び出すことができます。

于 2011-08-11T06:37:14.450 に答える