I'm facing some issues in establishing relationships amongst User, Clan, and Clan Member models. I have three models in which I have defined the relationship as...
Clan model
public function clanMembers() {
return $this->hasMany('App\ClanMember', 'clan_id', 'clan_id');
}
ClanMember model
public function clan() {
return $this->belongsTo('App\Clan', 'clan_id', 'clan_id');
}
I am trying to get Clan details of a requested user and his other Clan Members. I am using the following:
$clanMembers = ClanMember::find(Auth::user()->id)->clan()->with('clanMembers')->get();
From the above, I am getting the response correct.
"data": [
{
"id": 2,
"clan_leader_id": 3,
"clan_name": "#rockers1",
"clan_avatar": "",
"game_id": 1,
"max_members_count": 50,
"clan_id": "1505ccd15b01",
"created_at": "2019-05-04 04:31:44",
"updated_at": "2019-05-04 04:31:44",
"clan_leader_name": ""
"clan_members": [
{
"id": 2,
"user_id": 2,
"clan_id": "1505ccd15b01",
"role_id": 2,
"status": 0,
"created_at": "2019-05-04 04:33:03",
"updated_at": "2019-05-04 04:33:03"
}
]
}
]
Now I want to establish a relationship between the User and Clan model which has id and clan_leader_id as a foreign key to get clan_leader_name from User table in Clan model and user_name in place of user_id in clan_members. Clan member has user_id and id with the user as a foreign key.
Check out many-to-many relationships. Your models/tables should be: User, Clan, and ClanUser, where clan_user is an intermediate pivot table containing clan_id and user_id.
Your Clan model should contain the following relationship
public function users()
{
return $this->belongsToMany('App\User');
}
And your User model should contain the following relationship
public function clans()
{
return $this->belongsToMany('App\Clan');
}
To get a list of clans for a user:
$clans = User::find($userId)->clans()->get();
To get a list of users for a clan:
$users = Clan::find($id)->users()->get();
Related
Hi, there I'm fairly new to laravel-lighthouse. I've read the documentation but unfortunately, there is no detail about this issue. My question is How can I query more than one pivot table. I have an Item table that belongs to many other Models.
The code is given below.
class Item extends Model
{
public function provisions(): BelongsToMany
{
return $this->belongsToMany(Pwmp::class,
'project_wise_material_provision_items', 'item_id', 'provision_id')
->withPivot('qty', 'unit_cost')
->withTimestamps()
->as('provision_items');
}
public function procurements(): BelongsToMany
{
return $this->belongsToMany(Pwpp::class,
'project_wise_procurement_plan_items', 'item', 'procurement')
->withTimestamps()
->as('procurement_items')
->withPivot('qty', 'unit_cost');
}
public function log_sheets(): BelongsToMany
{
return $this->belongsToMany(Braols::class,
'bid_receiving_and_opening_log_sheet_items', 'item', 'braols')
->withTimestamps()
->as('log_sheet_items')
->withPivot('qty', 'unit_cost', 'tax');
}
public function workshop(): BelongsToMany
{
return $this->belongsToMany(TransformerWorkshop::class,
'transformer_workshop_items', 'item', 'workshop')
->as('workshop_items')
->withTimestamps()
->withPivot('qty', 'flow', 'type');
}
public function sub_office(): BelongsToMany
{
return $this->belongsToMany(MaterialReceiptInSubOffice::class,
'material_receipt_in_sub_office_items', 'item', 'receipt')
->as('sub_office')
->withTimestamps()
->withPivot('id','qty', 'type');
}
Here is my GraphQL schema
type Item{
id: ID!
workshop_items: [TransformerWorkShopItemsPivot]
provision_items: [ProjectWiseMaterialProvisionItem]
sub_office: MaterialReceiptInSubOfficeItemsPivot
}
type MaterialReceiptInSubOfficeItemsPivot{
qty: Int
type: Int
id: ID
}
type ProjectWiseMaterialProvisionItem {
qty: String
unit_cost: String
}
type TransformerWorkShopItemsPivot{
qty: Int
type: Int
flow: Int
}
Now when i query the api
```graphql
material_receipt_in_sub_office_store(id: 4){
id
items{
id
provision_items{
unit_cost
qty
}
sub_office{
type
id
qty
}
}
}
}
```
it returns the following result
{
"data": {
"material_receipt_in_sub_office_store": {
"id": "4",
"items": [
{
"id": "431",
"name": "Drill Machine",
"image": "crane2.jpg",
"category_id": {
"id": "993"
},
"provision_items": null,
"sub_office": {
"type": null,
"id": null,
"qty": null,
"__typename": "MaterialReceiptInSubOfficeItemsPivot"
}
},
I am unable to fetch the multiple pivot table data.
however, if I query pivot it returns the data of only one pivot.
First, it looks like you don't use Laravel model's relationships into your type definition.
By specifying a #belongsToMany / #hasMany directive (see more here) you'll be able to optimize your queries.
type Item{
id: ID!
workshop_items: [TransformerWorkShopItemsPivot] #hasMany(relation: "workshop")
provision_items: [ProjectWiseMaterialProvisionItem] #hasMany(relation: "provisions")
sub_office: MaterialReceiptInSubOfficeItemsPivot #hasMany
}
I'm just not sure about the fact you give table aliases in your relation definition..
Then, by doing the query, you can fetch as much pivot relations as you want. Never got relation problems by doing this.
Please Correct me if I am wrong.
I have two models "Users" and "Profiles"
Scenario 1:
In the "Profiles" model I have defined "user_id" as primary key and foreign key to "users.id"
class Profile extends Model
{
/**
* primary key
*/
protected $primaryKey = 'user_id';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id', 'country'
];
at schema.graphql
type Mutation {
upsertProfile(user_id: ID, country: String): Profile #upsert
}
type Profile {
user_id: ID!
country: String
user: User #belongsTo
}
Let's suppose there is an id 28 in users table. When I try to run mutation:
mutation {
upsertProfile(user_id: 28, country: "India") {
country
}
}
It works fine and updates the country, but if there is no user_id 28 exists, as per definition it should create one.
As it defines the user_id column is not an auto-increment column
I did one more test
Scenario 2:
I removed 'user_id' as the primary key and added the id column as the primary key and auto-increment.
Let suppose id 1 is there, then after running the mutation:
mutation {
upsertProfile(id: 1, country: "India") {
country
}
}
I got the expected result.
But when I try to run mutation
mutation {
upsertProfile(user_id: 28, country: "India") {
country
}
}
I am getting duplicates of result with new id everytime(auto-increment) whenever I ran this mutation.
My question,
How to use upsert if user_id exists then update the row, else create a row.
As laravel createOrUpdate function prototype contains checking on multiple columns to get a row updated, is there any way to do the same on upsert directive.
BTW, at scenario 1 I debugged query and found that insert query is running but I am getting an exception at the grpahql-playground result
{
"errors": [
{
"debugMessage": "No query results for model [App\\Models\\Profile] 0",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"upsertProfile"
],
....
]
Make sure the ID attribute is fillable/unguarded.
In my case it was a timestamp issue. I put this line of code in my model and problem was solved
public $timestamps = false;
I have a Many to Many relationship between User and Project. I am trying to list a users projects but can't access the child fields in a view:
Models
// Project
public function users() {
return $this->belongsToMany('App\User')->withTimestamps();
}
// User
public function projects() {
return $this->belongsToMany('App\Project')->withTimestamps();
}
Intermediate table: project_user
user_id, project_id, timestamps
Controller
$projects = User::with('projects')->where('id', auth()->user()->id)->get();
return view('home')->with('projects', $projects);
View
#foreach($projects as $project)
- {{ $project->name}}
<br>
#endforeach
This returns no errors and no results
If I try $projects->projects as $project I get "projects" not available to this collection.
If I return $projects in the controller I get:
[
{
"id": 1,
"first": "User",
"last": "Name",
"organization": "Organization",
"phone": "5555555555",
"email": "test#example.com",
"created_at": "2018-03-22 20:16:20",
"updated_at": "2018-03-22 20:16:20",
"projects": [
{
"id": 10,
"name": "Project One for User One",
"description": "Project Description",
"created_at": "2018-03-22 20:16:20",
"updated_at": "2018-03-22 20:16:20",
"pivot": {
"user_id": 1,
"project_id": 10,
"created_at": "2018-03-22 20:16:20",
"updated_at": "2018-03-22 20:16:20"
}
},
...
How can I access the child fields name and description?
First, you do not have to query for the user, as it is already authenticated. If you use something like the Debugbar package, you can see that it will query the user for the current session.
So, to fetch the currently authenticated user, you can simply use:
$user = auth()->user(); // you can als use this in the view if you want.
In the controller, your code:
$projects = User::with('projects')->where('id', auth()->user()->id)- >get();
Will do a query to fetch all users with id = auth()->user()->id and it will eagerload all projects of those users (<- plural !!!).
So the $projects variable contains all the users with that id and it will attach all the projects in a subsequent query. Hence it is giving you an array of user objects, instead of the projects that you want. Which makes sense, since you are querying the User table.
Personally, I would do something like this in the controller:
$user = auth()->user();
$projects = $user->projects->get(); // doing this here will allow you to change get() to paginate() if you want.
return ('home')->with(['projects' => $projects]); // < either use compact as in the docs, or an associative array
Now in the view $projects will contain a Collection of projects, not users, and you can simply do:
#foreach($projects as $project)
- {{ $project->name}}
<br>
#endforeach
I have the following tables
users
id
books
id
favourite_books
id
user_id (FK)
book_id (FK)
I have the following Model:
class User {
public function favouriteBooks()
{
return $this->belongsToMany(Book::class, 'favourite_books');
}
}
I want to get all the ids that belong to a user.
The way I am doing this currently is like so:
$user->favouriteBooks()->select('book_id')->get();
However this returns data like so;
[
{
"book_id": 23,
"pivot": {
"user_id": 57,
"book_id": 23
}
},
{
"book_id": 41,
"pivot": {
"user_id": 57,
"book_id": 41
}
},
...
]
I want it to return data like so:
[
23,
41,
...
]
How can I do that?
I recommend putting pivot in the hidden array like in user.php:
protected $hidden = ['pivot'];
which would remove pivot from all json's returned.
Use the pluck() method:
$user->favouriteBooks()->pluck('book_id');
Or :
$user = User::where('id',1)->with('favourite_books')->first();
$fbs = [];
foreach($user->favourite_books as $book) {
$fbs[] = $book['book_id'];
}
unset($user->favourite_books);
$user->favourite_books = $fbs;
return $user;
Problem details:
I have three models
a Directorate with id and name fields,
an Employee with id and name fields and
a Telephone with id, tel, employee_id, directorate_id, description and type fields. The employee_id may be nullable, that is there are telephones stored in database with employee_id = null
The models are related as follows:
an employee may have many telephones
a directorate, may have many telephones
class Directorate extends Model
{
public function telephones()
{
return $this->hasMany(Telephone::class);
}
public function employees()
{
return $this->hasMany(Employee::class);
}
}
class Employee extends Model
{
public function telephones()
{
return $this->hasMany(Telephone::class);
}
public function directorate()
{
return $this->belongTo(Directorate::class);
}
}
class Telephone extends Model
{
public function employee()
{
return $this->belongsTo(Employee::class);
}
public function directorate()
{
return $this->belongsTo(Directorate::class);
}
}
Question:
I want to fetch a Collection of all the Telephone models that belong to a specific Directorate, that have employee_id = null and also having their directorate relation eager loaded. In addition, from that resulting collection of Telephone models, I need only some of the models' fields, that is id, tel and description
Tries
What I tried so far was the following:
I created a query scope in the Telephone model:
public function scopeHaveNoEmployeeId($query)
{
return $query->where('telephones.employee_id', '=', null);
}
In my controller
$myTelephones = Telephone::with('directorate')
->haveNoEmployeeId()
->where('directorate_id', $directorateId)
->get(['id', 'tel', 'description']);
However what I am receiving are the requested fields of the filtered models without the relation eager loaded, for instance:
[
{
"id": 79,
"tel": "0648136867",
"directorate": null
},
{
"id": 380,
"tel": "0223796011",
"directorate": null
}
]
I tried also to lazy eager load the relation afterwards but with no luck.
Finally I noticed that if I request all the Telephone models fields, the relation will eager load as I request. For example:
$myTelephones = Telephone::with('directorate')
->haveNoEmployeeId()
->where('directorate_id', $directorateId)
->get();
Then as a result:
[
{
"id": 79,
"tel": "0648136867",
"directorate": {
"id": 23
"name": "Some name"
}
},
{
"id": 380,
"tel": "0223796011",
"directorate": {
"id": 23
"name": "Some name"
}
}
]
Your telephone does not have any relationship with the directorate model.
put this in your Telephone model.
public function directorate()
{
return $this->belongsTo(Directorate::class);
}
Actually, after digging into Laravel's details for a while, I noticed that my initial question was out of context and somewhat silly. I was first eager loaded a relationship and then fatuously I filtered out the relationship by not including it in get() parameters. I had just to do the following:
$myTelephones = Telephone::with('directorate')
->haveNoEmployeeId()
->where('directorate_id', $directorateId)
->get(['id', 'tel', 'description', 'directorate']);