Eloquent/Laravel5 linking distant relations ("hasOneThrough") - laravel-5

The question in short:
"pages" and "tasks" have a many-to-many relationship linked by the pivot table "page_tasks". The table "responses" is linked to that pivot table by the foreign key "page_task_id".
Now I want to be able to access the page and the task a response belongs to directly with Eloquent. However the hasManyThrough function does not work, as it exspects the foreign_keys at different places:
public function task(){
return $this->hasManyThrough('PageTask', 'Task', 'page_task_id', 'task_id');
}
Unknown column 'tasks.page_task_id' in 'field list'
This means that eloquent exspects the task table having a foreign key page_task_id pointing to page_tasks. But in my model the page_tasks table has a foreign key task_id pointing to tasks. How do I tell eloquent that fact?
An other approach I tried was to use existing relations that were previously defined:
public function task(){
return $this->page_task->task();
}
This however tells me that there is no methoid called "task".
What would the recommended way be to achieve this? What am I doing wrong?
Here are some more details if needed:
"pages" and "tasks" have a many-to-many relationship with pivot table page_tasks linking it.
Page-Model:
class Page extends Model {
public function tasks(){
return $this->belongsToMany('Task', 'page_tasks');
}
}
Task-Model:
class Task extends Model {
public function pages()
{
return $this->belongsToMany('Page', 'page_tasks');
}
}
This works fine.
Response-Model looks like this
class Response extends Model {
protected $fillable = [
'page_task_id',
];
public function page_task(){
return $this->belongsTo('App\PageTask', 'page_tasks');
}
public function task(){
??????
}
}
PageTask-Model looks like this:
class PageTask extends Model {
protected $fillable = [
'page_id',
'task_id',
];
public function page(){
return $this->belongsTo('Page');
}
public function task(){
return $this->belongsTo('Task');
}
public function responses(){
return $this->hasMany('Response');
}
}

Related

Laravel many to many relationship with pivot

I'm using Laravel Filament.
I got a projects and responsibles tables in a many-to-many relationship. But also another table of responsabilityTypes
projects
id
title
responsibles
id
name
responsabilityTypes
id
name
project_responsible
project_id
responsible_id
responsibilityType_id
And here are my relationships setup:
Responsible.php
public function projects() {
return $this->belongsToMany(Project::class,'rel_project_responsible','responsible_id','project_id')
->withPivot('responsibilityType_id')
->withTimestamps()
->using(AcademicoProyecto::class);
}
Project.php
public function responsibles() {
return $this->belongsToMany(Responsible::class,'rel_project_responsible','project_id','responsible_id')
->withPivot('responsibilityType_id','sort')
->withTimestamps()
->using(AcademicoProyecto::class);
}
I have set up a class for the pivot table like so:
ProjectResponsible.php
use Illuminate\Database\Eloquent\Relations\Pivot;
class AcademicoProyecto extends Pivot
{
}
ResponsibilityType.php
//Don't know how to set up
My question is, when the user is in a Project Edit page and clicks on the "attach" button, in order to add a Responsible record, a Modal pops up to select a Responsible, but I also implemented a Select list to display the different types of responsibilities.
What am I missing to set up in order to access and display the types of responsibilities in the select list and attach it to the pivot table?
Your question asks about "access and display" but you have no controller or view code. But for the model, it's just a simple relationship between two tables, so define it as such:
class AcademicoProyecto extends Pivot
{
use SoftDeletes;
public function responsibilityType() {
return $this->belongsTo(ResponsibilityType::class);
}
}
class ResponsibilityType extends Model
{
protected $fillable = ["name"];
}
Now you simply update the other models to access the relationship in the withPivot() call.
class Responsible extends Model {
public function projects() {
return $this->belongsToMany(Project::class,'rel_project_responsible','responsible_id','project_id')
->withPivot('responsibilityType')
->withTimestamps()
->using(AcademicoProyecto::class);
}
}
class Project extends Model {
public function responsibles() {
return $this->belongsToMany(Responsible::class,'rel_project_responsible','project_id','responsible_id')
->withPivot('responsibilityType', 'sort')
->withTimestamps()
->using(AcademicoProyecto::class);
}
}
Now you should be able to do, for example:
$foo = Responsible::with("projects")->first();
foreach ($foo->projects as $project) {
echo $project->pivot->responsibilityType?->name;
}

Laravel hasMany relationship issue

I have a problem about table relationship in models. when I try to add hasMany relation there is an error popping up.
Call to undefined relationship [Plan100] on model [App\AllPlan].
This is the main table model places
protected $table = "places";
public $with = ["AllPlan"];
public function allplans()
{
return $this->hasMany("App\AllPlan");
}
And AllPlan table model
protected $table = "all_plans";
public function place()
{
return $this->belongsTo("App\Place");
}
No problem 'till here. I can see the AllPlan data inside the Places table on json response... But, the problem is popping up when I try to add hasMany relation into AllPlan table like below.
Now AllPlan table model looks like this.
protected $table = "all_plans";
public $with = [
"Plan100",
"Plan90",
];
public function place()
{
return $this->belongsTo("App\Place");
}
public function plan()
{
return $this->hasMany(
"App\Plan100",
"App\Plan90"
);
}
And the Plan100 table model look like this:
public function plan()
{
return $this->belongsTo("App\AllPlan");
}
But it's giving me an error. But I am not very sure where do I do wrong. Thank you.
Seems to me that you are trying to create two new relations, but this can't be done inside one function. Create two functions and refactor your code like this:
public function plan100()
{
return $this->hasMany(App\Plan100", 'foreign_key');
}
public function plan90()
{
return $this->hasMany(App\Plan90", 'foreign_key');
}

Laravel how to define 3 relationships with one model?

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.

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