Doctrine query builder and manytomany - php

I have a simple problem.
I have some users. I have some contacts. Single User can have some Contacts. One Contact may be owned by many Users, a simple ManyToMany relation:
User <-> user_contact <-> Contact
How can I build a query that will return something like all Contacts not owned by a User. Those contacts may be owned by another User or not.

The MEMBER OF option will do the magic.
I think you're looking for something like this:
$em->createQuery("select c from Contract c where :userId NOT MEMBER OF c.Users")
->setParameter("groupId", <<YOUR_USER_ENTITY_OR_USER_ID>>)
->getResult();
Ofcourse I don't know your entities, but I think this will give you some idea.

Related

Laravel/Eloquent - Modeling a HasOne relationship via a BelongsToMany relationship

Say I have four tables:
users
groups
activities
group_activities
Where a group can have any number of activities and an activity can belong to any number of groups through their intermediate table group_activities, and a user belongs to one group via users.group_id. I want to correctly model a relationship between users and activities so that a user can have any one activity, but only if the group that user belongs to has a relation to that activity.
HasOneThrough doesn't seem to work here, since the group the user is related through has multiple activities. HasManyThrough doesn't work since the user can only have one.
I want to properly model this relationship so that it can be picked up for selection automatically via a Nova relationship field, but I'm struggling to figure out exactly how I would do so. My first thought is a HasOneThrough relation with some set of subqueries, but I can't quite piece together where to start.
How would I do this, or conversely, is it possible via Eloquent's automatic relationship system at all?
To ensure we are on the same idea of your relationships:
The relationship between Groups and Activities is a Many To Many relationship (Many To Many - Larvel Documentation).
The group_activities table is the pivot table.
The relationship between users and groups is a One To Many relationship One To Many - Larvel Documentation and the inverse of it One To Many (Inverse) - Larvel Documentation.
To actually answer your question:
If you want to use a shortcut from users to their activities, the Has Many Through is the correct way. If a group can have arbitrary many activities, and a user belongs to one group, the user will be associated to these arbitrary many activities through the group -hence Has Many Through. Note that this is not really a separate relationship though, it's just a convient shortcut.
If you wan't to associate a user with a single Activity directly, you need to to this via a separate One to Many relationship between Users and Activities.
I'm not entirely sure if I interpret your question correctly, so the following is just an assumption, but do you want to ensure a user can only be associated to an activity thats also associated with the user group? So to restrict possible activites by group? If that is the case, you'd simply need to check if the selected activity is in the activities associated with the users group:
With your relationships set up like this:
class User {
public function activity(){
return $this->belongsTo('App\Activity');
}
public function possibleActivities(){
return $this->hasManyThrough('App\Activity','App\Group');
}
}
you can check and associate activities like this:
if( $user->possibleActivities()->contains( $activity ) ){
$user->activity()->associate($activity);
}

Query result as field in Doctrine entity

As part of a login system I have a User entity which I need to add 'Last Login' and 'Total Logins' information to.
I have a couple of tables to represent this, the user table and the user_log table. The user_log table captures other log actions, so I need to select only a specific type (LOGIN).
Basically I need to know how to express the following query in terms of doctrine entities:
SELECT username,
MAX(user_log.log_time) AS last_login,
(SELECT COUNT(id) FROM user_log
WHERE user_log.user_id = user.id
AND user_log.log_action = "LOGIN") AS login_count
FROM user
LEFT JOIN user_log ON user_log.log_action = "LOGIN"
AND user_log.user_id = user.id
I've tried using DQL, the problem is the DQL ran the correct query but it didn't work because I don't know how to create this kind of relationship in doctrine entities.
The only solution I can think of at the moment is to use the query above in a custom repository method and manually create / return the entities. If possible though I'd like to set up the relationships using annotations so that I can fetch this user information using the built in repository methods.
Any help would be greatly appreciated, thanks!

Difference between HABTM relationship and 2 $belongsTo relationship with a third model

I'm creating a project management system which projects are assigned to users
What's the difference between creating a Model ProjectsUser and defining 2 $belongsTo relationship and defining HABTM relationships in both Project and User models? What would be the most correct way, though? And how do I save the data in the projects_users table?
From my experience, if you want to be able to save or delete rows only from the join table (the one with 2 IDs), then it is much more simple using three models associated through both a hasMany and a belongsTo association.
You can also retrieve data from the join table directly and do the queries you want much more easily
This is what CakePHP documentation says refering to HABTM and saving data:
However, in most cases it’s easier to make a model for the join table and setup hasMany, belongsTo associations as shown in example above instead of using HABTM association.
Here you can find more the full text:
http://book.cakephp.org/2.0/en/models/saving-your-data.html#what-to-do-when-habtm-becomes-complicated
I have used this method for a "reads" table (with post_id and user_id) as well as for subscriptions and similar kind of relationships.
The first way is called "hasAndBelongsToMany" [details here].
The second is called "hasMany through" [details here].
The second link relating to "hasMany through" has details and a lengthy explanation about when and why you would want to use it.
Not sure about the specifics of cakephp, but in general defining the relation model explicitly gives you more control over it, for instance if you wanted to do some validation or add callbacks on creation of this relationship.

MVC Complex query and model usage

I have 3 tables.
users,
campaigns,
links.
They have one-to-many relations. User have many campaigns. Campaign has many links.
I calculate top users by counting the total number of links each user have. So I join 3 tables and group by user and select user and sum(links).
This query involves 3 tables. I have already 3 model class for each of these tables. Now my question is in which model should I put this query? should it go in User model (as I call it top10users? Or there is other way to get this info by utilizing already existing 3 models. I want to know what is most suitable from MVC's point of view.
Additional Information
I am using orm in kohana.
Query:
SELECT u.id,
u.name,
SUM(l.num_visited) total_num_visited
FROM users u
JOIN campaigns c
ON ( u.id = c.user_id )
JOIN links l
ON ( c.id = l.campaign_id )
GROUP BY u.id
ORDER BY total_num_visited DESC
LIMIT 10;
There's no strict reason that your model absolutely has to map 1-to-1 with a table. It may make the most sense in this case to provide a model specifically for Top Users, especially because it is dependent on joining data from several related tables.
Then if there is specific business logic related to Top Users that isn't relevant to the standard User class, you can keep it separated and clean. You can always provide helper / factory methods from TopUser that return instances of User, Campaign, or Link if you need to drill down.
I would say go for topusers(). There is no "correct" answer to this question, not in a technical context. But it should be clearly to understand. So if you want to get top users, why would you put such a method in one of the other models than users? Think of a new team member who gets your code: Where would you look for top users when not in the users model first?

Relationship between three entities in Doctrine

I have Doctrine setup with all my tables in my database, and working properly.
I have those three entities: Users, Groups and News
There is a many-to-many relationship between Users and Groups. (I put my users in groups)
There is also a many-to-many relationship between News and Groups. (I give access to a News item to a few Groups)
Database Schema:
I want to get the News that a given User has access to.
Is there an efficient way to do this in Doctrine?
EDIT: I should add that I already had the solution nailed down with a straight SQL query before I started to use Doctrine, I want to know the Doctrine way to do this.
This thread explain the issues about many to many relationships in doctrine.
many-to-many relationship in doctrine
This blog post explain how to handle such events.
http://melikedev.com/2009/12/09/symfony-w-doctrine-saving-many-to-many-mm-relationships/

Categories