Доступ к моделям CodeIgniter в других моделях - PullRequest
38 голосов
/ 16 мая 2009

Раньше в модели CodeIgniter не было доступа к другой модели.

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

Это все еще в силе, или они изменили это?

Ответы [ 8 ]

69 голосов
/ 16 марта 2010

Это ОЧЕНЬ длинные ответы на простой вопрос.

Краткий ответ: Теперь это полностью поддерживается. Перекрестная загрузка, если вам это нравится!

39 голосов
/ 21 сентября 2009

Я категорически не согласен с тем, что «модель» должна инкапсулировать таблицу базы данных только с простыми операциями CRUD. Как отмечено в статье в Википедии:

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

... этот прикладной уровень призван сделать больше, чем просто действовать как абстракция таблицы единой базы данных. Подумайте о значении слова «контроллер» - оно должно действовать скорее как директор, а не как само приложение. «Модель» - это место для бизнес-логики. Большинство крупномасштабных приложений фактически хранят большую часть своей бизнес-логики в самой базе данных (в форме триггеров, хранимых процедур, внешних ключей и т. Д.).

Я думаю, что неправильное понимание того, что такое «модель», отчасти вызвано той же (чрезмерной) шумихой «MVC», не имея при этом особого понимания самих концепций. Вроде как, насколько пустой «AJAX» или, еще проще, «Web 2.0». К счастью или к сожалению, на повозке MVC запрыгнуло множество детишек сценариев, и поскольку простые сценарии с практическими рекомендациями и примерами делают не больше, чем просто совет поместить код вашей базы данных в «модель», злоупотребление этим слоем как только абстракция базы данных стала обычным явлением. Теперь вы читаете сообщения по всему Интернету, называя их «нечистыми», «грязными», «хакерскими», чтобы поместить любую бизнес-логику в модель. Это неверно. Дезинформировали.

Простой пример - подумать о внешних ключах: даже если вы хотите, чтобы ваша "модель" была моделью базы данных , если вы хотите быть "чистой", "правильной" или чем-то еще вы действительно должны обеспечивать ссылочную целостность в нем. Благодаря отсутствию реальной поддержки внешнего ключа в MySQL в течение многих лет веб-приложения росли, и никто не беспокоился о ссылочной целостности вообще. Подходит для сценария детского образа жизни, я думаю. В любом случае, даже для того, чтобы даже этот упрощенный вид модели мог поддерживать достоверность внешнего ключа, модель должна работать с другими (или, особенно, если такая среда, как 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;
   }
8 голосов
/ 17 мая 2009

Это возможно, но не идеально и считается плохим и больше для "быстрого исправления", чем идеальная или чистая реализация.

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/

6 голосов
/ 11 ноября 2010

Вы можете загружать модели из моделей, как говорит Фил Стерджон, но вы должны быть осторожны с зависимостями, если загружаете модели в конструктор моделей: если модель A использует модель B, а модель B использует модель A, при попытке загрузить один или другой, вы попадете в бесконечный цикл.

1 голос
/ 16 марта 2010

В подобных ситуациях в 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);



Я думаю, что это более чистые возможности.
Какой способ использования зависит от того, сколько методов необходимо для доступа к другой модели. Если есть один или два, было бы лучше дать это как параметр метода. Если больше - я думаю, что лучше иметь атрибут класса и сеттер.
И элегантным способом вы можете указать ту или иную модель в зависимости от какого-либо условия - если они оба частично реализуют один и тот же интерфейс с возвращаемыми данными одного и того же типа (это редко полезно, но иногда может быть).

0 голосов
/ 29 июля 2016

Лучше создать вспомогательную функцию, а не вызывать функцию из другой модели, чтобы ее можно было использовать в 2 моделях одновременно и повторно использовать код.

0 голосов
/ 14 июля 2011

В CI 2.0 вы можете просто вызывать одну модель напрямую из другой.

0 голосов
/ 16 мая 2009

Я думаю, что обычно лучше писать библиотеки, которые обращаются к моделям, а затем включают библиотеки в вашу модель, если это необходимо.

Например, если вам нужно проверить, авторизован ли кто-либо выполнить определенное действие CRUD, вы можете включить любую используемую вами библиотеку аутентификации (в большинстве случаев она, вероятно, включается автоматически). Вы не обязательно хотели бы получить доступ к модели напрямую - она ​​кажется грязной и неправильной.

Я думаю, что предпочтительным способом является сделать то, что вам нужно сделать в вашем контроллере, и передать результаты метода (ов) одной модели, если необходимо, в метод (ы) другой модели.

Несмотря на это, я не понимаю, почему было бы невозможно включить одну модель в другую, как таковую. Я не думаю, что вы можете сделать это с синтаксисом, который вы показываете, хотя. Вы должны сделать это каким-то другим запутанным способом. В любом случае, IMO, это плохая практика - включать модель непосредственно в другую модель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...