Класс не имеет поля или ассоциации с именем user.email при использовании CallbackFilter для поиска в нескольких полях подмодели - PullRequest
0 голосов
/ 23 сентября 2019

Я использую Sonata Admin для управления своими объектами Order.У каждого Заказа есть Пользователь, а у каждого Пользователя есть электронная почта, имя и фамилия, которые являются строками.

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

[Семантическая ошибка] строка 0, столбец 72 рядом с 'email LIKE'% sally% '': Ошибка: Class App \ Entity\ У заказа нет поля или ассоциации с именем user.email

На странице документации есть этот дразнящий тизер:

TODO: * базовая конфигурация фильтра и опции * таргетинг на подмодельполя, использующие разделенную точками нотацию * расширенные параметры фильтра (global_search)

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

Как мне настроить свой запрос в OrderAdmin.php?

Вот соответствующая часть Order.php:

/**
 * @var User
 *
 * @ORM\ManyToOne(targetEntity="App\Application\Sonata\UserBundle\Entity\User", inversedBy="orders")
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
private $user;

... и соответствующая часть User.php:

/**
 * @Assert\Email(groups={"Import"})
 * @Groups({"api_read", "api_write"})
 */
protected $email;

/**
 * @Groups({"api_read", "api_write"})
 */
protected $firstname;

/**
 * @Groups({"api_read", "api_write"})
 */
protected $lastname;

... и вот соответствующая часть OrderAdmin.php:

/**
 * @param DatagridMapper $datagridMapper
 */
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
    $datagridMapper->add('user', CallbackFilter::class, [
        'show_filter' => true,
        'callback' => [$this, 'getFullUserNameFilter']
    ]);
}

public function getFullUserNameFilter($queryBuilder, $alias, $field, $value)
{
    if (!$value['value']) {
        return;
    }

    $queryBuilder->andWhere($queryBuilder->expr()->orX(
        $queryBuilder->expr()->like($alias.'.user.email', $queryBuilder->expr()->literal('%' . $value['value'] . '%')),
        $queryBuilder->expr()->like($alias.'.user.firstname', $queryBuilder->expr()->literal('%' . $value['value'] . '%')),
        $queryBuilder->expr()->like($alias.'.user.lastname', $queryBuilder->expr()->literal('%' . $value['value'] . '%'))
    ));
}

1 Ответ

0 голосов
/ 23 сентября 2019

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

public function getFullUserNameFilter($queryBuilder, $alias, $field, $value)
{
    if (!$value['value']) {
        return;
    }

    if(is_string($value['value'])) {
        $queryBuilder->leftJoin(sprintf('%s.%s', $alias, $field), 'user');
    }
    $queryBuilder->andWhere($queryBuilder->expr()->orX(
        $queryBuilder->expr()->like('user.email', $queryBuilder->expr()->literal('%' . $value['value'] . '%')),
        $queryBuilder->expr()->like('user.firstname', $queryBuilder->expr()->literal('%' . $value['value'] . '%')),
        $queryBuilder->expr()->like('user.lastname', $queryBuilder->expr()->literal('%' . $value['value'] . '%'))
    ));
}

(все остальное из моего примера кода остается прежним.)

Теперь фильтр работает отлично.

...