Doctrine findBy with multiple conditional fields - symfony

I have some bad data in the table but not all fields have null values and I want to get all bad rows with one iteration by implementing something like this, if possible.
$contactObj = $this->em->getRepository("ImporterBundle:Contact")
->findBy([$field1 => null OR $field2 => null OR $field3 => null ...]);
Are there is a solution to do something like above example without using repositoryClass?

You can use the matching(Criteria $criteria) function of Doctrine\ORM\EntityRepository:
use Doctrine\Common\Collections\Criteria;
$criteria = Criteria::create()
->where(Criteria::expr()->isNull('functions'))
->orWhere(Criteria::expr()->isNull('salutation'))
->orWhere(Criteria::expr()->isNull('category'))
->orWhere(Criteria::expr()->isNull('address'))
->orWhere(Criteria::expr()->isNull('city'))
->orWhere(Criteria::expr()->isNull('company'));
$contactObj = $this->em->getRepository("ImporterBundle:Contact")
->matching($criteria);
Doctrine expression builder

So I just need to use repository class
And use expressions.
public function getBadData() {
$db = $this->createQueryBuilder('c');
return $db->select('c')
->where($db->expr()->isNull('c.functions'))
->orWhere($db->expr()->isNull('c.salutation'))
->orWhere($db->expr()->isNull('c.category'))
->orWhere($db->expr()->isNull('c.address'))
->orWhere($db->expr()->isNull('c.city'))
->orWhere($db->expr()->isNull('c.company'))
->getQuery()
->getResult();
}
As JimL suggested, I had change repository method by using orX()
public function getBadData() {
$db = $this->createQueryBuilder('c');
return $db->select('c')
->where($db->expr()->orX()->addMultiple(
[
'c.functions is null',
'c.salutation is null',
'c.category is null',
'c.address is null',
'c.city is null',
'c.company is null'
]
))
->getQuery()
->getResult();
}
Which now should be more readable.

Related

Symfony Form Query Builder

I have a problem with my query builder but I do not know how to fix this error can you help me please?
So here is my problem, I want to retrieve the list of questions that are not in my questionnaire and have the same theme as my questionnaire.
Here is my code:
$builder
->add('orderQuestion')
->add('idQuestion', EntityType::class, [
'class' => Question::class,
'query_builder' => function(EntityRepository $er) use ($idTheme, $idQuestionnaire){
$resultatQuestion = $er->createQueryBuilder('questionn')
->select('questionn.id')
->innerJoin('App\Entity\SurveyQuestion', 'surveyQuestion', 'WITH', 'questionn.id = surveyQuestion.idQuestion')
->where('surveyQuestion.idSurvey = :idSurvey')
;
$resultat = $er->createQueryBuilder('q')
->leftJoin('q.surveyQuestions', 'sQ')
->leftJoin('sQ.idSurvey', 's')
->where('q.idTheme = :idTheme')->setParameter('idTheme', $idTheme)->setParameter(':idSurvey', $idQuestionnaire)
->andWhere($er->createQueryBuilder('question')->expr()->notIn('q.id', $resultatQuestion->getDQL()))
;
return $resultat;
},
'choice_label' => function ($question) {
return $question->getLabel();
},
])
;
But, with this code a have this error : "Warning: get_class() expects parameter 1 to be object, array given".
How can I solve this problem ?
could you modify your code
$resultat = $er->createQueryBuilder('q')
->leftJoin('q.surveyQuestions', 'sQ')
->leftJoin('sQ.idSurvey', 's')
->where('q.idTheme = :val')
->andWhere('q.id NOT IN ' . $test)
->setParameter('val', $idTheme)
->getQuery()
->getResult()
;
So, to be clear, as I mentioned in the comment and in the Symfony's documentation - 'query_builder' can either be a QueryBuilder object, a callable or null.
This way you need to remove ->getQuery() and ->getResult() from your second query.
Update
So, thanks for the clarification from #msg in comments. And according it, you also need to remove from the first statement ->getQuery() and ->getResult() too and just add there ->getDQL()
And it should work.

How to pass Array of Entities to Entity Repository and run `where in` query?

