Symfony query on intermediate table - sql

I have a ManyToMany relation between guest and event. The intermediate table is events.
This sql query is working in PHP My Admin :
SELECT *
FROM guest AS G
LEFT JOIN guest_event AS E ON event_id = G.id
I'm trying to do the same query with the querybuilder, and tried this:
$query = $this->createQueryBuilder('g')
->leftJoin('g.events', 'e', 'WITH', 'e.id = :id')
->addSelect('e');
but I get no results! Does anyone have a solution?

Or try this:
$id = 1; // Your event id
$repository = $this->getDoctrine()
->getRepository('AcmeDemoBundle:Entity');
$query = $repository->createQueryBuilder('g')
->select('e')
->leftJoin('g.events', 'e', 'WITH', 'e.id = :id')
->setParameter('id', $id)
->getQuery();
$events = $query->getResult();
Read the docs about Using Doctrine's Query Builder in Symfony

You don't have entity reference
Probably something like this would do it:
$query = $this->createQueryBuilder()
->select('e')
->from('MyBundle:Guest', 'g')
->leftJoin('g.events', 'e', 'WITH', 'e.id = :id');

Related

transform SQL to createQueryBuilder

I'm trying to transform this sql
SELECT * FROM user_account
LEFT JOIN brand ON user_account.id = brand.user_id_id
LEFT JOIN influencer ON user_account.id = influencer.user_id_id'
to a createQueryBuilder, I try this but it's not working
$qb = $this->createQueryBuilder('u')
->from(Brand::class, 'brand')
->from(Influencer::class, 'influencer')
->leftJoin('brand', 'b', 'ON', 'u.id = b.user_id_id')
->leftJoin('influencer', 'i', 'ON', 'u.id = i.user_id_id');
$query = $qb->getQuery();
return $query->execute();
And I got this error
[Semantical Error] line 0, col 42 near 'brand b ON u.id': Error: Class
'brand' is not defined.
Someone can help?
Many thanks
I have never used doctrine query builder, but after reading the docs I would suggest the following solution:
$qb = $this->createQueryBuilder()
->from('user_account', 'u')
->leftJoin('u', 'brand', 'b', 'u.id = b.user_id_id')
->leftJoin('u', 'influencer', 'i', 'u.id = i.user_id_id')
$query = $qb->getQuery();
return $query->execute();
NOTE: I left b.user_id_id as it is in your example, even though I think there is a typo. Maybe this should mean b.user_id. The same for influencer.

TYPO3 Extbase Join

