Laravel how to define 3 relationships with one model? - laravel-5

I have a Model which is called Championship. Championship may have 3 judges which are called Main Judge, Main Secretary and Judge Operator.
All of them linked to User Model and stored in the database as user ID.
My relationships looks like this
class Championship extends Model
{
protected $table = 'championships';
public function mainJudge()
{
return $this->hasOne('App\User', 'id', 'main_judge');
}
public function mainSecretary()
{
return $this->hasOne('App\User', 'id', 'main_secretary');
}
public function judgeOperator()
{
return $this->hasOne('App\User', 'id','judge_operator');
}
}
But I can't undertand how to define inverse relationship in User model
class User extends Authenticatable
{
public function sex()
{
return $this->belongsTo('App\Models\Sex');
}
public function player()
{
return $this->hasOne('App\Models\Player', 'user_id');
}
public function championship()
{
????
}

You just have to add it like you are adding other relations :
public function championship()
{
return $this->belongsTo('App\Championship');
}
When you do :
$championship = Championship::find($id);
$mainJudge = $championship->mainJudge;
$mainSecretary = $championship->mainSecretary;
// All objects will be exactly same
dd($mainJudge->championship,$mainSecretary->championship,$championship);
I assume all the user records have a foreign key to championships table championship_id
When you call the $user->championship relation it will return you the championship wrt to its foreign key championship_id
No need to worry you are just confusing the inverse relations:
See it this way:
Your mainJudge, mainSecretary, judgeOperators are of type App\User and every user have a championship_id when you will call the (App\User)->championship it will always return you its respective championship or null if the championship_id is empty.
Its just matter of perspective.
Just try the above code it will clear out your confusion.

Related

Laravel MongoDB 1:n relations

What is the correct way of defining 1:n relations in Laravel using MongoDB between two models Author and Book where one author can have several books while one book has exactly one authors?
Author.php
class Author extends Model
{
public function books()
{
// what to place here?
return $this->...
}
}
Book.php
class Book extends Model
{
public function author()
{
// what to place here?
return $this->...
}
}
Controller.php
class BookController extends Controller
{
public function store (Author $author, Request $request)
{
$book1 Book::create();
$book2 Book::create();
// connect $book1 <-> $author and $book2 <-> $author
// what to place here?
$book1->save();
$book2->save();
}
}
After calling store() I want to be able to do the following request
dump ($book1->author); // return $author
dump ($author->books); // return Collection of $book1 and $book2
assume you have the foreign key author_id in books table
class Author extends Model
{
public function books()
{
return $this->hasMany(Book::class, 'author_id');
}
}
class Book extends Model
{
public function author()
{
return $this->belongsTo(Author::class, 'author_id');
}
}
class BookController extends Controller
{
public function store (Author $author, Request $request)
{
$book1 = new Book();
$book2 = new Book();
$author->books()->saveMany([$book1, $book2]);
}
}
Suppose you have the ff:
users = model a
posts = model b
Case 1: vice versa of Case 2:
Case 2:
// on posts table/document you should have a user_id (as foreign key)
// and on post model you need define the belongsTo relationship
$this->belongsTo(User::class)
// on the User model you have to define hasOne or hasMany
$this->hasOne(Post::class) or $this->hasMany(Post::class)
Case 3:
On case 3, I'm not sure if adding a reference to each other is necessary because creating a single reference that links them can provide the data you require regardless of whether the request comes from model a or model b.
It is possible that it will not solve your problem. However, hopefully it will be of some assistance to you.
For case 1 ( in model_a ):
public function model_b_many()
{
return $this->hasMany( Model_b::class, 'id' );
}
For case 2 ( in model_b ):
public function model_a_many()
{
return $this->hasMany( Model_a::class, 'id' );
}
This will also work for case 3 :)

Polymorphic relationship with other polymorphic realtion?

I have order and return tables which have a created_by and accepted_by field where the corresponding user id is stored.
But now I would like to have multiple types for created_by and accepted_by instead of only user type. Assume a company could also create or accept the order/return.
I was thinking of a polymorphic one to many relationship.
Let’s name this table participants.
Something like:
ID
created
participantable_id
participantable_type
1
1
1
user
2
0
11
company
This works either for order or return but not both.
Is it practically to add extra colums to participants like trx_id and trx_type (order/return)?
How would the realtionships looks like to perform queries like:
$order->createdBy // should give me either user or company model
$order->acceptedBy
$return->createdBy
$return->acceptedBy
Or is there even a cleaner solution I am overlooking?
Thanks!
It would be 1:N polymorphic relationships so no need for an extra table. The structure can be found in the documentation
Your Order and Return model need to have the columns created_by_id, created_by_type, accepted_by_id, accepted_by_type.
______ (1) Company
/
Order (N) ----<
\______ (1) User
_____ (1) Company
/
Return (N) ----<
\_____ (1) User
class Order extends Model
{
public function created_by()
{
return $this->morphTo(__FUNCTION__, 'created_by_type', 'created_by_id');
}
public function accepted_by()
{
return $this->morphTo(__FUNCTION__, 'accepted_by_type', 'accepted_by_id');
}
}
class Return extends Model
{
public function created_by()
{
return $this->morphTo(__FUNCTION__, 'created_by_type', 'created_by_id');
}
public function accepted_by()
{
return $this->morphTo(__FUNCTION__, 'accepted_by_type', 'accepted_by_id');
}
}
class User extends Authenticatable
{
public function created_orders()
{
return $this->morphMany(Order::class, 'created_by');
}
public function accepted_orders()
{
return $this->morphMany(Order::class, 'accepted_by');
}
public function created_returns()
{
return $this->morphMany(Return::class, 'created_by');
}
public function accepted_returns()
{
return $this->morphMany(Return::class, 'accepted_by');
}
}
class Company extends Model
{
public function created_orders()
{
return $this->morphMany(Order::class, 'created_by');
}
public function accepted_orders()
{
return $this->morphMany(Order::class, 'accepted_by');
}
public function created_returns()
{
return $this->morphMany(Return::class, 'created_by');
}
public function accepted_returns()
{
return $this->morphMany(Return::class, 'accepted_by');
}
}

