Is there a way to get a nested Eloquent model based on ids from another table? - php

Hey there stackoverflow
I am currently building a course application as part of my laravel project.
My problem lies in how the eloquent handle model relations, i'm still kinda new to eloquent, so hopefully you can answer my question.
The structure
The Course has many episodes and each episode has many sections.
Which means I have 3 tables in the DB. Courses -> course_episodes -> course_episode_sections
ID table is where i connect courses with users - course_users.
Right now i can create courses and and put in all the data correctly.
The Problem
I need to retrieve all the courses and its nested children that the user has bought, which is connected in the course_users table with columns course_id and user_id
Course structure
Same stucture in DB
course: {
name: null,
sub_title: null,
estimate: null,
trailer: null,
type: null,
text: null,
course_episodes: [
{
name: null,
section: [
{
order: null,
type: null,
content: null,
},
]
},
]
}
Model Pictures
My models as of right now.
class CourseUsers extends Model {
protected $fillable = [
'id',
'course_id',
'user_id',
'active',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courses()
{
return $this->belongsToMany(Course::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function scopeFindForUserId($query, $userId)
{
return $query->where(function ($q) use ($userId) {
$q->where(function ($q) use ($userId) {
$q->where('user_id', $userId);
});
});
}
Course model
class Course extends Model{
protected $fillable = [
'id',
'name',
'sub_title',
'type',
'estimate',
'trailer',
'gateway_id',
'text',
'active',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courseEpisode()
{
return $this->hasMany(CourseEpisode::class);
}
public function courseUsers() {
return $this->hasMany(CourseUsers::class);
}
public function scopeActive(Builder $builder)
{
return $builder->where('active', true);
}
Course episode Model
class CourseEpisode extends Model implements HasMedia {
use HasMediaTrait;
protected $fillable = [
'id',
'course_id',
'order',
'name',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function course()
{
return $this->belongsTo(Course::class);
}
public function courseSection()
{
return $this->hasMany(CourseEpisodeSection::class);
}
Course episode sections
class CourseEpisodeSection extends Model {
protected $fillable = [
'id',
'course_episode_id',
'order',
'type',
'content'
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courseEpisode()
{
return $this->belongsTo(CourseEpisode::class);
}

According to your explanation, course_users table holds many-to-many relationship between Course and User model. In case of a many-to-many relationship, you actually don't need a CourseUser model. This kind of table which holds many-to-many relationship is called pivot table. Read more from the Official Documentation
I am defining only the relationships with your Course, User, CourseEpisode, CourseEpisodeSection models.
Course.php
class Course extends Model
{
public function courseEpisodes()
{
return $this->hasMany(CourseEpisode::class);
}
public function users()
{
return $this->belongsToMany(User::class,'course_users')->withPivot('active');
}
}
CourseEpisode.php
class CourseEpisode extends Model
{
public function courseSections()
{
return $this->hasMany(CourseSection::class);
}
}
User.php
class User
{
public function courses()
{
return $this->belongsToMany(Course::class,'course_users')->withPivot('active');
}
}
If you want to get all the children relationships from a user, use nested eager loading :
$user_with_nested_course_data = User::with('courses.courseEpisodes.courseSections')->find($id);

Related

Laravel 5.6.5 relationship executing wrong query

As you can see on the following image my laravel relation between shoporder and shoporderroutingstepplans is not as it has to be.
I have no idea what I exactly did wrong so I hope someone can help me out. In the code beneath I have left some fields out of the code to make it more legible.
class shoporder extends Model
{
protected $primaryKey = 'ID';
protected $fillable = [
'CADDrawingURL',
'ID',
'Costcenter',
'CostcenterDescription',
'Costunit',
'CostunitDescription',
'Created',
'Creator',
'CreatorFullName',
'Description',
'ShopOrderParent',
'ShopOrderParentNumber',
'ShopOrderRoutingStepPlanCount',
'Status',
'SubShopOrderCount',
];
public function shopOrderRoutingStepPlans() {
return $this->hasMany('App\shopOrderRoutingStepPlan', 'ShopOrder', 'ID');
}
}
class ShopOrderRoutingStepPlan extends Model
{
protected $primaryKey = 'ID';
public $table = "shoporderroutingstepplans";
protected $fillable = [
'Account',
'ID',
'AccountName',
'AccountNumber',
'AttendedPercentage',
'Backflush',
'Created',
'Creator',
'CreatorFullName',
'Description',
'ShopOrder',
];
public function shopOrder() {
return $this->belongsTo('App\shopOrder', 'ShopOrder', 'ID');
}
}
This is the code Im executing to get the relations of 1 shoporder in the controller.
$orders = shopOrder::find('0600959e-6b92-4135-8ea8-1fa2fd92a916')->shopOrderRoutingStepPlans()->get();
In the shoporder migration I defined the primary key:
$table->string('ID')->unique();
$table->primary('ID');
In the shoporderroutingstepplans migration I defined the foreign key as followed.
$table->string('ID')->unique();
$table->primary('ID');
$table->foreign('ShopOrder')
->references('ID')
->on('shoporders');
You must switch the order of the last two parameters:
From
return $this->hasMany('App\shopOrderRoutingStepPlan', 'ShopOrder', 'ID');
To
return $this->hasMany('App\shopOrderRoutingStepPlan', 'ID', 'ShopOrder');
The parameters are
model,
name of column in the linked model,
name of column in this model.

Eloquent: Two foreign keys in a table pointing to the same table

I have two models:
Team
Game (Played between two games)
The Game model has two foreign keys pointing to the Team model - team1_id & team2_id.
Here's the code for Team model:
class Team extends Eloquent
{
protected $table = 'team';
protected $fillable = [
'name',
'color',
'year'
];
public function games()
{
return $this->hasMany(\App\Models\Game::class);
}
}
Code for Game model:
class Game extends Eloquent
{
protected $table = 'game';
protected $casts = [
'team1_id' => 'int',
'team2_id' => 'int'
];
protected $fillable = [
'team1_id',
'team2_id',
'location',
'start_at'
];
public function team1()
{
return $this->hasOne(\App\Models\Team::class, 'team1_id');
}
public function team2()
{
return $this->hasOne(\App\Models\Team::class, 'team2_id');
}
}
I get an error saying the column could not be found.
return $this->hasMany(\App\Models\Game::class, 'team1_id');
This works, but the problem is that I want to get games depending on both team1_id and team2_id.
You had to specify the foreign key and the local key you use to reference that relation
public function localTeam()
{
return $this->belongsTo(\App\Models\Team::class, 'id', 'team1_id');
}
public function foreignTeam()
{
return $this->belongsTo(\App\Models\Team::class, 'id', 'team2_id');
}

Laravel retrieve values from foreign key

I have these models with their related db tables,at the moment I can retrieve all the requirement
Requirement::all()
but I just have a list of foreigns key (destination_id,applier_id,doc_id). How can i retrieve directly the row connected to that foreigns key?
class Requirement extends Model
{
protected $fillable = [
'required',
'destination_id',
'applier_id',
'doc_id'
];
public function destination()
{
return $this->belongsTo(Destination::class);
}
public function applier()
{
return $this->belongsTo(Applier::class);
}
public function doc()
{
return $this->belongsTo(Doc::class);
}
}
class Doc extends Model
{
protected $fillable = [
'type',
'description',
'note'
];
public function requirements()
{
return $this->hasMany(Requirement::class);
}
}
class Destination extends Model
{
protected $fillable = [
'country',
'passying_country',
'transfer_conditions',
'passing_conditions'
];
public function requirements()
{
return $this->hasMany(Requirement::class);
}
}
You can call with() function instead of all(). So if you try this following :
$requirements = Requirement::with('destination', 'applier', 'doc')->get();
Make it dd($requirements) and look the output.
Hope it will work.

Laravel 5.2 Model Relationships

im new to Laravel and have a relationship question.
The goal is to get all News where news.page_id = page.id AND page.pagetype_id = pagetype.id WHERE pagetype.component = news AND page.app_id = 1
class News extends Model
{
protected $table = 'news';
protected $fillable = ['page_id', 'title', 'description', 'active', 'created_at', 'updated_at'];
}
class Page extends Model
{
protected $table = 'pages';
protected $fillable = ['app_id', 'unique_id', 'pagetype_id', 'title', 'picture_url', 'short_description', 'description', 'valid_since', 'valid_until', 'extras', 'active', 'created_at', 'updated_at'];
public function pagetype() {
return $this->belongsTo('App\Models\PageType', 'pagetype_id');
}
}
class PageType extends Model
{
protected $table = 'pagetypes';
protected $fillable = ['pagetype', 'component', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->belongsToMany('App\Models\Page', 'pagetypes', 'id', 'id');
}
}
// now i need All News Items where page.pagetype_id = pagetypes.id and patchtypes.component = news
// First Attempts are
Page::whereHas('pagetype', function ($q) {
$q->where('component', 'news');
})->where(['app_id' => 1])->get();
// result is all Pages which has the proper component news.
This is what i have tried yet, but in my attempt i'll only receive the proper pages but of course not the news.
My "current" solution is to get all the pages and then loop through News::where('page_id', $myPageId). But im pretty sure its possible to get a proper relationship to get also news.
I cant do any other model since there are many different pagetypes and components aswell.
Thanks so far.
You need to add relationship function to news model.
public function pages() {
return $this->belongsTo('App\Models\Page');
}
And call it through News model.
News::with('pages')->where('app_id',1);
First off all I think that you are wrong with you PageType relation
class PageType extends Model
{
protected $table = 'pagetypes';
protected $fillable = ['pagetype', 'component', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->hasMany('App\Models\Page');
// if i understood you correctly you haven't got any pivot table
}
}
Then you should link your News and Page like so
News.php
class News extends Model
{
protected $table = 'news';
protected $fillable = ['page_id', 'title', 'description', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->belongsTo('App\Models\Page');
}
}
Page.php
class Page extends Model
{
protected $table = 'pages';
protected $fillable = ['app_id', 'unique_id', 'pagetype_id', 'title', 'picture_url', 'short_description', 'description', 'valid_since', 'valid_until', 'extras', 'active', 'created_at', 'updated_at'];
public function pagetype() {
return $this->belongsTo('App\Models\PageType');
}
public function news() {
return $this->hasMany('App\Models\News');
}
}
Then you can achieve your goal
News::whereHas('page', function($q) use($appId) {
$q->where('app_id',$appId);
})->whereHas('page.pagetype', function($q) {
$q->where('component', 'news');
})->get();

working on relation many to many in laravel 5.2

i made third table because i need extra colums in third table.
i has written relation method in both model but id is not
moving
in user model method is
class User extends Model
{
protected $fillable = [
'user_type_id', 'accountType', 'email', 'password', 'userName', 'gender', 'dob', 'country', 'city', 'mobileNo', 'cnic', 'address',
'degreeLevel', 'degreeTitle', 'institution', 'complitionYear', 'acedCountry', 'experience', 'workExperience', 'industry', 'perCountry', 'cv'
];
protected $table = 'users';
/********************************************************************/
/* Relationship between User and Ranklist */
/*******************************************************************/
public function RankList()
{
return $this->hasMany('App\Models\RankList','user_id');
}
public function Company()
{
return $this->hasMany('App\Models\Company');
}
public function newsAndEvents()
{
return $this->hasMany('App\Models\newsAndEvents','user_id');
}
/********************************************************************/
/* Relationship between User and user type */
/*******************************************************************/
public function UserType()
{
return $this->belongsTo('App\Models\UserType','user_type_id');
}
public function course_outline()
{
return $this->belongsTo('App\Models\CourseOuline','user_id');
}
public function Jobs()
{
return $this->belongsToMany('App\Models\Job','Job_User','User_id','Job_id');
}
public function Skill_User()
{
return $this->belongsToMany('App\Models\Skill','Skill_User','Skill_id','User_id');
}
public function Feedback_User()
{
return $this->belongsToMany('App\Models\Feedback','Feedback_User','Feedback_id','User_id');
}
}
in job model method is
class Job extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
/**************************************************/
/* Company Post Job */
/**************************************************/
protected $fillable = [
'jobType', 'jobTitle','skills','industry', 'department', 'vacancy', 'qualification', 'degreeTitle', 'miniExperience', 'jobCategory',
'city', 'gender', 'companyName', 'description','posting_date', 'applied_date', 'companyLogo',
];
protected $table = 'jobs';
/**************************************************/
/* Relationships between company and job */
/**************************************************/
public function Company()
{
return $this->belongsTo('App\Models\Company','company_id');
}
public function job_skill()
{
return $this->belongsToMany('App\Models\Skill','Job_Skill','Job_id','skill_id');
}
public function Users()
{
return $this->belongsToMany('App\Models\User','Job_User','User_id','Job_id');
}
}
pivot table code is
class Job_User extends Model
{
protected $fillable = [
'cv','current_salary','expected_salary','status',
];
protected $table = 'jobs_users';
}
but user apply on job error is shown
Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (bridging_the_gap.jobs_users, CONSTRAINT jobs_users_user_id_foreign FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE) (SQL: insert into jobs_users (cv, current_salary, expected_salary, updated_at, created_at) values (1st, 15,000-19,999, 30,000-39,999, 2016-06-02 10:57:02, 2016-06-02 10:57:02))
Try something like this
//model jobs
public function Jobs()
{
return $this->belongsToMany('App\Models\jobs_users');
}
//model users
public function Users()
{
return $this->belongsToMany('App\Models\jobs_users');
}
//model pivot - jobs_users
public function user() {
return $this->belongsTo('App\Models\user');
}
public function jobs() {
return $this->belongsTo('App\Models\job');
}
This are basics to make pivot (many to many relation). For more fields you have to define in pivot model extra fields etc...
Hope it helps

Categories