symfony2 doctrine query negation of where - symfony

i wanna query for all of my categories like this:
$othercategories = $this->getDoctrine()->getRepository('Bundle:Category')->findBy(
array('language' => $language, 'active' => 1),
array('sorting' => 'ASC')
);
what i wanna do is to add another parameter to my query, i want all categories EXCEPT one with a specific id. so like:
WHERE id NOT IN ( 2 )
or
WHERE id <> 2
how can i achieve that?

You can use DQL queries like this
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery( 'SELECT c FROM Bundle:Category c WHERE c.language = :language AND c.active = 1 AND c.id NOT IN ( 2 ) ORDER BY c.language ASC' )
->setParameter('language', $language);
$category= $query->getResult();
Sorry I couldn't test this because I am using my phone to answer this question and I don't know your entity variables. Let me know what changes you did to make it work, it will help others.
For more info check http://symfony.com/doc/master/book/doctrine.html
You can add these queries in repository and reuse them. Refer the Cook book on http://symfony.com/doc/master/cookbook/index.html
Hope this helped.

You can use this syntax if you prefer
$repository = $this->getDoctrine()->getRepository('Bundle:Category');
$queryBuilder = $repository->createQueryBuilder();
$notInCategoryIds = array(2); // Category ids that will be excluded
$queryBuilder->select('c')
->from('Bundle:Category', 'c')
->where('c.language = :language')->setParameter('language', $language)
->andWhere('c.active = :active')->setParameter('active', 1)
->andWhere($queryBuilder->expr()->notIn('c.id', $notInCategoryIds)
->orderBy('c.sorting', 'ASC');
$results = $queryBuilder->getQuery()->getResult();
It's probably going to be more useful for other developers that prefers this syntax

Related

update an arrayResult of doctrine

i this query i get all of phones with certain condition
and one thing that i want after that is to set isFirstInstalled of all phones in this query to 1
also i want data of this query for api result
what is the most optimize way for that
the simplest way is using the result of the query in foreach and set one by one to 1 ?!
i want the result of my query before updating
$isFirstNotInstalledCases = $em->getRepository(User::class)
->createQueryBuilder('u')
->select("u.phone as phone")
->addSelect("u.isFirstInstalled as isFirstInstalled")
->where("u.phone IN (:phone)")
->andWhere("u.isFirstInstalled = :isFirstInstalled")
->setParameters(['isFirstInstalled'=>0,'phone'=>$phones])
->getQuery()
->getArrayResult();
Try to avoid foreach if you have not to do logic, use update better. Something like this:
$qb = $this->_em->createQueryBuilder();
$q = $qb->update('App\User', 'u')
->set('u.isFirstInstalled', 1))
->where("u.phone IN (:phone)")
->andWhere("u.isFirstInstalled = :isFirstInstalled")
->setParameters(['isFirstInstalled'=>0,'phone'=>$phones])
->getQuery();
$p = $q->execute();

Convert SQL query into Drupal 7 PHP rules

