views:

62

answers:

2

Hello,

Currently this function works : it displays for a specific game, how many jobs there are.

The problem : If there is no job, the game does not appear on the list.

How to display the game even if there is no job attached ?

Thanks

public function getWithGames()
    {
        $q = $this->createQuery('c')
            ->leftJoin('c.stJob j')
            ->where('j.expires_at > ?', date('Y-m-d h:i:s', time()))
            ->addOrderBy('c.name');

        $q->andWhere('j.is_activated = ?', 1);
        $q->andWhere('j.is_public = ?', 1);


        return $q->execute();
    }
+4  A: 

Your conditions should be part of the LEFT JOIN ... ON clause.

$q = $this->createQuery('c')
    ->leftJoin('c.stJob j WITH j.expires_at > ? AND j.is_activated = 1 AND j.is_public = 1', date('Y-m-d h:i:s', time()))
    ->addOrderBy('c.name');

Putting conditions in the ON clause (as opposed to the WHERE) indicates that they apply specifically to the JOIN. If no rows satisfy those conditions, there is no join — and that's just what you want in this case. Putting them in the WHERE indicates that the result rows must satisfy those conditions. And obviously if there was no join, you can't satisfy any conditions about the j table.

VoteyDisciple
i think this really doesnt matter as its a left join anway. so no matter where the condition is applied. but look what he defines as the problem. if there is no job, it is not listed. so he wants a joined valiues where (the job attributes public and activated are 1) OR (both are NULL) ... (which happens if there is no job). the last part is what he forgot
Joe Hopfgartner
It matters immensely. Doing an `OR ... stuff is NULL` is not at all desirable. The very purpose of the `ON` clause is that those are the conditions ***used to establish the join***. If no rows match those conditions, there is no join — and in the case of a LEFT JOIN that's fine. Trying to mimic an `ON` clause with manually-written "stuff is NULL" conditions is ugly. I hope that's not the reason for a downvote here.
VoteyDisciple
that is totally true. gave you an upvote for this :) what i didn't like was that it isnt the problem in his code. the problem in his code was a purely semantic problem of not understanding what a left join actually does.
Joe Hopfgartner
+1 btw ..............
Joe Hopfgartner
thank you, the ON fixed the problem. I'll know that for the future.
Tristan
A: 
$q->andWhere('j.is_activated = ?', 1);
$q->andWhere('j.is_public = ?', 1);

if there is no job its is_activated and is_public field cant be 1. it will be null so you need something like: where (j.is_activated = 1 and j.is_activated = 1) or (j.is_activated = IS NULL and j.is_activated IS NULL) ...

i am not familiar with what librar you are using to construct this query but i guess it could work like this:

public function getWithGames()
    {
        $q = $this->createQuery('c')
            ->leftJoin('c.stJob j')
            ->where('j.expires_at > ?', date('Y-m-d h:i:s', time()))
            ->addOrderBy('c.name');

        $q->andWhere('(j.is_activated = ? AND j.is_public = 1) OR (j.is_activated IS NULL  AND j.is_publicIS NULL )', 1);

        return $q->execute();
    }

this is not pretty... but as i said i dont know your library. you could probably pass an array of arguments or do something like "orWhere...." blabla...

the way it is done is also clumsy and could be done better. use the conditions directly to establish the join! that way you avoid ahving the whole tables combined and afterwards filtered...

Joe Hopfgartner