creating self referencing entities in laravel 5.5 - laravel

i have a situation where i have entity, base, which can contain ingredients, drinks and bases itself. I know how to make relations to ingredients and drinks, but do not know how to do it when it comes to bases within base. Any help would be appreciated. I can not use solution with parent_id, because one base can belong to several other bases, and do not want duplicates in the bases table. I need some solution with pivot table.

Assuming you have parent_id in bases table
class Base extends Model
{
public function children()
{
return $this->hasMany(Base::class,'parent_id','id');
}
public function parent()
{
return $this->belongsTo(Base::class,'id','parent_id');
}
}
And then you can easily access bases of a base like this
foreach($base->children() as $childBase){
$childBase->ingredients();
$childBase->drinks();
}

Finally i found solution, self referencing entity can be done with itself with Many To Many relation.
Model relation look like this :
class BaseDrink extends Model {
public function drinkbase(){
return $this
->belongsToMany('App\BaseDrink', 'basedrink_basedrink','basedrink_id', 'parent_basedrink_id')
->withPivot('created_by')
->withPivot('last_modified_by')
->withPivot('id')
->withTimestamps();
}
}

Related

Removing duplicates in Laravel relationships

I'm working with a situation where people and employers are related through licenses. So my models look something like this:
class Employer extends \Illuminate\Database\Eloquent\Model
{
public function people()
{
return $this->belongsToMany(Person::class, 'licenses');
}
// &c
}
class Person extends \Illuminate\Database\Eloquent\Model
{
public function employer()
{
return $this->belongsToMany(Employer::class, 'licenses');
}
// &c
}
However, person-employer pairs can have multiple licenses. So the aforementioned relationship returns duplicate Person entities, namely one Person entity for every License entity associated with the employer.
How do I fix this issue so that these relationships only return unique entities?
You can try laravel $collection->unique('licence_number')
so whatever eloquent returns you in collection just use unique with attribute
on the basis of you want to make the result unique like
licence_number is in the collection
[ { licence_number:1, name:'test' }, { licence_number:2, name:'jhon' } ]

Laravel Eloquent Relation belongsTo update

I am trying to update/delete/create in belongsTo relations.
Company has many sports
sports is belonging to Company
Here is two models.
class CompanySports
{
public function company()
{
return $this->belongsTo(Company::class, "company_id","id");
}
class Company
public function sports()
{
return $this->hasMany(CompanySports::class,"company_id","id");
}
}
at controller, when sports is added or modified or remove, what is the best practice to update?
i know that many to many, sync can be used. In this, what is the best solution? Should i compare everytime after loading all from database which is not good practice i believe.
From your code, I would first recommend putting your models in separate files, and ensuring they are singular. If you use the artisan make:model command to generate the stubs, it should do this for you.
// app/CompanySport.php // <-- NOTE singular
class CompanySport // <-- NOTE singular
{
public function company()
{
return $this->belongsTo(Company::class, "company_id","id");
}
}
// app/Company.php
class Company {
public function sports()
{
return $this->hasMany(CompanySport::class,"company_id","id"); // singular
}
}
From there, I find it helpful to build helper methods in the various classes so that the grammar sounds natural and more importantly, belongs to the model. For example:
// app/Company.php
class Company
{
...
public function addSport(CompanySport $sport)
{
$this->sports()->save($sport);
}
public function removeSport(CompanySport $sport)
{
$this->sports()->find($sport->id)->delete();
}
}
These helper functions can then be easily called from anywhere, e.g. controller:
// CompanySportsController.php
public function store(Company $company, CompanySport $sport)
{
$company->addSport($sport);
return redirect('/company/' . $company->id);
}
If you are using these helpers, there is no comparing or sync to be done since you are only using a one to many relationship. Eloquent does everything for you.
Also, I've found this cheatsheet particularly helpful when building out the initial relationships and scaffolding of a new app.
While adding new record of Company Model, you need not to do anything as there is no child for it yet.
While updating an instance of a Company model, again you need not to update anything on its children. As relationship are based on id(primary key) which I believe you don't change while updating.
And now for deleting there are some questions. Do you want to delete the children when the parent is deleting? If so, you can use ON DELETE CASCADE which you can set up in migration like
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
in your spors table.
Well you can make your own function too like answered in here
Well if you don't want to delete the children, you can use softdelete on your Model. set up the relations then like
CompanySports
public function company()
{
return $this->belongsTo(Company::class, "company_id","id")->withTrashed();
}
This way you can get the parent of a children without any error though the parent is deleted.

