symfony querybuilder query need to write - symfony

I have the following tables in mysql with given relationships and same has been define in the symfony2. I want to achieve the following query which I wrote it down below. can some one help me how can I write it in querybuilder?
unitids(id,unitid,databaseid)
Mappaths(id,ref_unitid2(forigen key for unitids id) ,ref_unitid1 (forigen key for unitids id),nomal value)
traveltime(id,ref_map_path(forigen key for mappaths id), traveltime,noobjs,ondate)
my mysql query is like this :
SELECT t.ID,t.ondate, un.databaseid as source1,
un1.databaseid as desitnation, t.traveltime, t.noobjs
FROM test.traveltime t
left join test.mappaths p on t.ref_map_path = p.ID
left join test.unitids un on (p.ref_unitids1 = un.id )
left join test.unitids un1 on (p.ref_unitids2= un1.id)
where un.databaseid=50 and un1.databaseid =1 limit 1;
which give me each one row of source and destination of and objects etc like this :
in symfony2 when i run this query
$query = $em->createQueryBuilder();
$results = $query->select('un.databaseid,un1.databaseid')
->from('ApiMapBundle:Traveltime', 't')
->leftJoin('t.refMapPath', 'p')
->leftJoin('p.refUnitids2', 'un')
->leftJoin('p.refUnitids1', 'un1')
->where('un.databaseid = :bdatabaseid1')
->setParameter('bdatabaseid1', 2)
->andwhere('un1.databaseid = :bdatabaseid2')
->setParameter('bdatabaseid2',1)
//->setMaxResults(1)
->getQuery()
->getResult();
it give me output like
Array ( [0] => Array ( [databaseid] => 1 ) [1] => Array ( [databaseid] => 1 ))
but instead it should give me
Array ( [0] => Array ( [databaseid] => 1 ) [1] => Array ( [databaseid] => 2 ))
How can i achieved this above output?????

Assumed that you are writing code in Repository and you also defined relations in your Entities
$em = $this->getEntityManager();
$query = $em->getRepository('BUNDLE:traveltime')->createQueryBuilder('t');
$query->select('t.Id,..')
->leftJoin('t.ref_map_path','p')
->leftJoin('p.ref_unitids1','un')
->leftJoin('p.ref_unitids2','un1')
->where('un.databaseid = :bdatabaseid')
->setParameter('bdatabaseid',1)
->orWhere('un1.databaseid = :bdatabaseid1')
->setParameter('bdatabaseid1',2);

Related

DQL access id from object property with left join

I realized this sql which works without problems
SELECT meeting.name, meeting.date, community.name, participation.isPresent, participation.user_id
FROM meeting
INNER JOIN community
ON meeting.community_id = community.id
AND community.is_active = 1
LEFT join participation
ON meeting.id = participation.meeting_id
AND participation.user_id = 1078
WHERE meeting.date >= CURRENT_DATE()
ORDER BY meeting.date DESC
I'm trying to reproduce it with the doctrine query builder but I never got the right result. The user id part doesn't seem to be part of the leftJoin function but is applied to the request globally, which is not what I want.
public function getNextMeetings()
{
$qb = $this->createQueryBuilder('m')
->select('m.name AS meeting, m.date, c.name AS community, p.isPresent', 'IDENTITY(p.user) AS user')
->innerJoin('m.community', 'c')
->where('c.isActive = true')
->leftJoin('m.participations', 'p')
//->leftJoin('p.user', 'u')
//->where('u.id = 1078 OR u.id IS NULL')
//->where('IDENTITY(p.user) = 1078')
->andWhere('m.date >= CURRENT_DATE()')
->orderBy('m.date', 'DESC');
return $qb->getQuery()->execute();
}
My comments are what I tried to fix this issue.
Check Working with QueryBuilder: High level API methods
More precisely, the definition od leftJoin() function:
public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null);
You can place a condition on the joined Entity by:
use Doctrine\ORM\Query\Expr;
->leftJoin('m.participations', 'p', Expr\Join::WITH, 'p.user = :userId')
->setParameter('userId', 1078)
Note you do not need a condition for "meeting.id = participation.meeting_id", as this is autoapplied by the relation m.participations to the join constructed.

