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.
Related
Context:
Foo has items (polymorphic many-to-many relationship), my pivot model is Itemables, and itemables have type (one-to-many relationship.)
Every time I need a Foo, I also need its items (itemables) and the itemable type Model (not to be confused with itemable_type property).
The problem:
When I query for an individual itemable, everything works fine, I get the type (not only type_id).
But when I query for the Foo, I just get the type_id, not the type model (example results below).
Example results:
Individual itemable (it works fine): Itemable::find(2)
App\Models\Itemable {#4903
id: 2,
itemable_type: "App\Models\Foo",
itemable_id: 2,
item_id: 6,
quantity: "386.85",
type_id: 5,
type: App\Models\Type{#4969 // This is what I want
id: 5,
name: "something",
}
}
Foo (it doesn't get the App\Models\Type): Foo::find(2)
App\Models\Foo {#4853
id: 2,
name: "Aut autem tenetur.",
user_id: 1,
items: Illuminate\Database\Eloquent\Collection {#4916
all: [
App\Models\Item {#4898
id: 2,
name: "Quaerat sint eaque.",
user_id: 1,
pivot: App\Models\Itemable {#4891
id: 2,
itemable_type: "App\Models\Foo",
itemable_id: 2,
item_id: 6,
quantity: "386.85",
type_id: 5,
// Where is my App\Models\Type, Laravel??? <<--------------
},
},
// more items...
Models and relations:
class Foo extends Model
{
protected $fillable = [
'name',
'user_id',
];
protected $with = ['items'];
public function items() {
return $this->morphToMany(Item::class, 'itemable')
->using(Itemable::class)
->withPivot('quantity', 'type_id')
->withTimestamps();
}
}
class Itemable extends MorphPivot
{
protected $table = 'itemables';
public $incrementing = true;
protected $fillables = [
'item_id',
'quantity',
'type_id',
];
protected $with = ['type']; // This doesn't work when query Foo
public function type() {
return $this->belongsTo(Type::class);
}
}
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.
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'] });
}
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'm trying to create a social-network like feature in an app I'm building, and Want to associate a Friend with another Friend.
Assume I have this:
Friend:
connection: doctrine
tableName: friend
columns:
id:
type: integer(8)
primary: true
autoincrement: true
name:
type: string(75)
notnull: true
How do I create a many to many relationship to associate Friend with itself?
Thanks ahead of time for your help..
Use self-referencing equal nest relations.
From the docs:
Equal Nest Relations
Equal nest relations are perfectly
suitable for expressing relations
where a class references to itself and
the columns within the reference class
are equal.
This means that when fetching related
records it doesn't matter which column
in the reference class has the primary
key value of the main class.
The previous clause maybe hard to
understand so lets take an example. We
define a class called User which can
have many friends. Notice here how we
use the 'equal' option.
// models/User.php
class User extends BaseUser
{
public function setUp()
{
parent::setUp();
// ...
$this->hasMany('User as Friends', array(
'local' => 'user1',
'foreign' => 'user2',
'refClass' => 'FriendReference',
'equal' => true,
)
);
}
}
// models/FriendReference.php
class FriendReference extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('user1', 'integer', null, array(
'primary' => true
)
);
$this->hasColumn('user2', 'integer', null, array(
'primary' => true
)
);
}
}
Here is the same example in YAML format. You can read more about YAML in the YAML Schema > Files chapter:
---
# schema.yml
# ...
User:
# ...
relations:
# ...
Friends:
class: User
local: user1
foreign: user2
refClass: FriendReference
equal: true
FriendReference:
columns:
user1:
type: integer
primary: true
user2:
type: integer
primary: true