How to use the `where` method along with the `with` method in laravel 4? - php

Given the following, very simple, example:
Country Class
class Country extends Eloquent {
protected $table = "countries";
protected $fillable = array(
'id',
'name'
);
public function state() {
return $this->hasMany('State', 'country_id');
}
}
State Class
class State extends Eloquent {
protected $table = "states";
protected $fillable = array(
'id',
'name',
'country_id' #foreign
);
public function country() {
return $this->belongsTo('Country', 'country_id');
}
}
How can I list all the states, based on the id or the name of the country.
Example:
State::with('country')->where('country.id', '=', 1)->get()
The above returns an area, as country is not part of the query (Eloquent must attach the join later, after the where clause).

I think you're either misunderstanding the relations or over-complicating this.
class Country extends Eloquent {
public function states() {
return $this->hasMany('State', 'state_id');
}
}
$country = Country::find(1);
$states = $country->states()->get();

Related

How to obtain three level model data laravel

Updated
User model
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens, HasRoles;
const MALE = 'male';
const FEMALE = 'female';
protected $guard_name = 'sanctum';
public function educationalBackgrounds()
{
return $this->hasMany("App\Models\Users\EducationalBackground", "user_id");
}
public function seminars()
{
return $this->hasMany("App\Models\Users\Seminar", "user_id");
}
}
I have child table EducationalBackground which is related to User table
class EducationalBackground extends Model
{
use HasFactory;
protected $table = 'users.educational_backgrounds';
protected $fillable = [
'user_id',
'studies_type',
'year',
'course',
];
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function educationalAwards()
{
return $this->hasMany("App\Models\Users\EducationalAward", "educational_background_id");
}
}
And a third table that i want to access the award field
class EducationalAward extends Model
{
use HasFactory;
protected $table = 'users.educational_awards';
protected $fillable = [
'educational_background_id',
'award',
'photo',
];
public function educationalBackground()
{
return $this->belongsTo('App\Models\Users\EducationalBackground', 'educational_background_id');
}
}
I have api get route here
Route::get('/educational-background/{id}', [UserProfileController::class, 'getEducationalBackground']);
Here is my api method it works fine. But i want to go deeper and access the data of third table.
public function getEducationalBackground($id)
{
$educationalBackground = EducationalBackground::with('user')->where('user_id', $id)->get();
return response()->json($educationalBackground, 200);
}
It looks like you're not really grasping the concept of relations yet. Also, I'd advise you to look into route model binding :) What you basically want to be doing is:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds()->with('educationalAwards')->get();
}
Also, when you're pretty sure that whenever you want to use backgrounds, you also want to use the awards, you can add the with(...) to the model definition like so:
class EducationalBackground extends Model
{
...
protected $with = ['educationalAwards'];
}
That way, you can simplify your controller method to:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds;
}

Accessing Pivot table "3rd Model relationship" in Laravel Eloquent

I have this Many-to-Many relation Laravel Eloquent relationship
The Models are:
class Email extends Model //actually represent the email account
{
protected $table = 'emails';
protected $fillable = [
'user_id',
'name',
];
public function messages() {
return $this->belongsToMany(Message::class)->withPivot('email_subtype_id');
}
}
class Message extends Model //actually represent the email message
{
protected $table = 'messages';
protected $fillable = [
'subject',
'body ',
];
public function emails() {
return $this->belongsToMany(Email::class)->withPivot('email_subtype_id');
}
}
class EmailMessage extends Pivot //actually represent the pivot table
{
protected $table = 'email_message';
protected $fillable = [
'email_id',
'message_id',
'email_subtype_id',
];
public function email() {
return $this->belongsTo(Email::class);
}
public function message() {
return $this->belongsTo(Message::class);
}
//this is the relation to a third model called EmailSubtype
//I want to include this relation to the Pivot when using it
public function subtype() {
return $this->belongsTo(EmailSubtype::class, 'email_subtype_id');
}
}
class EmailSubtype extends Model //3rd Model need to be included with Pivot
{
protected $table = 'email_subtypes';
protected $fillable = [
'name'
];
public function pivotEmailSubtype(){
return $this->hasMany(Pivot::class, 'email_subtype_id');
}
}
I am able to do this in the Controller:
$email = Email::find(1);
foreach($email->messages as $message) {
$subtype_id = $message->pivot->email_subtype_id;
dd($subtype_id); //1 that relates to subtype: CC Email Account
//also I can get the name indirectly away from the relation as follows:
$subtypeName = EmailSubtype::find($subtype_id)->first()->name;
dd($subtypeName);
}
Here I am getting the email_subtype_id only by direct pivot relation but have to do extra work to get the related email sub-type name.
I need to get the email sub-type name [Directly] from the 3rd Model EmailSubtype relationship oneToMany [hasMany and belongsTo] that relates to Pivot model with EmailSubtype model using something like:
$message->pivot->subtypeName;
Any help please!
Use this:
public function messages() {
return $this->belongsToMany(Message::class)->withPivot('email_subtype_id')
->using(EmailMessage::class);
}
$message->pivot->subtype->name

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: Querying and accessing child objects in nested relationship with where clauses Many to Many relationship

