I have tables:
users
- id
- name
- company_id
companies
- id
- company_name
watched_objects
- id
- user_id
- object_id
- type
Now I want to get all watched companies for a user.
So query should looks:
SELECT
companies.*
FROM companies
JOIN watched_objects ON watched_objects.object_id = companies.id
WHERE watched_objects.user_id = 1
How should I define relations?
I try this:
class User
{
public function watched()
{
return $this->hasManyThrough('App\Company', 'App\WatchedObject', 'user_id', 'id');
}
}
But query is:
SELECT
companies.*,
watched_objects.user_id
FROM companies
INNER JOIN watched_objects ON watched_objects.id = companies.id
WHERE watched_objects.user_id = 1
How I can change watched_objects.id to watched_objects.object_id.
If your treating object_id as company id, then the relation is considered to be many to many. Then table watched_objects will be the third table kept the relation of user and company.
class User {
public function watched() {
return $this->belongsToMany('App\Company', 'watched_objects', 'user_id', 'object_id');
}
}
In order to find the watched companies of user 1, you can use the following code.
$watched_companies = User::find(1)->watched;
To get all watched companies by a user you can do like this:
$watches=WatchedObject::where(['user_id'=>Auth::user()->id])->with('company')->get();
foreach($watches as $watch)
{
print_r($watch->company->company_name);
}
Relation:
Company hasMany watched objects:
public function watches()
{
return $this->hasMany('App\WatchedObject','object_id');
}
and belongsTo in watchedObject Model:
public function company()
{
return $this->belongsTo('App\Company','object_id');
}
Related
Let me explain the scenario.
i have tables:
competitions
id title body
then
books
id name user_id
then i have a pivot table to store participants
so
participants
id competition_id user_id
Now i have set some relationships for these models.
Competition model
public function participants()
{
return $this->belongsToMany('App\User');
}
User model
public function participatedCompetitions()
{
return $this->belongsToMany('App\Competition');
}
Now i am fetching one single competition and in that same query i need to fetch a list of books of the participants of that competition.
So how can i achieve this.
Thanks.
Here is how you get all the books:
$userIds = $competition->participant()->get()->pluck('id');
// $userIds is your collection of User Ids that is participant in that compititions.
$books = Book::whereIn('user_id',$userIds)->get();
I have a website build in Laravel.
I have two tables - Groups and Group members.
For each group_member, the row in the table has id, group_id and user_id.
The groups have a name and a description.
When a user joins a group, a row is created in the group_member table.
But I now need to get the groups that a user is part of.
So if I have user_id = 5, I need to get all the rows in group_member where user_id = 5, and then get the corresponding group, so I can query the groups.
I need to do something like $groups = Groups::whereGroup_member ...
But I cant query the model like that, because in Groups there is no where it specificies who the members are, it is just the group details - the members are specificed in group_member table.
How do I get the groups, which a member is part of using the laravel query standards?
In your User.php Model
public function group_member(){
return $this->hasMany(GroupMember::class,'user_id','id;);
}
In your GroupMember.php Model
public function group(){
return $this->belongsTo(Group::class,'group_id','id');
}
Your query will be
$users = User::with('group_member.group')->find($user_id);
You should use Many-to-Many relation:
class Group
...
public function members() {
return $this->belongsToMany(User::class); // Users (members) that belongs to Group
}
class User
...
public function groups() {
return $this->belongsToMany(Group::class, 'group_member', 'user_id', 'group_id'); // Groups that User belongs to
}
And at controller, when You have user id:
$groups = User::where('id', $user_id)->groups;
More about this written at official docs: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
I have the following tables:
user_details
id - PK
user_name
user_email
cities
id - PK
city_name
regions
id - PK
region_name
city_id - FK(cities)
user_region (Many to Many)
user_id
region_id
And these are the models:
User
public function regions()
{
return $this->belongsToMany('App\Regions', 'user_region', 'user_id', 'region_id');
}
Regions
public function cities()
{
return $this->belongsTo('App\Cities');
}
public function users()
{
return $this->belongsToMany('App\User', 'user_region', 'region_id', 'user_id');
}
Cities
public function regions()
{
return $this->hasMany('App\Regions', 'city_id', 'id');
}
I need to get the city name for a user. Which relation can I use here to do this?
According to your comment:
A city can have many regions. And a user can work in many regions. But, the user will only work in a single city.
As all regions which user belongs to will belong to only one city you can do as follow:
$user = User::find(1);
$city = $user->regions()->first()->cities;
echo $city->city_name;
A Venue has many Subscriptions.
A Subscription has many Subscribers (User).
Theres a pivot table, containing the relation between user_id and subscription_id.
How can I get all Subscribers from a Venue?
I have tried with:
class Venue {
/**
* Members
*/
public function members() {
return $this->hasManyThrough('App\User', 'App\Subscription');
}
}
But it fails with MySQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.subscription_id' in 'on clause' (SQL: select `users`.*, `sub
scriptions`.`venue_id` from `users` inner join `subscriptions` on `subscriptions`.`id` = `users`.`subscription_id` where `
users`.`deleted_at` is null and `subscriptions`.`venue_id` = 1)
How my Subscription model look:
`Subscription`
class Subscription extends Model {
protected $table = 'subscriptions';
/**
* Subscripers
*/
public function subscribers() {
return $this->belongsToMany('App\User');
}
/**
* Venue
*/
public function venue() {
return $this->belongsTo('Venue');
}
}
Simple question: Why are you using a third model for Subscriptions? It sounds like a normal n:m relation between User and Venue, as already written in the comments above.
class User {
public function venues() {
return $this->belongsToMany('App\Venue');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User');
}
}
This constellation actually needs three tables, which are (i gave each model a column name):
users
- id
- name
venues
- id
- name
user_venue
- user_id
- venue_id
But to access the relations, you can simply use the Eloquent magic:
// List of all venues (as Venue models) that are in relation with User with id $id
$venues = User::find($id)->venues()->get();
// Returns the alphabetically first user that has a relation with Venue with id $id
$user = Venue::find($id)->users()->orderBy('name', 'asc')->first();
If you need to store additional information in the pivot table (e.g. when the relation has been established), you can use additional pivot fields:
user_venue
- user_id
- venue_id
- created_at
class User {
public function venues() {
return $this->belongsToMany('App\Venue')->withPivot('created_at');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User')->withPivot('created_at');
}
}
// Returns the date of the relations establishment for the alphabetically
// first Venue the User with id $id has a relation to
$created_at = User::find($id)->venues()->orderBy('name', 'asc')->first()->pivot->created_at;
I've never tried to do whatever you are trying to do there, because it seems (with the current information) conceptually wrong. I also don't know if it is possible to set up an own model for a pivot table, but I think it should work if the pivot table has an own primary id column. It could probably be helpful if you've a third model that needs to be connected with a connection of two others, but normally that doesn't happen. So try it with pivot tables, like shown above, first.
Alright, I still don't see a good use case for this, but I can provide you a query that works. Unfortunately I wasn't able to get an Eloquent query working, but the solution should be still fine though.
class Venue {
public function members($distinct = true) {
$query = User::select('users.*')
->join('subscription_user', 'subscription_user.user_id', '=', 'users.id')
->join('subscriptions', 'subscriptions.id', '=', 'subscription_user.subscription_id')
->where('subscriptions.venue_id', '=', $this->id);
if($distinct === true) {
$query->distinct();
}
return $query;
}
}
The relation can be queried just as normal:
Venue::find($id)->members()->get()
// or with duplicate members
Venue::find($id)->members(false)->get()
I have 3 tables
type
type_id
person
person_id
category
category_id
table_name
table_id
person_id
In category I have connections of different tables/models with Type model, So if I have want to get type_id connected with person with person_id = 23 the query should look like this:
SELECT * FROM category WHERE table_name='person' AND table_id = 23
In my Person model I defined relationship with Type this way:
public function groups()
{
return $this->belongsToMany('Type', 'category',
'table_id', 'type_id')->wherePivot( 'table_name', '=', 'person' );
}
When I want to get those types and I use:
$person->groups()->get()
The query looks like this:
select `type`.*, `category`.`table_id` as `pivot_table_id`, `category`.`type_id` as `pivot_type_id` from `type` inner join `category` on `type`.`type_id` = `category`.`type_id` where `category`.`table_id` = '23' and `category`.`table_name` = 'person';
so it seems to be correct.
But I would like to use sync() for synchronizing types with persons and here's the problem.
When I use:
$person->groups()->sync('1' => ['table_name' => 'person']);
I see the query that gets all records from category to use for sync looks like this:
select `type_id` from `category` where `table_id` = '23';
so it doesn't use
`category`.`table_name` = 'person'
condition so synchronization won't work as expected.
Is there any simple way to solve it or should I synchronize it manually?
You should use Eloquents polymorphic relations (http://laravel.com/docs/4.2/eloquent#relationships)
class Category extends Eloquent {
public function categorizable()
{
return $this->morphTo();
}
}
class Person extends Eloquent {
public function categories()
{
return $this->morphMany('Category', 'categorizable');
}
}
Now we can retrieve catgories from person:
$person = Person::find(1);
foreach ($person->categories as $category)
{
//
}
and access person or other owner from category:
$category = Category::find(1);
$categorizable_model = $category->categorizable; //e.g. Person
I can confirm that it was a bug in Laravel 5 commit I used. I've upgraded for Laravel 5 final version and now query is generated as it should.