Update randomly certain number of rows

I'm trying to update a certain number of rows of my entity "Vehicule". I have no idea how could it work.
I'm actually trying to modify only two rows where direction= 5.This is the function I used in order to update.
public function ValidAction(\OC\UserBundle\Entity\User $direction) {
$qb = $this->getDoctrine()
->getRepository('CarPfeBundle:Vehicule')
->createQueryBuilder('v');
$q = $qb->update ('CarPfeBundle:vehicule v')
->set('v.direction', '?1')
->where('v.direction = ?2')
->setParameter(1, $direction)
->setParameter(2, 5)
->getQuery();
$p = $q->execute();
return $this->redirect($this->generateUrl('demandeveh_afficher'));
}
But the above code update all rows of my database. I need to update only two rows. Any help please?
Try to do this ;
public function ValidAction(\OC\UserBundle\Entity\User $direction) {
$qb = $this->getDoctrine()
->getRepository('CarPfeBundle:Vehicule')
->createQueryBuilder('v');
// $ids an array that contains all ids with your condition
$ids = $qb->select('v.id')
->where('v.direction = :direction')
->setParameter(
array(
'direction' => $direction
)
)
->getQuery()
->getResult();
$id1 = $ids[array_rand($ids)];
$id2 = $ids[array_rand($ids)];
//To be sure that $id1 is different from id2
while ($id1 == $id2) {
$id2 = $ids[array_rand($ids)];
}
$q = $qb->update ('CarPfeBundle:vehicule v')
->set('v.direction', ':val1')
->where('v.direction = :val2')
->andWhere('v.id IN (:id1, :id2)')
->setParameter(
array(
'val1' => $direction ,
'val2' => 5 ,
'id1' => $id1,
'id2' => $id2,
)
)
->getQuery();
$p = $q->execute();
return $this->redirect($this->generateUrl('demandeveh_afficher'));
}
With the above code I hope you can update only two rows and randomly.
Good luck !
While a solution like Houssem Zitoun suggested may work, why not use a subquery?
If you get the (like I did, if not, just skip the middle SELECT)
Error: #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
go with this answer and something like (doc): - untested
UPDATE CarPfeBundle:Vehicule v
SET v.direction = ?1
WHERE v.direction IN
(SELECT * FROM (
SELECT v.direction
FROM CarPfeBundle:Vehicule v2
WHERE v.direction = ?2 LIMIT 2
)) AS sq

ZF2 Doctrine with Symfony < OR null query

