Removing duplicates in Laravel relationships - laravel

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' } ]

Related

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 call to undefined method addEagerConstraints()

I have two models
Post.php
id
post
show_id
type = 'movie' or 'tv'
Show.php
id // this only auto increment counter ids
show_id
show_type = 'movie' or 'tv'
the thing is show can be either tv or movie and may two with the same show_id for exmaple one tv could have a show_id of 10 and also one movie can have it but the types are diffrent
i have in post model
public function show(){
return $this->belongsTo('App\Show', 'show_id');
}
in show model
public function post(){
return $this->hasMany('App\Post', 'id');
}
this relationship get the first show with matching show id it sees, wheather its a movie or tv, i want to restrict it to match type column on both sides
post.php:
public function show() {
return $this->belongsTo('App\Show', 'show_id', 'show_id')
->where('type', $this->type);
}
show.php
public function posts() {
return $this->hasMany('App\Post', 'show_id', 'show_id')
->where('type', $this->show_type);
}
UPDATE (the code above does not work!)
Trying to use where clauses (like in the example below) won't work when eager loading the relationship because at the time the relationship is processed $this->f2 is null.
Read more here: Compoships
I just came accross a package https://github.com/topclaudy/compoships
what it does it allows creating relationships based on more than one FK, which laravel doesnt support by default
I think what you're looking for is a polymorphic relation. Instead of having a model that may be one of two "types" there should probably be two separate models on the same relation. For example:
class Post
{
public function Show()
{
return $this->morphTo();
}
}
class TvShow
{
public function Post()
{
return $this->morphMany('App\Post', 'show');
}
}
class Movie
{
public function Post()
{
return $this->morphMany('App\Post', 'show');
}
}
Then your posts table would have a show_id and show_type field that would relate to either a tv show or movie. Check out the docs for more info, I'm not sure of the rest of your project so I'm not 100% this will fit but anytime you start putting "_type" fields in your table you should question whether or not you should be using a polymorphic relation. This will also likely keep your models cleaner and free of a bunch of if statements as you realize there are other differences between movies and shows and how you handle them.
https://laravel.com/docs/5.7/eloquent-relationships#polymorphic-relations

Access Method in a hasManyThorugh

I have 4 tables,
props, listing, offers, contact
props has many listing, listing belongs to props
public function listings()
{
return $this->hasMany('App\Models\Listing\Listing');
}
offer belongs to listing,
public function property()
{
return $this->belongsTo('App\Models\Property\Property')->with('owners');
}
then
offer belongsToMany contact trough offer_contact table
public function buyers()
{
return $this->belongsToMany(Contact::class, 'offer_contact', 'offer_id', 'contact_id')->with('primary_email');
}
My question is, how to access buyers()?
Something like $props->buyers()
In props model, what I did is
return $this->hasManyThrough('App\Models\Offer\Offer', 'App\Models\Listing\Listing');
You cannot. You may use nested iterations to get properties, listings belongs to each property, offers belongs to each listing and then customers belonging with the offer.
Alternatively, you may use the raw query to get the desired result using DB::statement();
I created a HasManyThrough relationship with unlimited levels: Repository on GitHub
After the installation, you can use it like this:
class Property extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function buyers() {
return $this->hasManyDeep(Contact::class, [Listing::class, Offer::class, 'offer_contact']);
}
}

Laravel ORM relationship - manager-employee over the same table of users

I have a user_managers pivot table that gets both keys from the users table:
employer_user_id
employee_user_id
I believe users would have a many to many relationship as a user can be managed by more than 1 manager there will be users who manage 1 or more users, while other users (excluding those under them) would manage them while there will be users who don't manage at all and a User can have only 1 manager.
My first try at defining this was to build another model named Manager representing the user_managers pivot table, so in User model I wrote the following 2 functions:
public function managedBy()
{
return $this->belongsToMany('Manager', 'employer_user_id');
}
public function manages()
{
return $this->hasMany('Manager', 'employee_user_id', 'employer_user_id');
}
Does this make sense or do you know of a better way to implement this kind of structure?
If a user can have only 1 manager then you can define you relationship as one to many like
//User model
public function managedBy()
{
return $this->belongsTo(User::class, 'manager_id');
}
public function managees()
{
return $this->hasMany(User::class, 'manager_id');
}
you don't need to pass $id to your relationship definition.
For multiple managers, Yes you would need a many to many relationship by adding a junction/pivot table which i guess you already have user_managers, Now you need to define your relationships using belongsToMany for managers and mangees like
public function managers()
{
$this->belongsToMany(User::class, 'user_managers', 'employer_user_id')
}
public function managees()
{
$this->belongsToMany(User::class, 'user_managers', 'employee_user_id')
}

creating self referencing entities in laravel 5.5

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();
}
}

Resources