Я использую Doctrine\Common\Collections\Criteria::expr() ( НЕ выражение построителя запроса).
Похоже, что операторы isNotNull() и notLike() не реализованы в этом классе.
Каков наилучший способ сделать isNotNull() и notLike() в этом случае?
Я использую Doctrine\Common\Collections\Criteria::expr() ( НЕ выражение построителя запроса).
Похоже, что операторы isNotNull() и notLike() не реализованы в этом классе.
Каков наилучший способ сделать isNotNull() и notLike() в этом случае?
Чтобы иметь значение is not null которое действует как Criteria::expr()->isNotNull('field') вы можете использовать
$criteria = Criteria::create();
$expr = $criteria::expr();
$collection->matching($criteria->where($expr->neq('field', null)));
Это совпадает с тем, как построитель выражений создает isNull но изменяет оператор сравнения на NEQ через.
return new Comparison($field, Comparison::EQ, new Value(null));
Который затем проверяется QueryExpressionVisitor и BasicEntityPersister, используемыми для построения запроса.
Для функциональности Criteria::expr()->like() Criteria::expr()->contains('property', 'value') является эквивалентом property LIKE %value% SQL property LIKE %value%. Однако он не допускает изменения в value% или %value но запрашивает извлечение (по состоянию на 2.5.4) с предлагаемыми startsWith и endsWith использования, которые были объединены с главным, - поэтому может быть выпущено с 2.5.5.
К сожалению, для Criteria::expr()->notLike() и других вариантов LIKE, \Doctrine\Common\Collections\ExpressionBuilder используемый Criteria, не поддерживает их.
Кроме того, если оператор сравнения не определен (например, CONTAINS), QueryExpressionVisitor и BasicEntityPersister, которая не позволяет вручную определять собственную функцию Comparison.
Лучшей альтернативой является использование собственного репозитория и выражений построителя запросов DBAL для замены желаемой функциональности.
Использование собственного хранилища сущностей для фильтрации результирующего набора предотвратит полное чтение ваших коллекций и увеличит скорость при использовании кэширования.
Альтернативой является использование filter для извлечения определенного подмножества объектов в коллекции.
class MyEntity
{
public function getCollectionFieldNotLike($value)
{
return $this->getCollection()->filter(function($a) use ($value) {
return (false === stripos($a->getField(), $value));
});
}
public function getCollectionFieldLike($value)
{
return $this->getCollection()->filter(function($a) use ($value) {
return (false !== stripos($a->getField(), $value));
});
}
}
$repo->getCollectionFieldNotLike('value');
$repo->getCollectionFieldLike('value');
Для процедурного синтаксиса комбинация обоих на репозитории.
$criteria = Criteria::create();
$expr = $criteria::expr();
$criteria->where($expr->neq('field', null));
$collection = $entityManager->getRepository('app:MyEntity')->matching($criteria);
$collectionNotLike = $collection->filter(function($a) {
return (false === strpos($a->getField(), 'value'));
});
Имейте в виду, что, как указано выше, это приведет к полному чтению таблицы из коллекции, поскольку для фильтрации результатов потребуется извлечь записи.