I have array of Plan $plans.
How to pass that array of $plans to my member controller?
Currently I use:
* #param Plans|array $plan in annotations
public function findMembersByPlans( $planArray)
{
$queryBuilder = $this->createQueryBuilder('m');
$count = $queryBuilder->select('count(m)')
->leftJoin('mp.plan', 'p')
->where($queryBuilder->expr()->in('p.plan', ':planArray'))
->setParameters(
[
'planArray'=> $planArray,
]);
How to get count of members? When I am Passing 1 Object. Plan $plan as parameter everything is ok.
You can try something like this:
->leftJoin('mp.plan', 'p', Join::WITH, $queryBuilder->expr()->in('p.id', ':planIds'))
->setParameteter('planIds', array_map(
function (Plan $plan) {
return $plan->getId();
}, $planArray
))
And you can remove the where clause.

symfony3 doctrine. Make condition for related records

i have entity ShopGoods with relation manyToMany to entity ShopCategory. That's my method for get list of goods:
public function getListByFilter(ShopGoodsFilter $filter) {
$qb = $this->createQueryBuilder('goods')
->select('goods')
->leftJoin('goods.categories', 'categories')
->where('categories.id = :category_id')
->andWhere('goods.status=1')
->andWhere('categories.status != 0') // it's my try...
->setParameter('category_id', $filter->getCategory()->getId())
->setMaxResults($filter->getLimit())
->setFirstResult($filter->getOffset());
return [
'data' => $qb->getQuery()->getResult(),
'total' => $this->getTotalByFilter($filter)
];
}
I can't understand how make condition to get goods with categories.status = 1 for all related categories.
You could use something like:
$qb = $this->createQueryBuilder('goods')
->select('goods')
->leftJoin('goods.categories', 'categories', 'WITH', 'categories.status = 1')

Doctrine / Symfony: convert custom type to database value before using QueryBuilder

I have defined a custom Doctrine data type for Uuid. When I search for an object using find($uuid), it works correctly, i.e. the attribute is converted using convertToDatabaseValue() before executing the query, and converted back with convertToPhpValue() when value is retrieved.
The conversion doesn't work if I use the QueryBuilder. Example:
$qb = $this->createQueryBuilder('s');
$qb = $qb->where( //some conditions...
$qb->expr()->eq( 's.uuid', ':uuid' ))->setParameter( 'uuid', $uuid );
I found two similar unanswered questions:
Symfony Doctrine datatype only works in findBy not querybuilder
Doctrine 2 Custom Types
It looks like that the conversion is in fact ignored.
How can I force the conversion of the parameter before executing the query? Is there a way to access the convertToDatabaseValue() function of the custom data type from the repository?
Thanks
Yes setParameter() has third parameter, but the type of third param as string is worked for me not the object.
You can do it in following way.
$qb = $this->createQueryBuilder('s');
$qb = $qb->where( //some conditions...
$qb->expr()->eq( 's.uuid', ':uuid' ))->setParameter( 'uuid', $uuid, 'uuid' );
If you dont know what exactly key is for datatype 'uuid' is.
Then use print_r(Type::getTypesMap()); to get list of all dataypes added.
In my case it was
Array
(
[array] => Doctrine\DBAL\Types\ArrayType
[simple_array] => Doctrine\DBAL\Types\SimpleArrayType
[json_array] => Doctrine\DBAL\Types\JsonArrayType
[object] => Doctrine\DBAL\Types\ObjectType
[boolean] => Doctrine\DBAL\Types\BooleanType
[integer] => Doctrine\DBAL\Types\IntegerType
[smallint] => Doctrine\DBAL\Types\SmallIntType
[bigint] => Doctrine\DBAL\Types\BigIntType
[string] => Doctrine\DBAL\Types\StringType
[text] => Doctrine\DBAL\Types\TextType
[datetime] => Doctrine\DBAL\Types\DateTimeType
[datetimetz] => Doctrine\DBAL\Types\DateTimeTzType
[date] => Doctrine\DBAL\Types\DateType
[time] => Doctrine\DBAL\Types\TimeType
[decimal] => Doctrine\DBAL\Types\DecimalType
[float] => Doctrine\DBAL\Types\FloatType
[binary] => Doctrine\DBAL\Types\BinaryType
[blob] => Doctrine\DBAL\Types\BlobType
[guid] => Doctrine\DBAL\Types\GuidType
[geometry] => CrEOF\Spatial\DBAL\Types\GeometryType
[point] => CrEOF\Spatial\DBAL\Types\Geometry\PointType
[polygon] => CrEOF\Spatial\DBAL\Types\Geometry\PolygonType
[linestring] => CrEOF\Spatial\DBAL\Types\Geometry\LineStringType
)
And my doctrine code was something like this.
$queryBuilder = $this->createQueryBuilder('c');
$queryBuilder
->where('st_contains(:polygon, point(c.latitude, c.longitude) ) = 1')
->setParameter('polygon', $city->getPolygon(), 'polygon');
Here's the solution: the function setParameter() has a third argument $type which is used to declare the typology of the parameter. The custom declared type can be retrieved with the getType() function of the Doctrine Type class:
$qb = $this->createQueryBuilder('s');
$qb = $qb->where( //some conditions...
$qb->expr()->eq( 's.uuid', ':uuid' ))->setParameter( 'uuid', $uuid, Type::getType('uuid') );

Symfony2 Doctrine Expr 'IS NOT NULL'

I'm using the FormType for an Entity of mine, and setting up an entity field.
I need two Where clauses in an And, and from what I've read on the Query Builder page, this is at least how I should go about it:
'query_builder' => function ($er){
$qb = $er->createQueryBuilder('p');
$qb
->where($qb->expr()->andx(
$qb->expr()->in('p', '?1'),
$qb->expr()->not(
$qb->expr()->eq('p.location', 'NULL')
)
))
->setParameter(1, $this->totalScope)
;
return $qb;
},
However, the not(eq('col', 'NULL')) doesn't achieve the desired result, and in fact, errors with:
Error: Expected Literal, got 'NULL'
You can use isNotNull:
'query_builder' => function ($er){
$qb = $er->createQueryBuilder('p');
$qb
->where($qb->expr()->andx(
$qb->expr()->in('p', '?1'),
$qb->expr()->isNotNull('p.location')
))
->setParameter(1, $this->totalScope);
return $qb;
},
You can also use DQL in your queryBuilder, which is much less ugly IMO.
Quick and dirty example from a controller:
$repo = $this->getDoctrine()->getRepository('AcmeBundle:Transaction');
$query = $repo->createQueryBuilder('t')
->where('t.timestamp > :timestamp')
->andWhere('t.pinNumber IS NOT NULL')
->setParameter('timestamp', new \DateTime('1 day ago'))
->getQuery()
;
Easier to read in my estimation.
You can use the QueryBuilder to find the results,
$query=$this->dm->createQueryBuilder('AppBundle:DocumentName')
->field('fieldName')->notEqual(null);
$data=$query->getQuery()->execute();

Resources