Как настроить SQL-запрос для ассоциаций сущностей в представлении редактирования Sonata Admin

У меня есть объект «Контакт», который имеет ассоциацию OneToMany с другим объектом «Счет-фактура»:

// src/AppBundle/Entity/Contact.php
/**
 * @var Collection
 *
 * @ORM\OneToMany(targetEntity="Invoice", mappedBy="contact", cascade={"persist", "remove"}, orphanRemoval=true)
 **/
private $invoices;

// src/AppBundle/Entity/Invoice.php
/**
 * @var Contacts
 *
 * @ORM\ManyToOne(targetEntity="Contact", inversedBy="invoices")
 * @ORM\JoinColumn(name="id_contact_fk", referencedColumnName="id_contact_pk")
 **/
private $contact;

Затем у меня есть класс Sonata Admin «ContactAdmin», который отображает эту ассоциацию в представлении редактирования:

// src/AppBundle/Admin/ContactAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->tab('Invoices')
            ->with('Invoices')
                ->add('invoices', 'sonata_type_collection', array(
                    'btn_add' => false,
                    'required' => false
                ), array(
                    'edit' => 'inline',
                    'inline' => 'table'
                ))
            ->end()
        ->end();
}

Это отлично работает, за исключением того, что у некоторых контактов есть сотни счетов за много лет. Мне нужно отобразить только счета за текущий год.

Не похоже, что есть какой-либо способ использовать динамическое значение (что-то вроде YEAR(CURDATE() в mysql) вместо столбца соединения при отображении ассоциации в Doctrine. Так что мне кажется, что мне нужно как-то переопределить запрос, который Sonata Admin/Doctrine использует при отображении представления редактирования ContactAdmin.

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

Существует событие sonata.admin.event.configure.form, с которым я мог бы действовать, но я не уверен, можно ли каким-либо образом изменить запрос из этого контекста?

Как я могу это сделать?


person Aaron    schedule 03.08.2015    source источник
comment
Вы должны иметь возможность добавить параметр запроса в массив параметров sonata -project.org/bundles/admin/master/doc/reference/ Я должен взять аргумент EntityRepository и вернуть построитель запросов.   -  person Jason Hendry    schedule 03.08.2015
comment
Спасибо за ответ @JasonHendry, однако «запрос» — это вариант только для типа формы «sonata_type_model». И я почти уверен, что он используется только для установки параметров элемента формы, и с его помощью невозможно переопределить запрос ассоциации.   -  person Aaron    schedule 04.08.2015


Ответы (2)


После некоторых копаний я обнаружил, что тип формы sonata_type_collection принимает недокументированный параметр с именем «данные». Вы можете передать ему коллекцию объектов напрямую, и он использует их.

person Aaron    schedule 07.08.2015
comment
Это работает, но после сохранения объекта сохраненные значения больше не отображаются в поле. - person amacrobert; 03.12.2019

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

Вместо этого используйте параметр query_builder:

$formMapper->add('invoices', null, [
    'query_builder' => function(\Doctrine\ORM\EntityRepository $invoice_repo) {
        return $invoice_repo
            ->createQueryBuilder('invoice')
            ->where('invoice.date > :date')
            ->setParameter('date', new DateTime('1 year ago'))
        ;
    }
]);
person amacrobert    schedule 02.12.2019