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
Related
I have a model Article (id, title, content, created_at).
I can do:
$articles = Article::orderBy('created_at','DESC')->skip($start)->take($length)
->get(['id', 'title', 'content', 'created_at']);
But I want to get 2 random additional articles for each article . How can I do it?
For example:
{
{
id: 1,
title: 'title1'
content: 'qwqwqwqwqwqwqwq',
created_at: '2022-11-25 14:04:35',
related: {
id: 77,
title: 'title77'
content: 'fhhhfh',
created_at: '2022-11-26 17:04:57',
},
{
id: 15,
title: 'title15'
content: 'kkkkkkkk',
created_at: '2022-11-27 15:04:45',
},
},
...
}
Since get() method of Eloquent's Builder returns a collection (Check here), You can use map() method to add random items you mentioned.
Article::orderBy('created_at','DESC')->skip($start)->take($length)
->get(['id', 'title', 'content', 'created_at'])->map(function ($articles){
$articles['related'] = Article::inRandomOrder()->take(2)->get();
return $articles;
});
You can just simple assign the related articles in a loop:
foreach ($articles as $article) {
$article->related = $articles->whereNotIn('id', [$article->id])->random(2)->values();
}
If you want to load the related articles by relationship, you can create a column named related_id in article table and set default value to 1
Then, create a relationship on Article model:
public function related(){
return $this->hasMany(Article::class, 'related_id', 'related_id');
}
Then, you can load the related articles by using with function (remember to add related_id to the array of get function):
$articles = Article::orderBy('created_at','DESC')->with(['related' => function($query){
$query->inRandomOrder()->take(2);
}])->skip($start)->take($length)->get(['id', 'title', 'content', 'created_at', 'related_id']);
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.
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'] });
}
Let's assume this simple relation:
class Thing
belongs_to :user # Not embedded!
end
And this simplified aggregation on Thing where we want to get the user object:
{ :$match => { ... } },
# Get user from belongs_to relation
{ :$lookup => {
from: 'users',
localField: 'user_id',
foreignField: '_id',
# Always has one element, because it's a belongs_to relation
as: 'user'
} },
In an aggregation there are two ways of replacing a field with the first element of an array.
With addFields and arrayElemAt:
{ :$addFields => { user: { :$arrayElemAt => ['$user', 0] } } }
With unwind (assuming one element in the array):
{ :$unwind => { path: '$user' } }
Question: I prefer the unwind, since it looks cleaner, but saw people using the first approach quite often. Is it faster or the "better practice"?
I've a many to many relation (user and account). In the user entity, I've private property groups (array collection).
When I try to validate this property (groups) with a simple "NotBlank", it's not work. So I try this below (collection and choice).
I read this http://symfony.com/fr/doc/2.3/reference/constraints/Choice.html
and this http://symfony.com/fr/doc/2.3/reference/constraints/Collection.html but it doesn't work or I don't correctly use them.
Can anybody gives me some help ?
/* USER accounts property
...
/**
* #ORM\ManyToMany(targetEntity="Account", mappedBy="users", cascade={"persist", "remove"})
*/
private $accounts;
...
Than the userType
...
->add('accounts', 'genemu_jqueryselect2_entity', array(
"class" => "CMiNewsBundle:Account",
"property" => "name",
"multiple" => "true",
"query_builder" => function (EntityRepository $er) use ($user)
{
return $er->createQueryBuilder('acc')
->join('acc.users','u')
->where('u.id = :userID')
->setParameter('userID' , $user);
}
)
)
...
The validation.yml
CM\Bundle\iNewsBundle\Entity\User:
properties:
...
accounts:
- NotBlank: ~
...
"NotBlank" assert checks if the property === null || property === ''. Since your property is a collection, you probably initialise it as an ArrayCollection in your constructor so it will never be null.
For collections you should use the "Count" assert
http://symfony.com/doc/current/reference/constraints/Count.html
It forces you to set the "maximum" count as well as the minimum so you might want to create your own assert.