Symfony / Doctrine findBy - PullRequest
       10

Symfony / Doctrine findBy

0 голосов
/ 28 января 2020

Хов, чтобы создать собственную функцию репозитория, которая запрашивает поле json. В моей базе данных есть столбец params, который выглядит следующим образом: "params": { "product": "stopper", "itemIdentifier": "" }

Я хочу запросить запись по значению продукта. В этом случае термин пробка.

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Если я правильно понял ваш вопрос, у вас есть таблица со столбцом с именем params. И внутри этого столбца mysql вы храните текст JSON.

И затем вы хотите запросить эту таблицу и выполнить фильтрацию, посмотрев на JSON в вашем столбце.

Это может быть немного утомительным, и в прошлом его тоже очень не поощряли (до JSON Type в Mysql 5.7.8). Лучшей практикой было бы иметь базу данных No SQL, такую ​​как MongoDB, которая фактически JSON хранится в коллекции (таблица).

В любом случае, для вас есть решение.

Принимая во внимание, что @AppyGG объяснил, как создать пользовательскую функцию репозитория.

Прежде всего, мы должны сделать запрос, используя чистый SQL. Это можно сделать двумя способами:

1.Возврат массивов, содержащих ваши данные.

$conn = $this->getEntityManager()->getConnection();

$sql = '
    SELECT * FROM product p
    WHERE p.price > :price
    ORDER BY p.price ASC
    ';
$stmt = $conn->prepare($sql);
$stmt->execute(['price' => $price]);

// returns an array of arrays (i.e. a raw data set)
return $stmt->fetchAll();

2.Возврат гидратированных объектов

use Doctrine\ORM\Query\ResultSetMappingBuilder;

$rsm = new ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('MyProject\Product', 'p');

$sql = '
    SELECT * FROM product p
    WHERE p.price > :price
    ORDER BY p.price ASC
    ';
 $nql = $this->_em->createNativeQuery( $sql, $rsm );
 $nql->setParameter('price', $price);

//Return loaded entities
return $nql->getResult();

Теперь, зная, как сделать сделав запрос MySQL с помощью doctrine, мы хотим выбрать результаты, отфильтрованные в JSON данных.

Я ссылаюсь на этот красивый стековый поток, который объясняет все это: Как искать JSON данные в MySQL?

Самое простое предлагаемое решение требует как минимум MySQL 5.7.8

Ваш запрос MySQL будет выглядеть следующим образом:

//With $entity->getParams() == '{"params": {"product":"stopper", "itemIdentifier":""}}'
$conn = $this->getEntityManager()->getConnection();

$sql = '
    SELECT * FROM Entity e
    WHERE JSON_EXTRACT(e.params, "$.params.product") = :product
    ';
//Or Like this if the column is of Type JSON in MySQL(Not doctrine, yes check MySQL).
$sql = '
    SELECT * FROM Entity e
    WHERE e.params->"$.params.product" = :product
    ';
$stmt = $conn->prepare($sql);
$statement->bindValue("product","stopper");
$stmt->execute();
return $statement->fetchAll();

Надеюсь, это поможет!

PS: обратите внимание, что в моем примере используется столбец с именем 'params' с Json, содержащий также именованный атрибут 'params', это может сбить с толку. Предполагаемая цель - показать, как выполнять многоуровневую фильтрацию.

0 голосов
/ 28 января 2020

Вы можете достичь этого с помощью classi c пример:

В вашем хранилище: Для одного результата

public function findOneProduct($value): ?Params
{
    return $this->createQueryBuilder('p')
        ->andWhere('p.product = :val')
        ->setParameter('val', $value)
        ->getQuery()
        ->getOneOrNullResult()
    ;
}

Для нескольких результатов

public function findParamsByProduct($value): ?Params
{
    return $this->createQueryBuilder('p')
        ->andWhere('p.product = :val')
        ->setParameter('val', $value)
        ->orderBy(/*some field */)
        ->setMaxResults(/*if needed*/)
        ->getQuery()
        ->getResults()
    ;
}

В ваш контроллер:

$stoppers = $entityManager->getRepository(Params::class)->findParamsByProduct('stopper');
...