How do I write this "WHERE" condition in a way which is compatible with Doctrine?
( ( `translations_es_google`.`translation_date` < `translations_masters`.`translation_date` ) OR ( `translations_es_google`.`translation_date` is null ) )
What I have tried (unsuccessfully) are:
$query1
->andWhere('((t.translationDate < m.translationDate) OR (t.translationDate is NULL))');
$query1
->andWhere('(t.translationDate < m.translationDate) OR (t.translationDate is NULL)');
Table alias for the Doctrine query are
t represents the table translations_es_google
m represents the table translations_masters
When I remove this "andWhere" condition the rest of the QueryBuilder query executes as expected.
The query I am trying to execute is
SELECT
`translations_masters`.`translation_key` , `translations_masters`.`text_domain` , `translations_masters`.`translation_date`
FROM
`translations_masters`
LEFT JOIN
`translations_es_google` ON ( ( `translations_masters`.`text_domain` = `translations_es_google`.`text_domain` ) AND ( `translations_masters`.`translation_key` =`translations_es_google`.`translation_key` ) )
WHERE
`translations_masters`.`language_iso` NOT LIKE 'es-Google' AND ( ( `translations_es_google`.`translation_date` < `translations_masters`.`translation_date` ) OR ( `translations_es_google`.`translation_date` is null ) )
GROUP BY
`translations_masters`.`translation_key` , `translations_masters`.`text_domain`
ORDER BY
`translations_masters`.`translation_date` ASC
As requested the QueryBuilder version of this query is:
$query1 = $this->entityManager
->createQueryBuilder()
->select('m.textDomain , m.translationKey , m.translationDate , m.translationDate AS translationMasterDate , t.translationDate')
->from(
'AMDatabase\Entity\TheVerse\Translations' . $explode1 . $explode2,
't'
)
->leftJoin(
'AMDatabase\Entity\TheVerse\TranslationsMasters',
'm',
Join::WITH,
'(m.textDomain = t.textDomain) AND (m.translationKey = t.translationKey)'
)
->groupBy('m.textDomain , m.translationKey')
->orderBy(
'm.translationDate',
'ASC'
)
->setMaxResults('1');
$query1
->andWhere(
$query1->expr()
->notLike(
'm.languageIso',
':languageIso'
)
)
->setParameter(
'languageIso',
$value
);
$query1->andWhere(
$query1->expr()->orX(
't.translationDate < m.translationDate',
't.translationDate IS NULL'
)
);
$result1 = $query1->getQuery()
->getArrayResult();
The output of $query1->getQuery()->getSQL() is
SELECT
t0_.text_domain AS text_domain_0, t0_.translation_key AS translation_key_1, t0_.translation_date AS translation_date_2, t0_.translation_date AS translation_date_3, t1_.translation_date AS translation_date_4
FROM
thev1010_theverseoftheday.translations_es_google t1_
LEFT JOIN
thev1010_theverseoftheday.translations_masters t0_ ON ((t0_.text_domain = t1_.text_domain) AND (t0_.translation_key = t1_.translation_key))
WHERE
t0_.language_iso NOT LIKE ? AND (t1_.translation_date < t0_.translation_date OR t1_.translation_date IS NULL)
GROUP BY
t0_.text_domain, t0_.translation_key
ORDER BY
t0_.translation_date ASC
LIMIT 1
The ? value is 'es-Google'
The output of $query1->getQuery()->getDQL(); is
SELECT
m.textDomain , m.translationKey , m.translationDate , m.translationDate AS translationMasterDate , t.translationDate
FROM
AMDatabase\Entity\TheVerse\TranslationsEsGoogle t
LEFT JOIN
AMDatabase\Entity\TheVerse\TranslationsMasters m WITH (m.textDomain = t.textDomain) AND (m.translationKey = t.translationKey)
WHERE
m.languageIso NOT LIKE :languageIso AND (t.translationDate < m.translationDate OR t.translationDate IS NULL)
GROUP BY
m.textDomain , m.translationKey
ORDER BY
m.translationDate ASC
The ? value is 'es-Google'
How about orX expression?
You can try it this way:
$query1->andWhere(
$query1->expr()->orxX(
't.translationDate < m.translationDate',
't.translationDate IS NULL'
)
);
orX gives you the ability to add multiple conditions, separated by comma.
You can also separate your orX condition to its own variable and pass everything added to it to andWhere condition.

search with Doctrine if blank field