Hi I have a problem to make my laravel query
Model Regions
class Region extends Model
{
protected $table = 'regions';
protected $guarded = [
];
public function county()
{
return $this->belongsTo('App\Models\County');
}
public function companies()
{
return $this->belongsToMany('App\Models\CompanyInfo',
'region_company','region_id','company_id');
}
Model Category
class Category extends Model
{
protected $table = 'categories';
protected $guarded = [];
public function companies()
{
return $this->belongsToMany('App\Models\Company', 'categories_company','category_id','company_id');
}
}
Model Company
class Company extends Model
{
protected $table ='companies';
protected $guarded = [
];
public function regions()
{
return $this->belongsToMany('App\Models\Region', 'region_company','company_id','region_id');
}
}
I have a input form where I want to filter by category and region and the output should be categories with companies if possible but I want to show only 10 companies per category. Not sure it is is possible.
here is what I have till now
$categories = $request->input('categories');
$region = $request->input('regions');
$companies = Category::whereIn('id',$categories)->with([
'companies.regions' => function ($query) use ($region) {
$query->whereIn('id', $region);
}])->get();
the problem here is that it is filtering the categories but it is still giving me all companies not filtering out the once that belong to certain region.
thank you
Dany
Try the following:
$categories = $request->input('categories');
$region = $request->input('regions');
$companies = Category::whereIn('id',$categories)->with([
'companies' => function ($query) use ($region) {
$query->whereHas('region', function ($q2) use ($region){
$q2->whereIn('id', $region);
});
$query->with(['region']);
$query->limit(10);
}])->whereHas('companies', function($q) use ($region) {
$q->whereHas('region', function ($q2) use ($region){
$q2->whereIn('id', $region);
});
})->get();

Accessing nested relationship with Laravel 4

I'm having trouble figuring out how to access a nested relationship within Laravel. The specific example I have is a Movie that has many entires in my Cast table which has one entry in my People table. These are my models:
MOVIE
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
MOVIECAST
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public function person()
{
return $this->hasOne('Person', 'person_id');
}
public function netflix()
{
return $this->belongsTo('Movie', 'movie_id');
}
}
PERSON
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
In my controller I can access the cast (containing person_id and role_id) like so:
public function movie($id)
{
$movie = Movie::find($id);
$cast = $movie->cast();
return View::make('movie')->with(array(
'movie' => $movie,
'cast' => $cast
));
}
...but I don't know how to access the corresponding name field in my People table.
EDIT 1:
Using the classes exactly as defined below in #msturdy's answer, with the controller method above I try to render the person names like so inside my view:
#foreach($cast->person as $cast_member)
{{$cast_member->person->name}}
#endforeach
Doing this i get the error:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$person
I don't know if it makes a difference or not but I have no id field on my People table. person_id is the primary key.
It should be simple, once you have accessed the cast...
Route::get('movies', function()
{
$movie = Movie::find(1);
$cast = $movie->cast;
return View::make('movies')->with(array(
'movie' => $movie,
'cast' => $cast));
});
Note: at this point, $cast is an instance of the Collection class, not a single object of the MovieCast class, as the
relationship is defined with hasMany()
you can iterate over it in the View (in my case /app/views/movies.blade.php
#foreach($cast as $cast_member)
<p>{{ $cast_member->person->name }}</p>
#endforeach
Class definitions used for testing:
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
public $timestamps = false;
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public $timestamps = false;
public function person()
{
return $this->hasOne('Person', 'person_id');
}
}
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public $timestamps = false;
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}

Categories