laravel model relationship seems backwards compared to docs

So I am setting up a one to one relationship between MyModel and the users table.
MyModel obviously has a user_id column to tie back to the users.
However - when i go to setup the relationship in MyModel I have to set it up in a way which seems backward!
This is in MyModel:
public function user()
{
return $this->hasOne('App\User', 'id', 'user_id');
}
Why Am i having to set the opposite foreign and local keys... ? Am i missing something?
Do it like this
class MyModel {
public function user()
{
return $this->belongsTo('App\User');
}
}
class User {
public function myModel()
{
return $this->hasOne('App\MyModel');
}
}
And that should work as intended (one to one) relationship

How to filter/select on intermediate (pivot) table columns in Laravel (5.4)

How do I create a column just in a pivot (intermediate) table in Laravel (5.4) and then filter results on it?
I have two models, Films and CastAndCrew. CastAndCrew are the various directors, producers, actors who work on a film. The pivot table should define the type of relationship between a CastAndCrew member and a Film. Obviously it's possible for someone to be e.g. an actor in one film and a producer on another, so I can't define this in their entry in the CastAndCrew table because it'll only be true for one film, and may be different for other films they worked on. So I assume I have to define the relationship in a pivot table, but I'm not sure how to do this exactly. What I've got so far:
class Film extends Model
{
protected $fillable = array('filmtitle', 'description');
public function List_Directors()
{
return $this->belongsToMany('App\CastAndCrew')->withPivot('type')->wherePivot('type', 'director');
}
public function List_Actors()
{
return $this->belongsToMany('App\CastAndCrew')->withPivot('type')->wherePivot('type', 'actor');
}
}
and
class CastAndCrew extends Model
{
protected $fillable = array('firstname', 'lastname');
public function List_Films_With_Director()
{
return $this->belongsToMany('App\Film')->withPivot('type')->wherePivot('type', 'director');
}
public function List_Films_With_Actor()
{
return $this->belongsToMany('App\Film')->withPivot('type')->wherePivot('type', 'actor');
}
}
When new CastAndCrew members get added to the site, I'm intending to use the attach method, e.g. to add a new director:
$newcastcrew->CastAndCrew::create(['firstname' => Request::get('firstname'), 'lastname' => Request::get('lastname')]);
$newcastcrew->List_Films_With_Director()->attach($filmID, ['type' => 'director']);
1.) Is that right?
2.) Does the ->withPivot('type') create the 'type' column in the Pivot table? If not, where/how do I define it?
2.) Presumably the ->wherePivot('type', 'director') clause in Film->List_Directors() then returns CastAndCrew members who are directors of that film? (which is what I want)
Corrections much appreciated!
Thanks
Your idea and logic is perfectly fine. You might want to add a relationship without the type condition to fetch all the films of user and all the cast and crew of a film. You also need to name your methods and relationships better. I've cleaned up the code for you. Feel free to use this if you prefer.
class Film extends Model
{
protected $fillable = array('filmtitle', 'description');
public function castAndCrew()
{
return $this->belongsToMany('App\CastAndCrew')->withPivot('type');
}
public function directors()
{
return $this->castAndCrew()->wherePivot('type', 'director');
}
public function actors()
{
return $this->castAndCrew()->wherePivot('type', 'actor');
}
}
class CastAndCrew extends Model
{
protected $fillable = array('firstname', 'lastname');
public function films()
{
return $this->belongsToMany('App\Film')->withPivot('type');
}
public function filmsAsDirector()
{
return $this->films()->wherePivot('type', 'director');
}
public function filmsAsActor()
{
return $this->films()->wherePivot('type', 'actor');
}
}

Many to Many with additional table in L4

I have a schema like that:
And now I want to use it in Laravel 4. So far, I could only achieve getting games for certain user, without touching owntype. Code:
public function games() {
return $this->belongsToMany('Game','games_users','owntype_id','games_id')->where('user_id','1');
}
The only thing I'm getting is onwtype_id. How can I add owntype table to the "equasion"?
You can access extra pivot table columns by specifying them through the withPivot function on the relationship function.
Basically I think you want to do this:
class User extends Eloquent {
public function games()
{
return $this->belongsToMany('Game', 'games_users')->withPivot('owntype_id');
}
}
class Game extends Eloquent {
public function users()
{
return $this->belongsToMany('User', 'games_users')->withPivot('owntype_id');
}
}
class Owntype extends Eloquent {
protected $table = 'owntype';
}
// Now you can do:
foreach ($user->games as $game)
{
// Echo each Owntype description.
echo Owntype::find($game->pivot->owntype_id)->description;
}
For the record... I think you might be taking it too far by creating a new table for owntype. Just set the description as a type column on the pivot table. Also make sure that your pivot table is named game_user (singular, alphabetically) and Laravel will know which pivot table to use automatically.
class User extends Eloquent {
public function games()
{
return $this->belongsToMany('Game')->withPivot('type');
}
}
class Game extends Eloquent {
public function users()
{
return $this->belongsToMany('User')->withPivot('type');
}
}
// Now you can do:
foreach ($user->games as $game)
{
// Echo each ownership type.
echo $game->pivot->type;
}
Some more info about working with pivot tables can be founded in the Laravel 4 docs.

Resources