I'm try to make this query with extbase work:
SELECT a.*
FROM tx_apartments_domain_model_apartment a
LEFT
JOIN tx_apartments_domain_model_booking b
ON b.apartment = a.uid
AND b.start <= '2018-07-23'
AND b.end >= '2018-07-21'
WHERE b.uid IS NULL AND a.hidden=0 AND a.deleted=0;
the following code does not work, i get an empty result:
/** #var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_apartments_domain_model_apartment');
$statement = $queryBuilder
->select('a.*')
->from('tx_apartments_domain_model_apartment','a')
->leftJoin(
'a',
'tx_apartments_domain_model_booking',
'b',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('b.apartment','a.uid'),
$queryBuilder->expr()->lte('b.start', '2018-07-23'),
$queryBuilder->expr()->gte('b.end', '2018-07-21')
)
)
->where(
$queryBuilder->expr()->isNull('b.uid')
)
->execute();
//DebuggerUtility::var_dump($queryBuilder->getSQL());
return $statement->fetchAll();
can anybody help me?
What kind of records do you expect to get?
as uid is a mandantory field you never have records where the uid is NULL.
If you want to access new records which are not stored to the database yet: they get a faked uid like NEW123
This works for me:
/** #var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_apartments_domain_model_apartment');
$queryBuilder
->getRestrictions()
->removeAll();
$statement = $queryBuilder
->select('a.*')
->from('tx_apartments_domain_model_apartment','a')
->leftJoin(
'a',
'tx_apartments_domain_model_booking',
'b',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('b.apartment','a.uid'),
$queryBuilder->expr()->lte('b.start', $queryBuilder->createNamedParameter('2018-07-23')),
$queryBuilder->expr()->gte('b.end', $queryBuilder->createNamedParameter('2018-07-21'))
)
)
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->isNull('b.uid'),
$queryBuilder->expr()->eq('a.hidden',0),
$queryBuilder->expr()->eq('a.deleted',0)
)
)
->execute();
$results = $statement->fetchAll();
// DebuggerUtility::var_dump($queryBuilder->getSQL());
// DebuggerUtility::var_dump($results);
return $results;
I do not know where exactly you are using this code. Typically I would think that retrieving records from the database should happen in a repository.
If you are using this in the ApartmentRepository and if there is a relation properly configured between apartments and bookings (1:n, I would assume) in the TCA, then you could use something like this:
public function findInDateRange ($dateConstraint)
{
$query = $this->createQuery();
$constraints = [];
$constraints[] = $query->lessThanOrEqual(
'bookings.start',
$dateConstraint['start']
);
$constraints[] = $query->greaterThanOrEqual(
'bookings.end',
$dateConstraint['end']
);
$query->matching($query->logicalAnd($constraints));
return $query->execute();
}
I deliberately left out the b.uid IS NULL part here, as that should always return nothing since uid should be AUTO_INCREMENT. Unless the default query settings are changed, there is also no need to check the disable fields (hidden, deleted) manually.
Note that in order for this to work, the Apartment Domain Model needs a field bookings with a corresponding column in the database (that is something I stumbled over last year).
As a side-note: Is it intentional that you allow for the end to be before the start in your query (start: 2018-07-23, end: 2018-07-21), or is that just exemplary?

Yii db command and CDbCriteria

I have two tables Products(id, name) and Views(id,count,time), and those two tables are not related to each other. This is my code:
$dbCommand = Yii::app()->db->createCommand("
SELECT P.`id`, P.`name`, V.`time`
FROM `products` P, `views` V
WHERE P.`type` = 2
ORDER BY V.`time` DESC
");
$data = $dbCommand->queryAll();
It is working, but I want to convert this query to CDbCriteria syntax.
$cdb = new CDbCriteria();
$cdb->select = //???
$cdb->where = //???
$cdb->order = //???
How can I do this? Can somebody help me?
You cannot use CDbCriteria, Try using query builder.
Yii::app()->db->createCommand()
->select('P.id, P.name, V.time')
->from('products P, views V')
->where('P.type = :type')
->order('V.time DESC')
->queryAll(array(
':type' => 2
));

Symfony createquery with union

I need to execute the next query with symfony :
$qb = $this->_em;
$query = $qb->createQuery(
'SELECT f1.friend1
FROM AppBundle:Friend f1
WHERE f1.friend2 = ?1
UNION
SELECT f2.friend2
FROM AppBundle:Friend f2
WHERE f2.friend1 = ?2
'
)->setParameters(array(1 => $user_id, 2 => $user_id));
When i execute this $query, i have this error : Expected end of string, got 'UNION'.
How can i do ?
Edit for my new code :
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
$rsm->addEntityResult('Project\MyBundle\Entity\Friend', 'f');
$rsm->addFieldResult('f', 'friend1', 'friend1');
$rsm->addFieldResult('f', 'friend2', 'friend2');
$rsm->addFieldResult('f', 'id', 'id');
$rsm->addFieldResult('f', 'state', 'state');
$sql = "SELECT f1.friend1 AS friend
FROM friend f1
WHERE f1.friend2 = ?
UNION
SELECT f2.friend2 AS friend
FROM friend f2
WHERE f2.friend1 = ?";
$result = $this->_em->createNativeQuery($sql, $rsm)
->setParameter(1, $user_id)
->setParameter(2, $user_id)
->getResult();
return $result;
This is my new query. I have test this query directly on phpmyadmin, and i have a return. But with this code, i have empty in $result
UNION is not supported in doctrine instead you can use Doctrine\ORM\Query\ResultSetMapping; this will map your resultset to the entity which you defined to use by the native query like $rsm->addEntityResult('Namespace\yourBundle\Entity\Friend', 'f');
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
$rsm->addEntityResult('Namespace\yourBundle\Entity\Friend', 'f');
$rsm->addFieldResult('f', 'friend', 'friend1');
$sql = "SELECT f1.friend1 AS friend
FROM friend_table f1
WHERE f1.friend2 = ?
UNION
SELECT f2.friend2 AS friend
FROM friend_table f2
WHERE f2.friend1 = ?";
$result = $DM->createNativeQuery($sql, $rsm)
->setParameter(1, $user_id)
->setParameter(2,$user_id)
->getResult();
Edit from comments
Not advisable solution due to lack of information why using union but the answer for question in comments below you can do so to map fields,but remember this will give you the duplicates
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
$rsm->addEntityResult('Project\MyBundle\Entity\Friend', 'f');
$rsm->addFieldResult('f', 'friend1', 'friend1');
$rsm->addFieldResult('f', 'friend2', 'friend2');
$rsm->addFieldResult('f', 'id', 'id');
$rsm->addFieldResult('f', 'state', 'state');
$sql = "SELECT f1.id,f1.friend1 AS friend,f1.friend1,f1.friend2 ,f1.state
FROM friend f1
WHERE f1.friend2 = ?
UNION
SELECT f2.id,f2.friend2 AS friend,f2.friend1,f2.friend2 ,f2.state
FROM friend f2
WHERE f2.friend1 = ?";
$result = $this->_em->createNativeQuery($sql, $rsm)
->setParameter(1, $user_id)
->setParameter(2, $user_id)
->getResult();
Edit 2 i just want an array with one field "friend", with friend1 in one case, and friend2 in another
For the above you asked you can run two queries using your entity
$DM = $this->getDoctrine()->getEntityManager();
$result1=$DM->getRepository('Namespace\yourBundle\Entity\Friend')
->findBy(array('friend2'=>$user_id));
$result2=$DM->getRepository('Namespace\yourBundle\Entity\Friend')
->findBy(array('friend1'=>$user_id));

How to get particular column in zend using Left join

I am new to zend framework,
Following is the plain mysql query which takes particular column from table,
SELECT jobs_users.id,jobs_users.first_name from jobs_users left join friends on jobs_users.id=friends.friend_id where friends.member_id=29
I tried with zend to implement the above query like below,
public function getFriendsProfileList($id){
$db = Zend_Db_Table::getDefaultAdapter();
$select = $db->select();
$select->from('jobs_users')
->joinLeft(
'friends',
'jobs_users.id=friends.friend_id',
array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo')
)
->where("friends.member_id = ?", $id);
$result = $db->fetchAll($select);
return $result;
}
Here i got result with all column name , not with exact column name which i have given in query.
Kindly help me on this.
Use this instead:
$select->from('jobs_users', array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo'))
->joinLeft('friends', 'jobs_users.id=friends.friend_id')
->where("friends.member_id = ?", '20');
You may also try this:
$select = $db->select();
$select->setIntegrityCheck(false);
$select->joinLeft('jobs_users','',array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo'));
$select->joinLeft('friends','jobs_users.id=friends.friend_id', array());
$select->where("friends.member_id = ?", $id);
$result = $db->fetchAll($select);
return $result;