A Symfony
+ Doctrine
based project uses a User
calls to manage registered users. An additional UserMetadata
class is used to handle all kind of additional information (e.g. last login date, has visited page xy, etc.) about a user.
UserMetadata
has a unidirectional many-to-one relationship to User
(one user can have many linked metadata entries. User
class does not know about the metadata).
class UserMetadata {
...
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $user;
protected $key;
protected $value;
A metadata entry is stored as key/value pair. For example, the date a user last visited a certain page is stored as key='somePageName', value='2020-12-01'
is added. If no entry with key='somePageName'
exists, the user has not visited this page yet.
Goal 1: Create a query which selects all users which have NOT visited a certain page.
Finding the users who HAVE visited a page is no problem using a LEFT JOIN
:
$qb = $this->em->createQueryBuilder();
$qb->select('u')
->from('AppBundle\Entity\User', 'u')
->andWhere('u.someValue = :filter1')
->setParameter('filer1', 'someFilterValueInUserEntity')
->leftJoin(UserSettingsEntry::class, 's', 'WITH', 's.user=u.id')
->andWhere('s.key = :key')
->setParameter('key', 'somePageName');
But how to find users WITHOUT such an entry?
Goal 2: Create a query which selects all users which have NOT visited a certain page, OR where the page was visited more than 6 weeks ago.
Is this possible in the one query?