SELECT address
FROM user_address
WHERE username = '$user->name'
ORDER BY time DESC
LIMIT 1
Here is the SQL query that I can understand. How is it possible to convert it into Drupal's 7 PHP? I'm trying to figure that out for a day, and I tried different approaches, but it seems that I am just bad in that.
You can use db_select :
$results = db_select('user_address', 'ua')
->fields('ua', array('address'))
->condition('ua.username', $user->name, '=')
->orderBy('ua.time', 'DESC')
->range(0,1)
->execute()
->fetchAll();
var_dump($results);
Otherwise you can use db_query if you want to write entire SQL :
$results = db_query("SELECT address
FROM user_address
WHERE username = :username
ORDER BY time DESC
LIMIT 1 ", array(':username' => $user->name))->fetchAll();
var_dump($results);
Finally you can use db_query_range :
$page = 0;
$limit = 1
$results = db_query_range("SELECT address
FROM user_address
WHERE username = :username
ORDER BY time DESC",
$page * $limit,
$limit,
array(':username' => $user->name))
->fetchAll();
var_dump($results);
Try this:
$result = db_select('user_address', 'ua')
->fields('ua', array('address'))
->condition('ua.username', $user->name)
->execute()
->fetchAll();
For that we use db_select() or db_query() - first one preferable.
$query = db_select('user_address', 'u');
// Add condition and fields
$query->condition('u.username', ‘james’)
$query->fields('u’ array('u.address'));
// execute it
$result = $query->execute();
foreach ($result as $record) {
// Do something with each $record
}
For more see
https://www.drupal.org/docs/7/api/database-api/dynamic-queries/introduction-to-dynamic-queries.
update: see condition portion. Also, you can put this in a module or php executable area of your site or via drush command line.
Change the username James to match your need
$result = $result = db_select('usr_address','u')
->fields('u',array('address','uid'))
->range(0,1)
->orderby('time', 'DESC')
->condition('u.uid',$uid,'=')
->execute();
here is how it actually worked.
Thank you for your suggestions, but at the end I made it. By myself. Well, kinda ;D

How to make a Doctrine subquery?

I have two mysql tables and corresponding entities:
Question
--------
id
text
level
Asked
--------
* #ORM\ManyToOne(targetEntity="QuestionEntity")
* #ORM\JoinColumn(name="question", referencedColumnName="id")
question
user
I want to query for all questions that has a specific level and the question haven't been asked from a given user. How can I do this with an entity manager query builder?
With MySQL syntax the query would be:
SELECT
*
FROM
Question
WHERE
Question.level = 1
AND Question.id NOT IN( SELECT Asked.question FROM Asked WHERE Asked.user = 23)
I tried multiple things like Tomasz Madeyski commented, but I still got 500 Internal Server Error. This is my code: (I tested the subquery and it was fine when it is stand alone)
$em = $this->getDoctrine()->getManager();
$fbUser = $em->getRepository(FbUserEntity::class)->findOneBy(['fbId' => $session->get('fb_user_id')]);
$qb = $em->createQueryBuilder();
$qb2 = $qb;
$questions = $qb->select('q')
->from('MyBundle:QuestionEntity', 'q')
->where('q.level = :level')
->setParameter('level', $level)
->andWhere($qb->expr()->notIn(
'q.id',
$qb2->select('a.question')
->from('LMyBundle:AskedEntity', 'a')
->where('a.user = :userid')
->setParameter('userid', $fbUser->getId())
->getDQL()
))
->getQuery()
->getResult();
Try something like this:
$qb = $em->createQueryBuilder();
$subQuery = $qb->select('a.question')
->from('YourBundle:Asked', 'a')
->andWhere('a.user = 23')
$query = $qb->select('q')
->from('YourBundle:Question', 'q')
->andWhere('q.level = 1')
->andWhere($qb->expr()->notIn('q.id', $subQuery->getDQL())
->getQuery()
->getResult()
The key here is $qb->expr()->notIn() part
Investigating the logs I figured out that instead of
$qb = $em->createQueryBuilder();
$qb2 = $qb;
I should create a new queryBuilder for qb2:
$qb = $em->createQueryBuilder();
$qb2 = $em->createQueryBuilder();
But this still gives me an error. After some experimentingI figured out that if the subquery is executed, it gives something like this format:
array (size=2)
0 =>
array (size=1)
'question' => int 1
1 =>
array (size=1)
'question' => int 2
So I run through the subquery result like this:
$alreadyAsked = [];
foreach($asked as $q){
$alreadyAsked[] = $q['question'];
}
And pass the $alreadyAsked array to the main query like this, then it works:
->andWhere($qb->expr()->notIn('q.id', $alreadyAsked))

delete several rows where attribute = x

I need to delete all rows where the image_id = x applies
like this
DELETE FROM `ImageVoters` WHERE image_id =1
How do I do this using DQL?
Since im trying to delete several rows at once the remove() function won't work
EntityManager#remove() expects parameter 1 to be an entity object, array given.
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT u FROM GabrielUploadBundle:ImageVoters u WHERE u.image_id = 1');
$db_imageactions = $query->getResult();
$em->remove($db_imageactions);
$em->flush();
This is the code that works
$qb = $em->createQueryBuilder();
$qb->delete('GabrielUploadBundle:ImageVoters', 'v')
->where($qb->expr()->eq('v.image_id', ':imageId'))
->setParameter('imageId', $current_imageId);
$qb->getQuery()->execute();
You could create an ORM queryBuilder, to create a clean/safe query object by using internal orm methods
$qb->delete('My\Image\Namespace\ImageVoters', 'ivoter')
->where($qb->expr()->eq('ivoter.image_id', ':imageId')
->setParameter('imageId', 1);
$qb->getQuery()->execute();
You can also execute any raw SQL like this:
$sql = "DELETE FROM ImageVoters WHERE image_id =".$image_id;
$q = $em->getConnection()->exec($sql);

'where not in' query with doctrine query builder

Im trying to reproduce this query:
SELECT * FROM `request_lines`
where request_id not in(
select requestLine_id from `asset_request_lines` where asset_id = 1
)
in doctrine query builder,
I am stuck on the where request_id not in(select
I currently have:
$linked = $em->createQueryBuilder()
->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where()
->getQuery()
->getResult();
You need to use query builder expressions, and this means you need access to the query builder object. Also, the code is easier to write if you generate the subselect list ahead of time:
$qb = $em->createQueryBuilder();
$nots = $qb->select('arl')
->from('$MineMyBundle:MineAssetRequestLine', 'arl')
->where($qb->expr()->eq('arl.asset_id',1))
->getQuery()
->getResult();
$linked = $qb->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where($qb->expr()->notIn('rl.request_id', $nots))
->getQuery()
->getResult();
It is possible to do this in one Doctrine query:
$qb = $this->_em->createQueryBuilder();
$sub = $qb;
$sub = $qb->select('arl')
->from('$MineMyBundle:MineAssetRequestLine', 'arl')
->where($qb->expr()->eq('arl.asset_id',1));
$linked = $qb->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where($qb->expr()->notIn('rl.request_id', $sub->getDQL()))
->getQuery()
->getResult();
Check the reference in this answer here
Using Symfony 5, this solution might help those, who are trying to set parameters on a subquery, the notIn() 2nd argument accepts an array or you could pass a DQL instead and that's what we are doing here and keep in mind that the parameters should be added to the main query as below.
$main = $this->em->createQueryBuilder();
$sub = $main;
$sub = $sub->select('arl')
->from('$MineMyBundle:MineAssetRequestLine', 'arl')
->where($sub->expr()->eq('arl.asset_id',':id'));
$linked = $main->select('rl')
->from('MineMyBundle:MineRequestLine', 'rl')
->where($main->expr()->notIn('rl.request_id', $sub->getDQL()))
->setParameter('id', 1)
->getQuery()
->getResult();

Resources