Build a query inside another with querybuilder? - php

I got 2 tables User and Group; each object Group got an array members[] that points to some instances of User.
I need to build this same query with QueryBuilder :
SELECT (users instances) FROM User
WHERE (users instances) IN (SELECT Group.members from Group WHERE group.id = $someId)
How can I achieve that?

You have to make 2 querybuilders:
$qb2 = $this->em->createQueryBuilder('group')
->select('group.members')
->where('group.id = $someId');
$qb = $this->em->createQueryBuilder('user')
->select(user instances)
-where($qb->expr()->in('user instances', $qb2->getDQL());
it will give you the idea how it works. Of course you have to adjust this code to yours.

Improving #Eimsas Answer it could be:
$em = $this->getEntityManager();
$qb2 = $em->createQueryBuilder('group')
->select('group.members')
->where('group.id = $someId');
$qb = $em->createQueryBuilder('user');
$query = $qb->select(user instances)
->where($qb->expr()->in('user instances', $qb2->getDQL());
$result = $query->getQuery->getResult();

Related

From SQL to DQL

I want to change this SQL query : (i'm using a bundle)
(Evenement is an entity and evenement_evenement is the result of self-referencing many to many of evenement)
SELECT *
FROM evenement e
natural JOIN evenement_evenement ee
WHERE e.id = ee.evenement_source
AND e.id = 3
Into DQL. For now I have this :
public function findAllEventAssociateByEvent($idEvent){
$qb = $this->createQueryBuilder('e');
$qb->add('select', 'e');
$qb->from('Bundle:Evenement', 'e2');
$qb->where('e = :evenement');
$qb->andWhere('e2 in e.evenements');
$qb->setParameter('evenement', $idEvent);
return $qb;
//select * from evenement e NATURAL join evenement_evenement ee where e.id = ee.evenement_source and e.id = $idEvent
}
And i have this :
$eventAssocies = $em->getRepository('Bundle:Evenement')->findAllEventAssociateByEvent($id)->getQuery()->getResult();
But it's not working, i have an error in my "andWhere", but I don't know why...
I think you misunderstood some stuff, I reckon you query should more look like this:
public function findAllEventAssociateByEvent($idEvent){
$qb = $this->createQueryBuilder('e')
->join('e.evenement_evenement', 'e2')
->where('e = :evenement')
->setParameter('evenement', $idEvent);
return $qb;
}
The join will do what you were trying to do with your AndWhere I reckon
You cannot use andWhere like that, you have to treat it like you treated your where clause. Declare a parameter, and later on, set it. From what I understand, you'd need to use a subquery for that e.evenements part. Whatever you expect to be in e.evenements part, extract it to a variable, e.g: $evenements and do the following:
$qb->andWhere('e2 IN (:evenements)')
->setParameter('evenements', $evenements, Doctrine\DBAL\Connection::PARAM_INT_ARRAY);
Assuming $evenements is an array. If it's a string, you can explode() it for example.
If you are looking for a quick solution, try this:
$qb = $this->createQueryBuilder('e')
->select('e.id')
->where('e.id = :evenement')
->setParameter('evenement', $idEvent);
$evenementsIds = $qb->getQuery()->getResult(); // This will get you an array of ID's
$qb2 = $this->createQueryBuilder('e2')
->where('e2.id IN (:evenements)')
->setParameter('evenements', $evenementsIds, Doctrine\DBAL\Connection::PARAM_INT_ARRAY);
$result = $qb2->getQuery()->getResult();

Using partial? mysql

I am having trouble in creating a query on a search field. There are two tables I have in my database and when I perform my search functionality I need only the gsNumber as a requirement on the search field.
I got stuck on the query since I need to use partial, and I have a problem on what's needed to select on both tables. I don't get on what's the use of partial.
Here is my code below:
public function getDetails($gsNumber,$page = 1, $limit = 5 ){
$em = $this->getEntityManager();
$query = $em->createQuery(
'SELECT partial a.{ediTransactionId,gsNumber},
partial b.{}
FROM MatrixEdiBundle:Edi997Details b
JOIN a.ediTransaction b
WHERE a.errorCodeId != 1 AND a.gsNumber LIKE :gsNumber
AND b.flag = 1')
->setParameter('gsNumber', "%$gsNumber%")
->setFirstResult(($page-1)*$limit)
->setMaxResults($limit);
$paginator = new Paginator($query, $fetchJoinCollection = false );
$paginator->setUseOutputWalkers(false);
return $paginator;
}

Implicit joins and Where in Doctrine - how?

I have a ManyToMany relation of Users and Roles. That is I have User table and entity class, Role table and entity and a joining table "user_role" width user_id and role_id columns.
Now, I recently tried to get users with their roles, by using joins, like this:
$qb = $this->createQueryBuilder('u')
->join('user_role', 'ur', Join::ON, "I didn't know what to put here, nothing worked ")
Anyway, thanks to this answer I added correct mapping (annotations) to my both entity classes and then removed my own join, letting Doctrine do the job:
$qb = $this->createQueryBuilder('u');
$q = $qb->getQuery();
$users = $q->getResult();
And this works. I have a list of all users, and then I can access their roles (thanks to User->getRoles() method).
However, now I want to list only users having certain roles, for example 'ROLE_ADMIN' and I have no idea how to do this:
$qb = $this->createQueryBuilder('u')
>where('what_to_put_here = :roles')
->setParameter('roles', 'what_to_put_here')
By the way, the SQL code generated by Doctrine looks like this:
SELECT u0_.id AS id_0, u0_.username AS username_1, u0_.personal_name AS personal_name_2, u0_.password AS password_3, u0_.email AS email_4, u0_.is_active AS is_active_5 FROM user u0_
So there is no JOIN. From the Doctrine docs I know this is called "lazy load" - the roles of certain user will be fetched on demand.
But then, how can I do something like this:
SELECT * FROM `user`
JOIN user_role on user_role.user_id = user.id
JOIN role on role.id = user_role.role_id
WHERE role.role_name = 'ROLE_ADMIN'
?
Use this:
$qb = $this->createQueryBuilder('u')
->innerJoin('u.roles', 'r')
->where('r.roleName = :roleNameParameter')
->setParameter('roleNameParameter', 'ROLE_ADMIN');
I'm assuming you mapped the column role_name as property roleName in the entity.

Symfony2 Doctrine, How to fetch only the column names of particular table

Hi i want only the table field names(column names) how to achieve that, as of now i do have the following code -
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('SkerpInventoryBundle:InventoryMaster')->findAllIndex();
I am using the repositories to fetch all the data of the table. Now in "$entities" I am having the result data. Can anyone let me know how to fetch only the field name.
I guess, this is what you need (assume that you are in your controller):
$mappings = $this->getDoctrine()->getManager()->getClassMetadata('AcmeBundle:SomeEntity');
$fieldNames = $mappings->getFieldNames();
You can use DQL (Doctrine Query Language) For this. For example:
$query = $em->createQuery('SELECT u.username FROM CmsUser u');
$users = $query->getResults(); // array of CmsUser username values
echo $users[0]['username'];
For more information on DQL see:
http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html

Sub-queries ActiveRecord Yii

Is it possible to make sub-queries in ActiveRecord in Yii?
i have a query like this:
select * from table1
where table1.field1 in (select table2.field2 from table2)
i'm currently using the fallowing code:
object1::model()->findAll(array('condition'=>'t.field1 in (select table2.field2 from table2)'))
[Edit]
i would like to know if there is a manner to construct the sub-query without using SQL, and without using joins.
Is there any solution ?
and thanks in advance.
First find doublets by db fields:
$model=new MyModel('search');
$model->unsetAttributes();
$criteria=new CDbCriteria();
$criteria->select='col1,col2,col3';
$criteria->group = 'col1,col2,col3';
$criteria->having = 'COUNT(col1) > 1 AND COUNT(col2) > 1 AND COUNT(col3) > 1';
Get the subquery:
$subQuery=$model->getCommandBuilder()->createFindCommand($model->getTableSchema(),$criteria)->getText();
Add the subquery condition:
$mainCriteria=new CDbCriteria();
$mainCriteria->condition=' (col1,col2,col3) in ('.$subQuery.') ';
$mainCriteria->order = 'col1,col2,col3';
How to use:
$result = MyModel::model()->findAll($mainCriteria);
Or:
$dataProvider = new CActiveDataProvider('MyModel', array(
'criteria'=>$mainCriteria,
));
Source: http://www.yiiframework.com/wiki/364/using-sub-query-for-doubletts/
No, there is not a way to programmatically construct a subquery using Yii's CDbCriteria and CActiveRecord. It doesn't look like the Query Builder has a way, either.
You can still do subqueries a few different ways, however:
$results = Object1::model()->findAll(array(
'condition'=>'t.field1 in (select table2.field2 from table2)')
);
You can also do a join (which will probably be faster, sub-queries can be slow):
$results = Object1::model()->findAll(array(
'join'=>'JOIN table2 ON t.field1 = table2.field2'
);
You can also do a direct SQL query with findAllBySql:
$results = Object1::model()->findAllBySql('
select * from table1 where table1.field1 in
(select table2.field2 from table2)'
);
You can, however, at least provide a nice AR style interface to these like so:
class MyModel extends CActiveRecord {
public function getResults() {
return Object1::model()->findAll(array(
'condition'=>'t.field1 in (select table2.field2 from table2)')
);
}
}
Called like so:
$model = new MyModel();
$results = $model->results;
One interesting alternative idea would be to create your subquery using the Query Builder's CDbCommand or something, and then just pass the resulting SQL query string into a CDbCritera addInCondition()? Not sure if this will work, but it might:
$sql = Yii::app()->db->createCommand()
->select('*')
->from('tbl_user')
->text;
$criteria->addInCondition('columnName',$sql);
You can always extend the base CDbCriteria class to process and build subqueries somehow as well. Might make a nice extension you could release! :)
I hope that helps!
I know this an old thread but maybe someone (like me) still needs an answer.
There is a small issues related to the previous answers. So, here is my enhancement:
$model=new SomeModel();
$criteria=new CDbCriteria();
$criteria->compare('attribute', $value);
$criteria->addCondition($condition);
// ... etc
$subQuery=$model->getCommandBuilder()->createFindCommand($model->getTableSchema(),$criteria)->getText();
$mainCriteria=new CDbCriteria();
$mainCriteria->addCondition($anotherCondition);
// ... etc
// NOW THIS IS IMPORTANT
$mainCriteria->params = array_merge($criteria->params, $mainCriteria->params);
// Now You can pass the criteria:
$result = OtherModel::model()->findAll($mainCriteria);

Categories