Методы фильтрации в коллекции результатов Doctrine?

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

Я пишу инструмент импорта данных, который должен проверять, что каждая импортируемая строка содержит действительные данные. Например, в строке есть ссылка на код продукта, мне нужно проверить, существует ли уже существующий объект Product с этим кодом. Если нет, отметьте эту строку как недопустимую.

Теперь я легко могу сделать что-то подобное для каждой строки.

$productCode = $this->csv->getProductNumber();
$product = $doctrine->getRepository('MyBundle:Product')->findOneBy(array('code' => $productCode ));

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

$query = $this->getEntityManager()->createQuery('SELECT p FROM MyBundle\Entity\Product p');
$products = $query->getResult();

Все хорошо, но потом мне нужно писать запутанные циклы для поиска.

Два вопроса:

1). Мне было интересно, не хватает ли мне некоторых служебных методов, таких как у вас в Коллекциях Magento, где вы можете искать в результатах Коллекции без дополнительных обращений к базе данных. Например, в Magento это будет повторять сбор и фильтровать свойство кода.

$collection->getItemByColumnValue("code","FZTY444");

2). В настоящий момент я использую запрос ниже, который возвращает «прямоугольный массив». Более эффективно, но могло быть и лучше.

$query = $this->getEntityManager()->createQuery('SELECT p.code FROM MyBundle\Entity\Product p');
$products = $query->getResult();

Есть ли способ вернуть одномерный массив без повторения набора результатов и преобразования в плоский массив, чтобы я мог использовать in_array () для результатов?


person powerbookboy    schedule 14.06.2012    source источник


Ответы (2)


Если я правильно понял ваш вопрос, вы хотите отфильтровать массив объектов, возвращаемых getResult (). У меня был похожий вопрос, и я думаю, что нашел два способа сделать это.

Метод 1: массивы

Используйте метод array_filter для вашей $products переменной. Да, это представляет собой «цикл» в фоновом режиме, но я думаю, что это общеприемлемый способ фильтрации массивов, а не его собственное написание. Вам необходимо предоставить обратный вызов (предпочтительно анонимная функция в 5.3). Вот пример

$codes = array_filter($products, function($i) {
    return $i->getCode() == '1234';
});

Обычно в вашей функции возвращайте true, если вы хотите, чтобы результат возвращался в $codes, и false в противном случае (не уверен, необходимо ли false или достаточно ли возвращаемого значения void).

Метод 2: коллекция ArrayCollection доктрины

В вашем собственном репозитории или везде, где вы возвращаете метод getResult (), вы можете вместо этого вернуть ArrayCollection. Он находится в пространстве имен Doctrine Doctrine\Common\Collections\. Дополнительную документацию по интерфейсу этого метода можно найти здесь. Итак, в этом случае у вас будет

$query = $this->getEntityManager()->createQuery('SELECT p FROM MyBundle\Entity\Product p');
$products = new ArrayCollection($query->getResult());

Затем вы можете использовать метод filter () для коллекции массивов. Используйте его очень похоже на array_filter. За исключением того, что ему не нужен первый аргумент, потому что вы называете его так: $products->filter(function($i) { ... });

Класс ArrayCollection является итератором, поэтому вы можете использовать его в foreach циклах, сколько душе угодно, и он не должен отличаться от массива ваших продуктов. Если в вашем коде явно не используется $products[$x], тогда это должно быть plug 'n' play *.

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

person MikeMurko    schedule 13.11.2012

Вы можете использовать другой режим увлажнения. $ query-> getResult () обычно возвращает результат в виде гидратации объекта. Взгляните на $ query-> getScalarResult (), который должен больше соответствовать вашим потребностям.

Дополнительная информация о Веб-сайт Доктрины 2.

person Pierre    schedule 14.06.2012
comment
Привет, Пьер. $ query = $ this- ›getEntityManager () -› createQuery ('ВЫБРАТЬ p.code FROM MyBundle \ Entity \ Product p'); $ products = $ query- ›getScalarResult (); Это возвращает вложенный массив, каждый член которого содержит только «кодовый» ключ. Кажется странным, что когда возвращается только один столбец, создается вложенный массив. Кажется, что ни один из различных вариантов гидратации не может вернуть один массив, содержащий только значения, возвращенные из запроса ... - person powerbookboy; 15.06.2012
comment
Вы можете написать собственный гидратор. Мне кажется, это самый чистый подход. - person Pierre; 16.06.2012