#php #symfony #model-view-controller #doctrine-orm #doctrine
#php #symfony #модель-представление-контроллер #doctrine-orm #доктрина
Вопрос:
Давайте посмотрим на моего архитектора:
Модель:
// links table: (ID, LINKNAME)
Class Link extends Link_base
{
}
Контроллер:
public function index()
{
$this->links = new Doctrine - here I build the query, SELECT, ORDER BY, etc
}
в этом примере модель может оставаться пустой (без серьезной логики), все, что мне нужно, это выбрать с order by . Я не уверен, что могу использовать Doctrine в контроллере, хотя — должен ли я переделать его таким образом?
Class Link extends Link_base
{
public function getLinks()
{
return new Doctrine - here I build the query, SELECT, ORDER BY, etc;
}
}
Контроллер:
public function index()
{
$this->links = Links::getLinks();
}
Я не уверен, какой способ подходит. Конечно, при выборе требуется более сложная задача форматирования, она переходит к модели или помощнику — но я чувствую, что я только что создал новый (ненужный) слой. Этот getLinks() использовался только один раз. Другими словами: Doctrine может использоваться только в модели, или его можно использовать и в контроллерах?
Комментарии:
1. Может — да; должен — НЕТ
2. не могли бы вы подтвердить это примером или источником?
3. Doctrine2 — это платформа абстракции персистентности (реализующая шаблон отображения данных ), и ее никогда не следует использовать на уровне персистентности. Вместо этого его следует использовать в сервисах для хранения и извлечения данных из объектов домена (на уровне модели).
Ответ №1:
Ваши объекты (или модели, если вы предпочитаете это имя) должны не знать, как они сохраняются в / извлекаются из базы данных. Они должны быть просто простыми объектами PHP, содержащими только ряд свойств (соответствующих столбцам базы данных) и их получатели и установщики.
(Если вам интересно, прочитайте немного о принципе единой ответственности, который гласит, что у каждого класса должна быть одна и только одна ответственность. Если вы назначаете свои объекты ответственными за хранение данных и знаете, как сохранить эти данные в базе данных, у вас будет больше шансов внести ошибки при изменении одной из этих вещей.)
Вы можете извлекать объекты из своего контроллера:
<?php
namespace YourBundleController;
use SymfonyBundleFrameworkBundleControllerController;
class LinkController extends Controller
{
public function fooAction()
{
$links = $this->getDoctrine()
->getRepository('YourBundle:Link')
->findAll();
// do something with the result, like passing it to a template
}
}
Однако вам может потребоваться более сложный запрос (который включает сортировку и фильтрацию), и вам может потребоваться выполнить этот запрос с нескольких контроллеров. В этом случае вы не хотите дублировать эту логику на нескольких контроллерах, вы хотите сохранить эту логику в одном центральном месте.
Для этого создайте репозиторий:
<?php
namespace YourBundleRepository;
use DoctrineORMEntityRepository;
class LinkRepository extends EntityRepository
{
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQuery(
'SELECT l FROM YourBundle:Link l ORDER BY l.name ASC'
)
->getResult();
}
}
И добавьте класс репозитория в свое отображение:
YourBundleEntityLink:
type: entity
repositoryClass: YourBundleRepositoryLinkRepository
(проверьте документацию Symfony о пользовательских репозиториях, используете ли вы XML или аннотации вместо Yaml)
Теперь в вашем контроллере вы можете просто обновить свой fooAction
метод, чтобы он использовал ваш пользовательский метод репозитория:
public function fooAction()
{
$links = $this->getDoctrine()
->getRepository('YourBundle:Link')
->findAllOrderedByName();
}
Для получения дополнительной информации в документации Symfony есть отличная статья о Doctrine. Если вы еще этого не сделали, я бы определенно рекомендовал прочитать его.
Комментарии:
1. Красиво объяснено. Это напоминает о полезности репозиториев.