Intereting Posts

Использование классов ORM непосредственно из контроллера в MVC, плохая практика?

Недавно я углубился в использование ORM в моем приложении CodeIgniter, и один, к которому я пошел, – Propel. Теперь это дает мне возможность в основном использовать классы Propels как «Модель», но так ли это плохо?

Таким образом, мой код контроллера будет выглядеть следующим образом:

<?php class Page extends Controller { function __construct() { parent::__construct(); } function index() { $foo = FooQuery::create()->limit(10)->find(); $data['content'] = array('foo'=>$foo); $this->load->view('home', $foo); } } ?> 

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

заранее спасибо

Да, это плохая практика.

Модель должна содержать всю вашу логику данных и отвлечь ее от остальной части программы. В остальной части приложения модели должны выглядеть как черные ящики, из которых он получает свои данные. Если вы используете ORM как свою модель, вы пропускаете абстракцию и плотно соединяете ваш контроллер с вашим уровнем данных.

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

Теперь, когда классы Propel теперь используются, я думаю, что разница с более «формальной» моделью становится все меньше и меньше. Если это станет библиотекой, которую вы выпустили в мир, было бы выгодно иметь слой абстракции, чтобы вы могли иметь разные серверы, но если это собственное приложение, я бы просто использовал классы Query качестве вашей модели.

Но помните, что классы Query создаются, чтобы чувствовать себя как фактический объект, и что они скрывают реляционную часть как можно больше. Вы можете использовать это в своих интересах. Ознакомьтесь с этой статьей о переписывании ваших SQL-запросов с помощью методов Query , особенно третьего ответа: все больше и больше перемещайтесь в свой класс Query , поэтому ваш контроллер не чувствует, что использует базу данных.

 // Instead of this code in your controller, // tightly coupled to your database logic $books = BookQuery::create() ->filterByTitle('%war%') ->filterByPrice(array('max' => 10) ->filterByPublishedAt(array('max' => time())) ->leftJoin('Book.Author') ->where('Author.Name > ?', $fameTreshold); // You would use this code in your controller // and create small methods with the business logic in the BookQuery class $books = BookQuery::create() ->titleContainsWord('war') ->cheap() ->published() ->writtenByFamousAuthors(); 

Я обнаружил, что это случайное зло, когда ваш ORM следует за шаблоном Active Row .

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

Именно здесь я исторически использовал сервисный уровень для обработки выдержек в коллекциях моделей. Хотя, честно говоря, в последнее время я просто написал объект-помощник контроллера, который просто абстрагирует мой объект таблицы.

Это зависит от того, что вы делаете и почему. в этом примере вы помещаете предложение ограничения в запрос – это бизнес или логика отображения? С моей точки зрения, трудно утверждать, что это бизнес-логика – я возвращаю 10 элементов, которые не имеют отношения к модели, – вот насколько я думаю, имеет смысл использовать на одной странице. Если вы хотите, чтобы это правило было согласованным между контроллерами, вы можете установить некоторое значение конфигурации для обеспечения согласованности. Но включение его в модель просто делает модель ненужной большой (есть разница между жировыми моделями и тучными моделями)

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

Пример из Jan Fabry в основном довольно хорош. filterByTitle выглядит примерно так же, как titleContainsWord. filterByPublishedAt (array ('max' => time ())) намного хуже, чем -> опубликовано (). В общем, чем меньше вы должны знать контроллеры о внутренней структуре данных, тем лучше.