访问其他模型中的CodeIgniter模型

时间:2009-05-16 15:22:13

标签: php codeigniter

过去,在CodeIgniter模型中,您无法访问其他模型。

$this->load->model('bar');
$this->bar->something();

这仍然有效,还是他们改变了?

8 个答案:

答案 0 :(得分:69)

对于一个简单的问题,这些是非常长的答案。

简答:现在完全支持了。如果您愿意,可以交叉负载!

答案 1 :(得分:39)

我强烈反对“模型”只应使用简单的CRUD操作封装数据库表的概念。如维基百科文章中所述:

http://en.wikipedia.org/wiki/Model-view-controller#As_a_design_pattern

...应用程序层的目的不仅仅是作为单个数据库表抽象。想想“控制器”这个词的含义 - 它应该更像是一个导演,而不是整个应用程序本身。 “模型”商业逻辑的场所。事实上,大多数大型应用程序在数据库本身中都有很多业务逻辑(以触发器,存储过程,外键等形式)。

我认为对“模型”的误解部分是由于“MVC”的相同(过度)炒作造成的,而没有对概念本身进行过多的理解。有点像空的“AJAX”,甚至更简单,“Web 2.0”。无论好坏,大量的脚本小子都跳上了MVC旅行车,因为简单的howtos和示例场景所做的不仅仅是告诉你将数据库代码放在“模型”中,因此滥用该层只有数据库抽象已经司空见惯。现在,您阅读了互联网上的帖子,称其为“无法”,“脏”,“黑客”将任何业务逻辑放入模型中。那是错的。误导。

简单的例子是考虑外键:即使你只想让你的“模型”成为数据库模型,如果你想要“纯粹”,“正确”或者有什么你,你真的应该在其中强制执行参照完整性。多亏了MySQL多年来缺乏真正的外键支持,Web应用程序的成长使得任何人都不必担心引用完整性。适合脚本小子生活方式我想。无论如何,即使这个简化的模型视图能够维护外键的有效性,模型也必须与其他人一起工作(或者,特别是如果像CodeIgniter这样的框架不允许你这样做,你必须向其他人写查询表,有时在其他地方重复查询 - 这是不好的风格。)

因此,我认为这是CodeIgniter的缺点。我知道这可能不是一个简单的解决办法,但这肯定是一个令人失望的疏忽。

所以我所做的就是把上面的示例代码抽象为一个帮助器,这样我现在的函数几乎与普通的$ this-> load-> model()函数完全相同。在这里它(把它放到一个自动加载的帮助器中,你可以在任何模型中使用它):


   /**
    *
    * Allow models to use other models
    *
    * This is a substitute for the inability to load models
    * inside of other models in CodeIgniter.  Call it like
    * this:
    *
    * $salaries = model_load_model('salary');
    * ...
    * $salary = $salaries->get_salary($employee_id);
    *
    * @param string $model_name The name of the model that is to be loaded
    *
    * @return object The requested model object
    *
    */
   function model_load_model($model_name)
   {
      $CI =& get_instance();
      $CI->load->model($model_name);
      return $CI->$model_name;
   }

答案 2 :(得分:8)

这可能,但不是理想的,被认为是坏的,更多的是“快速修复”,而非理想或纯粹的实施。

class Location extends Model{
      public function get($ID){
                // Get main CI object handle and load model
                $CI =& get_instance();
                $CI->load->model('LocationType');
                // Call new model functions using handle to main CI object
                $CI->LocationType->setID($result->LocationTypeID);
                $CI->LocationType->setTitle($result->TypeTitle);
                $this->_locationType = $CI->LocationType;
                //Other Stuff
    }
}

任何时候你像这样使用主CI对象可能是一个坏主意。尝试重新考虑您的布局,只需将数据传入控制器或从控制器传递到模型。

http://codeigniter.com/forums/viewthread/69833/

答案 3 :(得分:6)

您可以像Phil Sturgeon所说的那样从模型中加载模型,但是如果在模型构造函数中加载模型,则必须小心依赖项:如果模型A使用模型B而模型B使用模型A,则在尝试加载时一个或另一个,你将进入一个无限循环。

答案 4 :(得分:1)

在Code Igniter中的情况中,我更喜欢两种可能性之一:

1)具有这样的模型属性和设置器:

class X extends Model {
  var $Y_model;
  public function setY($Y) {
    $this->Y_model = $Y;
  }

  public function doItRightNow($a,$b) {
    $list = $this->Y_model->getSomeList($a,$b);
    // ...
  }
  // ...
}


然后在其他方法之前使用此setter来提供其他模型的实例,以便方法可以使用它。

$this->load->model('X');
$this->load->model('Y');
$this->X->setY($this->Y);
$this->X->doItRightNow($something,$somethingElse);



2)在方法中有一个参数,我将从控制器给出另一个模型实例。

class X extends Model {
  public function doItRightNow($a,$b,$Y_model) {
    $list = $Y_model->getSomeList($a,$b);
    // ...
  }
  // ...
}

并像这样使用它:

  $this->load->model('X');
  $this->load->model('Y');
  $this->X->doItRightNow($something,$somethingElse,$this->Y);


我认为这些是更清洁的可能性 使用哪种方式取决于需要访问其他模型的方法数量。如果有一个或两个,那么将它作为方法参数提供可能会更好。如果更多 - 我认为拥有一个class属性和setter会更好 并且以优雅的方式,您可以根据某些条件提供一个或另一个模型 - 如果它们都部分实现了返回相同类型数据的相同接口(它很少有用,但有时也可以)。

答案 5 :(得分:0)

我认为访问模型的写库通常更好,然后在需要时将库包含在模型中。

例如,如果您需要检查某人是否有权使用某个CRUD操作,您可能希望包含您正在使用的任何身份验证库(在大多数情况下可能会自动包含该身份验证库)。你不一定想直接访问模型 - 它看起来很脏而且不合适。

我认为首选方法是在控制器中执行您需要执行的操作,并将结果从一个模型的方法传递给您的其他模型的方法。

无论如何,我不明白为什么不可能将一个模型包含在另一个模型中。不过,我认为你不能用你所显示的语法来做到这一点。你必须以其他复杂的方式做到这一点。在任何情况下,IMO,将模型直接包含在另一个模型中是不好的做法。

答案 6 :(得分:0)

在CI 2.0中,您可以直接从另一个模型调用一个模型。

答案 7 :(得分:-1)

最好创建一个辅助函数,而不是从另一个模型调用函数,这样它一次可以在2个模型中使用,代码可以重用。