【问题标题】:Codeigniter: Is calling a model from a helpler a bad idea?Codeigniter:从助手那里调用模型是个坏主意吗?
【发布时间】:2012-07-04 13:57:43
【问题描述】:

我的页面上有一个菜单,每个页面都加载了该菜单。菜单数据通过模型从数据库中获取。我的第一个想法是从控制器调用模型,然后将其传递给每个页面上的视图。但这会导致“混乱”的代码,如果我忘记将菜单数据传递给视图,则会导致丑陋的错误(或者只是没有菜单项)。

所以我想出了通过助手获取菜单项的解决方案,然后只需从视图中调用助手函数。这更有意义,因为我只将代码放在一个地方(菜单视图)。

我的视图是这样设置的:控制器调用“页面”视图,然后加载页眉视图、菜单视图、适当的内容视图,最后是页脚视图。助手只能从一个地方调用,即菜单视图。

通常你甚至不能从助手加载模型,但我使用 $i = get_instance();然后通过该实例加载模型; $i->load->model().

我觉得这不是要走的路,但有更好的方法吗?

编辑:换一种说法:

我想要: 查看 -> 获取数据 -> 显示

不是: 控制器 -> 获取数据 -> 传递给视图 -> 显示

我只是不确定这样做是否“可以”,因为它完全无视 MVC 模型。

【问题讨论】:

  • 我认为你应该考虑扩展你的控制器。这样你就可以在基础构造函数中加载菜单数据,它总是可用的,你不会忘记什么

标签: codeigniter dynamic view model helper


【解决方案1】:

所以我找到了一个剪切-粘贴的快速示例(在这种情况下,我有一个名为 login 的自动加载模型,但您当然可以手动执行)

在文件core\MY_Controller.php

class Admin_Controller extends CI_Controller 
{
    protected $login_ok;

    public function __construct() 
    {
        parent::__construct();

        /* --- Check if user is logged in --- */
        $this->config->load('adldap', TRUE);
        $data->login_ok = $this->login->check_login(TRUE);

        $this->load->vars($data);
    }
}

如果你用这个扩展你的控制器。您的视图中将显示$login_ok

这样您可以确保始终准备好所需的变量,您只需在一个地方编写代码

【讨论】:

  • 听起来不错!如果我使用它,我是否必须在我的控制器上扩展 Admin_Controller 而不是 CI_Controller?另外,我假设您的意思是application/core/My_Controller.php 对吗?
  • 嗯,这就是我要说的。复制粘贴是错误的,因为 Admin_Controller 应该被称为 MY_Controller,反之亦然。
  • @robert:只要文件名为MY_Controller.php,您可以随意命名。我在MY_Controller.php 有三个不同的类,即class Admin_Controllerclass User_Controllerclass Public_Controller
  • @qwerty:你说得对,就是文件,你会扩展你的新控制器而不是 CI_Controller
  • @danneth 你是对的。不知何故,我确信名称需要像控制器或模型中那样对应,但它们没有。 +1 4U :)
【解决方案2】:

我认为解决方案比你想象的要容易。

如果你现在在你的助手中做这样的事情:

create_menu()
{
    $menu_items = $this->db->query('')->result();
    // creating the menu here
}

您可以只更改函数以接受这样的输入并仍然遵循 MVC 模式。

助手

create_menu($input)
{
    $menu_items = $input;
    // creating the menu here
}

型号:

get_menu_data()
{
   $menu_items = $this->db->query('')->result();
}

这有意义吗?

编辑:

这是我在其中一个项目中的做法:

我扩展了我的标准控制器。在该控制器的构造函数中,我调用了模型并获取了数据:

$this->menu_items = $this->some_model->get_menu_items();

视图内nav.php

if(!empty($this->subnav_item))
{
   // Generate menu
}

这样MVC是完整的,但我不必担心传递变量。

编辑 2

如何扩展标准控制器:

application/core中创建文件MY_Controller.php

class MY_Controller extends CI_Controller {

    public $menu_items = '';

    function __construct()
    {
        parent::__construct();
        $this->load->model('some_model_that_you_always_use');
        $this->load->library('some_library_that_you_always_use');
        $this->menu_items = $this->some_model->get_menu_items();
    }

}

当你创建一个新的控制器时,你扩展 MY_Controller 而不是 CI_Controller 像这样:

 class Something extends MY_Controller {

 }

【讨论】:

  • 我明白你的意思,但我认为你不明白这个问题。如果我要使用您的示例,我仍然必须从控制器中的模型中获取菜单数据,然后将其从视图传递给助手。我不想将菜单数据从控制器传递到视图,我想从视图(或在这种情况下为助手)获取菜单数据以避免必须将菜单数据传递到每个视图页。我不确定这是否有意义,很难解释。
  • 我更新了我的问题,请查看我的编辑以获得更简单的解释。 :)
  • 所以如果我理解正确,你在每个控制器类的构造函数中都有$this->menu_items = $this->some_model->get_menu_items();?我想这会更容易,因为我只需要为每个控制器加载一次。但是,如果我有多个控制器怎么办?然后我仍然需要在不同的控制器中加载它几次。不过比我原来的想法好多了,如果没有更好的方法我一定会用它!
  • 不,不是在每个控制器中,而是在新的“默认控制器”中。数据确实每次都会加载,但您只需加载一次。看到不同?我用一个小的“操作方法”编辑了我的答案
  • 这正是我所需要的。也感谢您的解释。我读过它,但之前并没有完全弄清楚。 Danneth 发布了相同的答案,但你打败了他,所以我会将你的答案标记为已接受。
【解决方案3】:

请记住,MVC 模式并没有禁止视图直接联系模型。这只是 CodeIgniter 中常见的约定。

我建议在这种情况下,您的菜单视图应该直接从菜单模型加载菜单数据。

【讨论】:

    猜你喜欢
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 2011-05-17
    相关资源
    最近更新 更多