过去,在CodeIgniter模型中,您无法访问其他模型。
$this->load->model('bar');
$this->bar->something();
这仍然有效,还是他们改变了?
答案 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对象可能是一个坏主意。尝试重新考虑您的布局,只需将数据传入控制器或从控制器传递到模型。
答案 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个模型中使用,代码可以重用。