Laravel hasMany relationship detach all

Is there a simple solution to detach (without deleting) all related models through a hasMany Relation on a model?
For example, I have two tables:
College (id, name)
Student (id, name, college_id(nullable) )
In the College model I define this relationship:
class College extends Model
{
public function students()
{
return $this->hasMany('App\Student','college_id','id');
}
}
What is the best way to detach all current College students from the College (i.e, get all the students of the college and set their college_id to null)?
Is there an easy way to detach all students from the College model using eloquent?
Something like
class College extends Model
{
...
public function detachAllStudents()
{
...
}
}
P.S. already have read this question Laravel hasMany detach, but get errors when I try to apply it to my application
Yes, you can detach all the college students as below. Actually, we already have the college_id in your students table and we have to make this college_id null somehow. This is not called detach in Eloquent. The word detach come when you have many to many relationships. So, let's just update the students and see if it works or not.
$college->students()->update(['college_id' => null);
So, you method can be completed as below:
public function detachAllStudents()
{
$college->students()->update(['college_id' => null]);
}
That's it!
Directly from the documentation https://laravel.com/docs/5.8/eloquent-relationships:
Toggling Associations
The many-to-many relationship also provides a toggle method which "toggles" the attachment status of the given IDs. If the given ID is currently attached, it will be detached. Likewise, if it is currently detached, it will be attached:
$user->roles()->toggle([1, 2, 3]);
Despite Imran answer perfectly fits this scenario I would add a more generic approach. Let's say $college respects an interface instead of an implementation, you wouldn't know the foreign key at run time.
<?php
use Illuminate\Database\Eloquent\Relations\HasMany;
interface HasStudents {
public function students(): HasMany;
}
class College extends Model implements HasStudents
{
public function students(): HasMany;
{
return $this->hasMany(Student::class, 'college_id', 'id');
}
}
function detachStudents(HasStudents $model): void {
$studentsRelationship = $model->students();
$studentsRelationship->update([
$studentsRelationship->getQualifiedForeignKeyName() => null
]);
}
detachStudents($college);

A model with polymolymorphic ony to many and simple one to many relationship

I am using laravel 5.7. I have now a situation where i have a Fight model with structure user_id, fightable_id
i have two other tables users and monsters. so users_id refers to users (a user can have many fights) and fightable_id can refer to either a user or a monster (monsters table). so I have to define the functions for the relation ship
for User model i have to do
1.for polymorphic one to many relationship
public function fights()
{
return $this->morphMany('App\Fight', 'fightable');
}
2.for simple one to many relationship
public function fights()
{
return $this->hasMany('App\Fight');
}
I am confused now. ofcourse the only way is to change the functions name. but i will be doing the correct thing by changing the function names right (as both the functions have same name). or is there anything I am doing wrong?
I'm not sure I understand your question completely but I'll try my best!
Also this post will really help you understand the problem you are facing I think,
Laravel morph relationship
Using the code from the post I linked but taking your tables would produce models defined like this.
User Model
class User extends Model
{
public function fights()
{
return $this->hasMany('App\Fight');
}
}
Fight Model
class Fight extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
public function fightable()
{
return $this->morphTo();
}
}
Monster Model
class Monster extends Model
{
public function fight()
{
return $this->morphOne('App\Fight', 'fightable');
}
}
If you still feel this has not answered your question or need some more help just let me know!

Join 3 tables using Laravel Eloquent

So I have 3 tables
size_sets - id, name
sizes - id, name
size_set_sizes - size_id, size_set_id
I want to define a relationship in size_set model that would retrieve all sizes available for that sizeset
Something like:
public function sizes()
{
//define relationship here
}
Method sizes should retrieve the names from the size table, through size_set_sizes table in the size_set model...
My application is very dynamic and thus I needed to go with this structure. I tried the hasManyThrough relationship, but couldn't get that to work.
100% use a pivot table
https://laravel.com/docs/5.4/eloquent-relationships
This link will give you all you need
Use belongsToMany() relations like:
class Size extends Model
{
public function sizeSets()
{
return $this->belongsToMany(SizeSet::class, 'size_set_sizes');
}
}
class SizeSet extends Model
{
public function sizes()
{
return $this->belongsToMany(Size::class, 'size_set_sizes');
}
}
Then you can do:
$sizeSet = SizeSet::with('sizes')->find($id);
Then $sizeSet->sizes will return a collection of sizes for that size set.
I Think I found what I was looking for The answer is a pivot-table
http://laraveldaily.com/pivot-tables-and-many-to-many-relationships/

Resources