在其他模型中访问CodeIgniter模型

它曾经是一个CodeIgniter模型中,你不能访问另一个模型。

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

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

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

简短的回答:现在完全支持。 交叉加载,如果你觉得喜欢它!

我坚决不同意“模型”只能用简单的CRUD操作封装数据库表的概念。 正如维基百科文章所述:

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

…应用程序层旨在做的不仅仅是单个数据库表抽象。 想想“控制器”这个词的含义 – 它应该更多的是作为导演,而不是整个应用程序本身。 一个“模型” 一个商业逻辑的地方。 实际上,大多数大型应用程序在数据库本身(以触发器,存储过程,外键等等)的forms保存着它们的大部分业务逻辑。

我认为,对“模型”的误解部分是由于“MVC”的相同(过度)炒作而造成的,而没有深入理解这些概念本身。 有点像“AJAX”是多么的空虚,甚至更容易,“Web 2.0”。 无论好坏,大量的脚本小子已经跳上了MVC的旅行车,因为简单的howtos和示例场景并不仅仅是告诉你把数据库代码放在“模型”中,而是滥用了这个层只有数据库抽象已经变得司空见惯了。 现在你阅读整个互联网的post,称它为“unpure”,“dirty”,“hackish”,把任何业务逻辑放在模型中。 这是错误的。 误导。

简单的例子是考虑外键:即使你只希望你的“模型”成为一个数据库模型,如果你想成为“纯”,“正确的”或你有什么,你真的应该在其中执行参照完整性。 由于多年来MySQL缺less真正的外键支持,Web应用程序的发展并没有人担心引用完整性。 适合脚本kiddie生活方式我猜。 无论如何,即使这个模型的简化视图能够保持外键的有效性,模型也必须与其他模型一起工作(或者,特别是如果像CodeIgniter这样的框架不允许你这样做,你必须向其他人写查询有时在别处复制查询 – 这是不好的风格)。

所以我相信这是CodeIgniter的一个缺点。 我明白,这可能不是一个简单的解决办法,但肯定是一个令人失望的疏忽。

所以我做了上面的示例代码,并将其抽象成一个帮助器,以便我现在有一个几乎与正常的$ this-> load-> model()function相同的函数。 在这里(把它放到一个自动加载的助手中,你可以在任何模型中使用它):

 /** * * 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; } 

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

 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/

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

在Code Igniter这样的情况下,我更喜欢以下两种可能性之一:

1)有这样的模型的属性和setter:

 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); 

我认为这是更清洁的可能性。
使用哪种方式取决于需要访问其他模型的方法数量。 如果有一两个,最好把它作为方法参数。 如果更多 – 我认为最好有一个类属性和setter。
在优雅的方式,你可以给一个模型或另一个取决于某些条件 – 如果他们都部分实现相同的接口返回相同types的数据(这是很less有用的,但有时可以)。

我认为一般来说,访问这些模型的写入库会更好,如果需要的话,将库包含在模型中。

例如,如果您需要检查某人是否有权通过某个CRUD操作,则可能需要包含您正在使用的任何身份validation库(大多数情况下可能是自动包含的)。 你不一定要直接访问模型 – 它看起来很脏,不正确。

我认为首选的方法就是在你的控制器中做你需要做的事情,并把结果从一个模型的方法(如果需要的话)传递给你的其他模型的方法。

无论如何,我看不出为什么把一个模型本身包含到另一个模型中是不可能的。 但是,我不认为你可以用你正在显示的语法来完成。 你将不得不做一些其他复杂的方式。 无论如何,国际海事组织(IMO)将一个模型直接纳入另一个模型是一个不好的做法。

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

最好创build一个辅助函数,而不是从另一个模型中调用该函数,以便一次可以在2个模型中使用它,并且可以重用代码。