Relationship between a hasMany and belongsToMany in Laravel - php

I have two Models - InternalNotesThread and InternalNotes
class InternalNotesThread extends Model {
public function notes(){
return $this->hasMany('App\InternalNotes', 'thread_id', 'id');
}
}
class InternalNotes extends Model {
public function thread() {
return $this->belongsTo('App\InternalNotesThread');
}
public function users()
{
return $this->belongsToMany('App\User', 'user_notes_tagged', 'internal_notes_id', 'user_id');
}
}
Also, InternalNotes is mapped to User with a relation of belongsToMany.
DB Structure:
internal_notes_thread:
id - int
ticket_id (FK) - int
name - string
internal_notes:
id - int
thread_id (FK) - int
notes - string
user_notes_tagged: (Many to many with internal_notes and User)
internal_notes_id (FK) - int
user_id (FK) - int
For every note, there might be some user tagged in it.
How can I directly relate this relationship with the internal_notes_thread???
I get the data with this:
$data = InternalNotesThread::with('notes')->where('ticket_id', '=', $id)->get()->toArray();
But, in the notes array, I am not able to get the users tagged in that note
How can I get all the data in one go???

You're not eager loading the users, so they don't show up in your ->toArray() array.
Try this:
$data = InternalNotesThread::with('notes.users')
->where('ticket_id', '=', $id)
->get()
->toArray();

Related

How to get all the people in table 1 without getting the people who have me as parent_id in table 2?

I'm writing this post because I have a problem with my relationships on Laravel.
Here is the structure I currently have:
1st table:
- id
- name
- ...
2nd table :
- parent_id
- child_id
knowing that parent_id and child_id correspond to the same table. Here is the function that links them
public function relation()
{
return $this->belongsToMany('App\Person', 'person_relations', 'parent_id', 'child_id', 'id', 'id');
}
Currently I would like, for a search system, to get all the people in table 1 without getting the people who have me as parent_id in table 2.
I have added an inverse relation parents() to the People model instead of the relation() method in the question.
Person Model :
public function parents()
{
return $this->belongsToMany('App\Models\Person', 'person_relations', 'child_id', 'parent_id', 'id', 'id');
}
Controller :
public function test()
{
$myId = 1;
$persons = \App\Models\Person::whereDoesntHave('parents')
->orWhereHas('parents', function($qry) use($myId){
$qry->where('person_relations.parent_id', '!=', $myId);
})
->get();
}
This method will return all records which doesn't have a given $myId as their parent id.
Tested and working in Laravel 6.2 and 7.29

Laravel belongsTo not working even with specific FK

I use Laravel 5.3.
I have 2 tables and 2 models (ad and category) :
Model ad :
----------------
class Ad extends Model
{
protected $table = 'ads';
protected $primaryKey = 'ad_id';
public function category()
{
return $this->belongsTo(Category::class, 'cat_id', 'cat_id');
}
}
And
Model category :
-----------------
class Category extends Model
{
protected $table = 'categories';
protected $primaryKey = 'cat_id';
public function ads()
{
return $this->hasMany(Ad::class);
}
}
And my DB structure is :
ads:
ad_id -
ad_name
ad_status
cat_id
categoriess:
cat_id -
cat_name
I really don't know why, but I can't get the relation between using this (in my repository):
return $this->model
->select('ad_id', 'ad_name')
->where('ad_status', '=', 1)
->with('category');
The query is fine, I got ad information, but the relation is empty. I checked, the cat_id exists in both tables.
Did I miss something ?
You need to add cat_id key to select() to make it work:
return $this->model
->select('ad_id', 'ad_name', 'cat_id')
->where('ad_status', 1)
->with('category')
->get();
If you'll not add this key, relation will be always null. Also, use get() to get the data.

Laravel 5.3 hasManyThrough through an intermediate table

I have the following table relationship:
organizations
id - integer
organization_users
organization_id - integer (FK)
user_id - integer (FK)
users
id - integer
I am trying to get all the users of an organization through eloquent relationships. Here is my Organization.php model with its relationships:
class Organization extends Model
{
public function Users(){
return $this->hasManyThrough('App\User', 'App\OrganizationUser',
'organization_id', 'user_id', 'id');
...
}
I have tried many combinations of that relationship such as
return $this->hasManyThrough('App\User', 'App\OrganizationUser',
'user_id', 'organization_id', 'id');
But all turn up somewhat the same error (this one is from the first query):
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not
found: 1054 Unknown column 'organization_users.id' in 'on clause' (SQL: select
`users`.*, `organization_users`.`organization_id` from `users` inner join
`organization_users` on `organization_users`.`id` = `users`.`user_id` where
`organization_users`.`organization_id` = 1)'
Is it possible that I can have the relationship retrieve the user_id to query on the users table instead of Laravel trying to retrieve organization_users.id? If not is there another way around this?
This is many to many relationship.
User Model:
public function organizations()
{
return $this->belongsToMany('App\Organization','organization_users');
}
Organization Model:
public function users()
{
return $this->belongsToMany('App\User','organization_users');
}
To, get all the users with their organizations:
$users=User::with('organizations')->get();
foreach($users as $user)
{
print_r($user->name);
foreach($user->organizations as $organization)
{
print_r($organization->name);
}
}
What you are describing looks like it may be a 'Many-to-Many' relationship.
https://laravel.com/docs/5.3/eloquent-relationships#many-to-many

HasManyThrough with another relationship in Laravel 5.2

I have 3 models:
Tournament, Category, Team
A Tournament hasMany Category
A Category hasMany Team
Tables:
Tournament: Only attributes
Category: id, tournament_id, name
Teams: id, category_id, name
I would like to get all teams from a tournament by: $tournament->teams
I tried :
public function teams()
{
return $this->hasManyThrough(Team::class,CategoryTournament::class);
}
Then I need an extra relation of my team: team->category->name;
but the result of this HasManyThrough has no relationship....
Any Idea???
In Category model :
public function team ()
{
return $this->hasMany('App\Teams');
}
In Teams model :
public function category ()
{
return $this->belongsTo('App\Category', 'category_id');
}
I think should be like this, Try.
According to laravel documentation :
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
With this you can add relationship :
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id');
}

Has many through

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()

Categories