M – for model

Очень-очень редко, но бывает нужно использовать в каком-нибудь методе контроллера несколько несвязанных между собой моделей. Еще раз, ключевые слова: «редко-редко» и «несвязанных».

Можно такие модели перечислить в переменной класса $uses — тогда, они, правда, будут загружаться для любого метода контроллера.

В версии 1.1 фреймворка была функция loadModel(), которая теперь отменена.

Есть еще метод requestAction(), но он объявлен «плохим». И правда, это, по сути, еще один запрос к приложению по полной программе, с диспетчеризацией, роутингом, стартом и инициализацией всех сопутствующих классов. В общем, путь неоптимальный и пользоваться им можно лишь от полной безысходности.

Можно воспользоваться методом App::import() — это хороший метод для многих классов. Но загруженная модель будет неполной. Т.е. это будет просто загруженный класс модели, без всех предварительных инициализаций самой модели и т.п. Этим методом лучше пользоваться для подгрузки своих классов или библиотек сторонних разработчиков.

В общем, я лично чаще всего в Cake 1.2 использовал именно App::import(), мирясь с некоторыми ограничениями. Но, оказывается есть еще один метод, позволяющий полностью загрузить модель, со всем ее «обвесом»

teknoid в своем блоге описал пример создания dashboard, ну примерно как в wordpress 2.7 :-) . Мне полезность самой dashboard как-то сомнительна, но не в ней дело. А дело в том, что это тот редкий случай, когда в одном отдельно взятом методе нужно вызывать методы нескольких совершенно неотносящихся друг к другу моделей. teknoid приводит пример с вызовами методов для извлечения самых активных пользователей, самых посещаемых страниц, свежих новостей и т.д.

Для этого он использует ускользнувший от моего внимания :-) метод ClassRegistry::init(). Вот как выглядит написанный им метод контроллер Dashboard:

<?php
    class DashboardController extends AppController {
 
          var $name = 'Dashboard';
          var $uses = array();
 
          function index () {
               $this->set('topPosts', ClassRegistry::init('Post')->getTop());
               $this->set('recentNews', ClassRegistry::init('News')->getRecent());
               $this->set('topEmployees', ClassRegistry::init('Employee')->getTopPerformers());
               $this->set('topSellingProducts', ClassRegistry::init('Product')->getTopSellers());
          }
    }
?>

Этот метод позволяет загрузить только нужные модели, и только тогда, когда они нужны. Это, на мой взгляд, гораздо интереснее перечисления моделей в переменной $uses и принудительной их загрузки вне зависимости от необходимости их использования.

В общем, на мой взгляд, очень полезная вещь. Надо запомнить, может пригодится. Thanks to teknoid :-)

Related Posts with Thumbnails
17.12.2008 • Метки: , • Рубрики: CakePHP
  • BorisPlus
    Попробовал, несколько вариантов в свое время. Так и не понял, к сожалению, как правильно загрузить компонент динамически в контроллер. Например, у меня много компонентов, между ними есть связи в виде наследования и делегирования, пришлось также создать подкомпоненты и поместить их в подпапку папки components. Как Вы и говорили, хочется загружать не все, а именно тот - который нужен, а кокой нужен - определяется через некоторый адапторКомпонент.
    Странно, но мне ни App::import, ни ClassRegistry::init почему-то это не позволили сделать. require_once в середине кода - очень не хотелось, но оно единственное помогло. Да, подумывал вынести все в вендеры, но этот функционал ближе к контроллерам, чем к чему либо еше и используется только в них.
  • Сергей
    Сейчас напишу пост, как я перегружаю компоненты. ;-)
blog comments powered by Disqus