Раньше было, что в модели CodeIgniter вы не могли получить доступ к другой модели.
$this->load->model('bar');
$this->bar->something();
Это все еще актуально или они его изменили?
Раньше было, что в модели CodeIgniter вы не могли получить доступ к другой модели.
$this->load->model('bar');
$this->bar->something();
Это все еще актуально или они его изменили?
Это некоторые ОЧЕНЬ длительные ответы на простой вопрос.
Короткий ответ: Теперь это полностью поддерживается. Перегрузите карту, если вам это нравится!
Я категорически не согласен с тем, что "модель" должна инкапсулировать только таблицу базы данных с помощью простых операций CRUD. Как отмечено в статье в Википедии:
http://en.wikipedia.org/wiki/Model-view-controller#As_a_design_pattern
... этот прикладной уровень призван сделать нечто большее, чем просто действовать как абстракция одной таблицы базы данных. Подумайте о значении слова "контроллер" - он должен действовать скорее как директор, а не как само приложение. "Модель" - это место для бизнес-логики. Большинство приложений большого масштаба фактически хранят большую часть своей бизнес-логики в самой базе данных (в виде триггеров, хранимых процедур, внешних ключей и т.д.).
Я думаю, что непонимание того, что такое "модель", отчасти вызвано тем же (чрезмерным) шумом "MVC", не проводя с ним много понимания самих понятий. Кажется, что пустым "AJAX" является, или даже проще, "Web 2.0". К лучшему или к худшему, многие детишки script прыгнули на вагон MVC, а так как простые сценарии howtos и example не намного больше, чем сказать вам, чтобы вы поместили свой код базы данных в "модель", неправильное использование этого поскольку только абстракция базы данных стала обычным явлением. Теперь вы читаете сообщения по всему Интернету, называя это "нечистым", "грязным", "хакерским", чтобы поместить любую бизнес-логику в модель. Это НЕПРАВИЛЬНО. Дезинформировали.
Простым примером является думать о внешних ключах: даже если вы хотите, чтобы ваша "модель" была моделью базы данных, если вы хотите быть "чистой", "правильной" или какой у вас, вы действительно должны обеспечивать соблюдение ссылочной целостности. Благодаря отсутствию реальной поддержки внешнего ключа в MySQL на протяжении многих лет, веб-приложения выросли без всякого беспокойства по поводу ссылочной целостности вообще. Я полагаю, подходит для образа жизни script. Во всяком случае, даже при таком упрощенном представлении о модели, чтобы иметь возможность поддерживать внешний ключ, модель должна работать с другими (или, особенно, если инфраструктура, такая как 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;
}
Это возможно, но не идеально и считается плохим и более "быстрым", чем идеальная или чистая реализация.
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, например, это, вероятно, плохая идея. Попробуйте пересмотреть свой макет и просто передать данные в/из вашего контроллера к моделям.
Вы можете загружать модели с моделей, как говорит Phil Sturgeon, но вы должны быть осторожны с зависимостями, если вы загружаете модели в конструктор модели: если модель A использует модель B, а модель B использует модель A, когда вы пытаетесь загрузить один или другой, вы перейдете в бесконечный цикл.
В подобных ситуациях в 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);
// ...
}
// ...
}
И затем используйте этот установщик перед другими методами, чтобы дать экземпляр другой модели, чтобы он мог использоваться методами.
$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);
Я думаю, что это более чистые возможности.
Какой способ использовать зависит от того, сколько методов нужно получить в другой модели. Если есть один или два, может быть лучше указать его как параметр метода. Если больше - я думаю, что лучше иметь атрибут класса и сеттер.
И элегантным способом вы можете дать одну модель или другую в зависимости от какого-либо условия - если они оба частично реализуют один и тот же интерфейс с возвращенными такими же данными (это редко полезно, но иногда это может быть).
Я думаю, что в целом лучше писать библиотеки, которые обращаются к моделям, а затем включать библиотеки в вашу модель, если это необходимо.
Например, если вам нужно проверить, разрешено ли кому-либо проходить определенное действие CRUD, вы можете включить любую используемую библиотеку проверки подлинности (ее, вероятно, автоматически включали в большинстве случаев). Вы не обязательно хотите напрямую обращаться к модели - это просто кажется грязным и неправильным.
Я думаю, что предпочтительный способ - сделать то, что вам нужно сделать в вашем контроллере, и передать результаты из одного модельного метода (ов), если потребуется, другим вашим методам модели.
Независимо от того, я не понимаю, почему невозможно включить одну модель в другую. Я не думаю, что вы можете сделать это с синтаксисом, который вы показываете. Вы должны были бы сделать это каким-то другим запутанным способом. В любом случае, ИМО, это плохая практика включать модель непосредственно в другую модель.
В CI 2.0 вы можете просто вызвать одну модель напрямую из другого.
Лучше создать вспомогательную функцию вместо вызова функции из другой модели, чтобы ее можно было использовать в двух моделях одновременно, а код можно было повторно использовать.