this is my relation user entity
#OneToMany(() => DoctorSchedule, doctorSchedule => doctorSchedule.user)
#Field(type => DoctorSchedule)
#JoinColumn({ name: "doctorId" })
doctorSchedules?: DoctorSchedule[];
this is my resolver
#ResolveField((returns) => DoctorSchedule)
#UseGuards(JwtAuthGuard)
doctorSchedules(#Parent() user: User): Promise<DoctorSchedule[]> {
return this.usersService.getDoctorSchedule(user.id);
}
this is my doctor schedule entity
#ManyToOne(() => User, user => user.doctorSchedules)
#Field(type => User, { nullable: true })
user?: User;
this is my rsollver doctor schedule
#ResolveField(returns => User)
// #UseGuards(JwtAuthGuard)
user(#Parent() doctorSchedule: DoctorSchedule): Promise<User> {
return this.doctorScheduleService.getUser(doctorSchedule.doctorId);
}
many to one relation is working like:
query{
doctorSchedules{
day
}user(id:11){
first_name
last_name
}
}
output is good
but one to many is not working like:
query{
user(id:11){
email
first_name
doctorSchedules{
day
}
}
}
its giver me error "Cannot return null for non-nullable field DoctorSchedule.day."
please help me
Make sure you have the relationship in your service
Example:
method() {
return yourRepository.find({ relations: ['doctorSchedules'] });
}
Related
I have 4 tables:
Users with column id
Teams with column id
Roles with column id
Pivot teams_users with columns team_id user_id role_id
Goal: get teams, each team has members. Each member has a role in that team.
My approach:
Fetch teams, then fetch members and roles of that team. Loop the collection, add the role to the correct member, delete the role after.
$teams->each(function($team, $teamKey) use ($teams) {
if(empty($team->members) === false && empty($team->roles) === false) {
$team->members->each(function($member, $memberKey) use ($team) {
$team->roles->each(function($role) use ($member) {
if($member->id === $role->pivot->user_id) {
$member->role = $role;
}
});
});
}
});
My goal:
I want to do it using Eloquent and without looping the collection.
My Team model has two relations:
public function members() {
return $this->belongsToMany(User::class, "teams_users", "team_id", "user_id")->withPivot("role_id")->withTimestamps();
}
public function roles() {
return $this->belongsToMany(Role::class, "teams_users", "team_id", "role_id")->withPivot("user_id")->withTimestamps();
}
expected output should be like this:
{
teams: [
{
id: 1,
title: "Awesome team",
members: [
{
id: 1
name: "Test",
role: {
id: 1,
title: "Admin"
}
}
]
}
]
}
Your help is much appreciated.
I'm trying to access a property from the many-to-many relationship model. But NestJS's GraphQL implementation won't let me. I've tried already IntersectionType, creating a custom type, ...
But everything gives me:
throw new TypeError();
^
TypeError:
at Reflect.getMetadata...
Example:
export class Model1{
#Field(() => ID)
#PrimaryKey
#Column
id: string;
#BelongsToMany(() => Model2, () => Relation )
others: (Game & { Relation : Relation })[];
}
export class Model2{
#Field(() => ID)
#PrimaryKey
#Column
id: string;
#BelongsToMany(() => Model1, () => Relation )
others: (Game & { Relation : Relation })[];
}
export class Relation {
#ForeignKey(() => Model1)
#Field({ nullable: true })
#Column
model1Id: string;
#ForeignKey(() => Model2)
#Field({ nullable: true })
#Column
model2Id: string;
#Column
some_property: string
}
How would you setup your graphql properties so I can access the some_property from the relation object?
I can access it in code. But I can't seem to setup the graphql attributes so I can query them.
I want to filter my data, base on a method on my model:
method in my model:
// . . .
public function isBatched(): bool
{
return $this->rows()->count() > 1;
}
and my qraphql:
type Invoice
{
globalId: ID! #globalId #method(name: "getKey")
localId: Int! #method(name: "getKey")
pdfUrl: String #method(name: "getPdfUrl")
number: String
poNumber: String #rename(attribute: "po_number")
deposit: Deposit #hasOne
rows: [InvoiceRow!] #hasMany
bills: [Bill!] #belongsToMany(type: "paginator", relation: "bills")
isBatched: Boolean! #method(name: "isBatched")
isCompleted: Boolean #method(name: "isPaid")
dueDate: DateTime #rename(attribute: "due_date")
total: Money #method(name: "totalAmountMoney")
}
extend type Query {
invoices: Invoice! #paginate #cache
invoicesb(isBatched: Boolean #eq): [Invoice]! #paginate
}
but it does not work, it says isBatched filed is not exist, any idea?
#eq directive works for column's databases, not for your model's method. So, one thing you can do is to use Eloquent's scopes, like
class Invoice extends Model
{
// ...
public function scopeIsBatched(Builder $query, bool $isBatched): Builder
{
// Find the way to filter by your relationship count.
// So far, I think something like:
return $query->withCount('rows')->where('rows_count', '>', 1);
}
}
Then, your schema will be like
extend type Query {
invoicesb(isBatched: Boolean #scope): [Invoice]! #paginate
}
the right way:
public function scopeIsBatched(Builder $query, bool $isBatched): Builder
{
if ($isBatched) {
return $query->withCount('rows')->having('rows_count', '>', 1);
}
return $query;
}
I think this question is similar to this one, however I also think my use case is slightly different.
I am successfully able to update a pivot table using updateExistingPivot when a single user exists; however instead of referencing the FK on the pivot table, I need to reference the id.
I have three tables: users, roles and role_user.
users
id|name|email
roles
id|title
role_user
id|active|user_id|role_id
For example, if I have two users in my application, the users table would look like:
id: 1|name: foo|email: fooexample#email.com
id: 2|name: bar|email: barexample#email.com
My roles table looks like this:
id: 1|title: fizz
id: 2|title: buzz
id: 3|title: bang
Each user is given 3 roles by default. So my role_user table looks like this:
id: 1|active: true|user_id: 1|role_id: 1
id: 2|active: true|user_id: 1|role_id: 2
id: 3|active: true|user_id: 1|role_id: 3
id: 4|active: true|user_id: 2|role_id: 1
id: 5|active: true|user_id: 2|role_id: 2
id: 6|active: true|user_id: 2|role_id: 3
Because updateExistingPivot looks at the FK to decide what to update, everything works great with a single user. However, when I have duplicate user_id and/or role_id FK's things start to fall apart. Instead of looking at the FK, I need to be able to look at the id in my pivot table.
I am passing my roles to a vue component from my controller like this:
// Get the roles(s) that belong to the user.
$roles = $user->roles
->sortByDesc('title')
->toJson();
I am rendering the list on screen, and when a user clicks a role, they can update it's status:
...
async handleRoleClick(event, role) {
console.log('updating role: ', role);
try {
let response = await axios.patch(`/my-path`, {
active: !this.active,
id: role.pivot.id,
});
// data getting passed is correct.
// active: false
// id: 5 <-- the id of the pivot table, not a FK value
if (response.status === 200) {
console.log('response.data', response.data);
this.active = response.data.role.pivot.active;
console.log('active: ', this.active);
} else {
console.error('Error: could not update role. ', response);
}
} catch (error) {
console.error('Error: sending patch request. ', error);
}
},
...
My update method in my controller looks like this:
$attributes = request()->validate([
'active' => 'required',
'id' => 'required',
]);
// Get the authenticated user.
$user = auth()->user();
// Update the roles' status in the pivot table.
$user->roles()->updateExistingPivot($attributes['id'], $attributes);
// Get the role that was just updated via the relationship.
$role_with_pivot = $user->roles()->where('role_user.id', $attributes['id'])->first();
return response()->json(['role' => $role_with_pivot], 200);
The data I am sending in my request headers is correct. I am not getting any errors, however my pivot table is not getting the values I am passing to it. I assume it's because I am not correctly sending the id. In my example above it would be id: 5. Because there isn't a user_id of 5 or role_id of 5, Laravel isn't sure what to do.
How can I tell Laravel to look at the id of the pivot table, and not a foreign key?
The way I am doing it though seems kind of sketchy. I'd be really interested to see if there is a more "Laravel way" of doing this. Everything else is above is the same, here is what my update method on my controller looks like.
controller
public function update(Request $request, Role $role)
{
$attributes = request()->validate([
'active' => 'required',
'id' => 'required',
]);
// Get the authenticated user.
$user = auth()->user();
// Get the requested role (row) from the pivot table.
$role = $user->roles()->where('role_user.id', $attributes['id'])->first();
// Update the requested role.
$role->pivot->active = $attributes['active'];
// Save the requested role.
$role->pivot->save();
// Get the role that was just updated via it's relationship.
$role_with_pivot = $user->roles()->where('role_user.id', $attributes['id'])->first();
return response()->json(['role' => $role_with_pivot], 200);
}
You should retrieve role id in you View instead of pivot primary key, and use role_id to update pivot table.
As stated your user has multiple roles, but only one combination of role and user id.
async handleRoleClick(event, role) {
console.log('updating role: ', role);
try {
let response = await axios.patch(`/my-path`, {
active: !this.active,
id: role.id, //change this
});
// data getting passed is correct.
// active: false
// id: 5 <-- the id of the pivot table, not a FK value
if (response.status === 200) {
console.log('response.data', response.data);
this.active = response.data.role.pivot.active;
console.log('active: ', this.active);
} else {
console.error('Error: could not update role. ', response);
}
} catch (error) {
console.error('Error: sending patch request. ', error);
}
},
it's late, but might help some artisans in the future.
You may use DB method directly or create a dedicated model/entity for that table.
e.g
DB::table('role_user')->where('id', $id);
or
RoleUser::find($id);
class ModelA {
public function modelB()
{
return $this->hasMany(ModelB::class);
}
}
class ModelB {
public function modelC()
{
return $this->hasMany(ModelC::class);
}
}
class ModelC {
public function modelD()
{
return $this->hasMany(ModelD::class);
}
}
class ModelD {
//has column status_changed_date
}
I have $modelA = ModelA::find($id);
ModelA have multiple ModelB, ModelB have multiple ModelC, ModelC has multiple ModelD.
Now I want update status_changed_date for all matching records.
Is there any better way to do this. I have refered https://laravel.com/docs/5.7/eloquent-relationships#updating-many-to-many-relationships
but couldn't find out a solution.
Please help to solve this.
$modelAs = ModelA::with('modelB.modelC.modelD')->find($id)
before you can use that way :
$modelA->modelB->each->modelC->each->modelC->each->update([
'field' => 'value'
]);
or reduce values to ids, this only made one query :
$ids = [];
$modelA->modelB->each->modelC->each->modelC->each(function ($c) use($ids) {
$ids[] = $c->id;
});
ModelC::whereIn('id', $ids)->update([
'field' => 'value'
});
if each->modelC->each is not working, use method notation
Instead of making all this update, make one common table of common fields and directly update that table.
For more
Laravel Polyformic relationships