i have written a DQL query for my multiple search,working fine if i specify the all fields but if i keep one of the field blank it won't show me the result
$query = $em->createQuery
('SELECT d FROM EntityBundle:Doctor d WHERE d.name =:name AND d.degree =:degree AND d.area = :area_id AND d.sex = :sex AND
(
( YEAR(d.dob) BETWEEN :d2 AND :d1 ) OR
( YEAR(d.dob) BETWEEN :e2 AND :e1 ) OR
( YEAR(d.dob) BETWEEN :f2 AND :f1 )
)' )
->setParameter('name', $name)
->setParameter('degree', $degree)
->setParameter('area_id', $area)
->setParameter('sex', $sex)
->setParameter('d1', $this->p1)
->setParameter('d2', $this->p2)
->setParameter('e1', $this->q1)
->setParameter('e2', $this->q2)
->setParameter('f1', $this->r1)
->setParameter('f2', $this->r2)
->getResult();
i have tried setParameter('name', (is_null($name)? "IS NULL" : $name)) also but still there is no luck..
You can use QueryBuilder instead of DQL
$qb = $qb->select('d');
if($name !== null) {
$qb = $qb->where('d.name = :name')->setParameter(...);
}
...
$qb->getQuery()->getResult();

doctrine dql exception: Illegal offset type in /var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php line 601

I want to produce a DQL for following MySQL query:
SELECT * FROM `folders` AS `t` WHERE `t`.`Library` = #myLib AND AND `t`.`Id` NOT IN (
SELECT DISTINCT(`f`.`Id`) FROM `folders` AS `f` JOIN `folders` AS `ff` ON (`f`.`Position` LIKE CONCAT(`ff`.`Position`, '%')) WHERE `ff`.`Active` = 1 AND `ff`.`Library` = #myLib AND `f`.`Library` = #myLib
)
ORDER BY `t`.`Position` ASC
The query works fine in mySQL and returns correct records.
To generate DQL I've tried both below options:
1.
$query = $em->createQuery("SELECT F FROM MyBundle:Folders T WHERE T.Library = :libid AND T.id NOT IN (
SELECT DISTINCT(F.id) FROM MyBundle:Folders F JOIN MyBundle:Folders FF WITH F.Position LIKE CONCAT(FF.Position, '%') AND F.Library = :libid AND FF.Library = :libid AND FF.Active = true
) ORDER BY T.Position ASC")
->setParameter('libid', $library);
$result = $query->getResult();
2.
$q1 = $this->createQueryBuilder('F')
->select('DISTINCT(F.id)');
$q1->join('\MyBundle\Entity\Folders', 'FF', 'WITH', $q1->expr()->like('F.Position', $q1->expr()->literal('CONCAT(FF.Position, \'%\')')))
->where('FF.Active = true')
->andWhere("FF.Library = '$library'")
->andWhere("F.Library = '$library'");
$q2 = $this->createQueryBuilder('T');
$q2->where('T.Library = :libid')
->andWhere($q2->expr()->notIn('T.id', $q1->getDQL()))
->setParameter('libid', $library)
->orderBy('T.Position', 'ASC');
$result = $q2->getQuery()->getResult();
In my perspective it seems OK but I don't know why in both ways it produce following exception:
ContextErrorException: Warning: Illegal offset type in
/var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php line 601
Any help will be appreciated.
It seems no one has an answer for this. I found a temporary solution as below (I call it temporary because I'm changing my unique query to two separate queries and it seems the issue is in core of doctrine).
$qb = $this->createQueryBuilder('F')
->select('DISTINCT(F.id)');
$qb->join('\MyBundle\Entity\Folders', 'FF', 'WITH', 'F.Position LIKE CONCAT(FF.Position, \'%\')')
->where('FF.Active = true')
->andWhere("FF.Library = :library")
->andWhere("F.Library = :library")
->setParameter('library', $library);
$included_folders = $qb->getQuery()->getArrayResult();
$query = $this->createQueryBuilder('F')
->where('F.Active = false')
->andWhere('F.Library = :library')
->setParameter('library', $library)
->orderBy('F.Position', 'ASC');
if (!empty($included_folders)) {
if (count($included_folders) > 1)
{
foreach ($included_folders as $index => $value)
{
if (is_array($value))
{
$included_folders[$index] = !empty($value['id']) ? $value['id'] : $value[1];
}
}
$query->andWhere($query->expr()->notIn('F.id', $included_folders));
}
else {
$query->andWhere('F.id != :folder ')
->setParameter('folder', $included_folders[0]);
}
}
$result = $query->getQuery()->getResult();
As you see instead of getting the dql from my first query and putting it inside my second dql in notIn section which will lead to the warning message, I execute the first query and get the results then put the results inside notIn if amount of returned values are more than one, otherwise it should be in regular !=. This solved my problem for now, but as you see amount of transactions are now increased
If anyone has a better solution or any fix for the warning I will be thankful.
I've encountered the same error and it seems that this has been fixed in latest trunk of Doctrine/ORM.
Using "2.5.*#dev" as version in your composer.json for doctrine/orm should fix this bug and will let you do what you want in a single query.

Resources