Laravel condition for secondary table - laravel

Mode Position.php has following code.
class Position extends \Eloquent {
public static function get_position_by_url($url) {
return Position::where('url','=',$url)->where('status','=','0')->with('message')->get();
}
public function message() {
return $this->hasMany('Message');
}
}
The above code works fine, What I need is to get data by condition in messages table, like following:
class Position extends \Eloquent {
public static function get_position_by_url($url,$screenSize) {
return Position::where('url','=',$url)->where('status','=','0')->with('message')->where('screensize','=',$screensize)->get();
}
public function message() {
return $this->hasMany('Message');
}
}
But the both conditions are applied to positions table, which I want to apply second condition to messages table.

You can filter eager loaded models by passing a closure:
return Position::where('url','=',$url)->where('status','=','0')->with(['message' => function($q) use ($screensize){
$q->where('screensize','=',$screensize);
}])->get();
Like documented here under Eager Loading Constraints

Related

How to get data from table related through pivot table?

I have 4 tables: countries, activities, country_activities and packages.
countries and activities are related through pivot table country_activity, and packages is related to country_activity.
Now, How do I eager load all packages related to each activity in a country?
class Country extends Model
{
public function activities() {
return $this->belongsToMany('App\Models\Activity','country_activities')->using('App\Models\CountryActivity')->as('country_activities');
}
}
class Activity extends Model
{
public function countries() {
return $this->belongsToMany('App\Models\Country','country_activities')->using('App\Models\CountryActivity')->as('country_activities');
}
}
class Package extends Model
{
public function country_activities() {
return $this->belongsToMany('App\Models\CountryActivity');
}
}
class CountryActivity extends Pivot
{
protected $table = 'country_activities';
public function packages() {
return $this->hasMany('App\Models\Package');
}
}
So, this worked for me.
class Country extends Model
{
public function activities() {
return $this->belongsToMany('App\Models\Activity','country_activities')->using('App\Models\CountryActivity')->withPivot(['id'])->as('country_activities');
}
Now, In my controller, I do this
$country = Country::with(['activities'=> function($q) {$q->where('name','Trekking');}])->where('name','Nepal')->first(['id','name']);
$country->activities->map(function ($i){
$i->country_activities->load('packages');
return $i;
});
I did something similar in a project i worked on. I'm not sure it will work but it's worth the shot:
$country = Country::find(1);
$country->activities = $contry->activities()->get()->each(function ($i, $k){
$i->packages = $i->pivot->packages;
//$i->makeHidden('pivot'); -> This is useful if you want to hide the pivot table
});
var_dump($country);

join table in laravel

I have 3 table in laravel:
class General extends Mode
{
public function populars()
{
return this->hasMany('App\Popular');
}
}
enter code here
and
class Popular extends Model
{
public function general()
{
return this->belongsTo('App\General');
}
}
and
class Specific extends Model
{
public function popular(){
return this->belongsTo('App\Popular');
}
}
...
how to join tables and return this list result:
1. generals
2.popular
3.Specific
I assume Popular has many Specific, you could add another mapping in Popular model as
class Popular extends Model
{
public function general()
{
return this->belongsTo('App\General');
}
public function specific()
{
return this->hasMany('App\Specific');
}
}
Doing with eloquent way you could write it as
$generals = General::with('populars.specific')->get();
Using query builder you could join them as
DB::table('general as g')
->join('popular as p', 'g.id','=','p.general_id')
->join('specific as s', 'p.id','=','p.popular_id')
->get();

Laravel hasMany with multiple constraints

I have query that I run on my ServiceController
return Service::with('contacts', 'locations.datetimes')->find($service->id);
This works great perfectly, but I need to change it. The relationships are defined as follows:
class Service extends Model
{
public function locations()
{
return $this->belongsToMany('App\Models\Service_location', 'service_location_service');
}
}
class Service_location extends Model
{
public function datetimes()
{
return $this->hasMany('App\Models\Service_detail');
}
}
I need a second constraint on the datetimes where I need the relationship to be along the lines of
return $this->hasMany('App\Models\Service_detail')->where('service_id', $service->id);
The problem is I can't find a way to pass through the $service_id. How do you handle two constraints on a hasMany relationship?
Let try this. Change Service_location to this
class Service_location extends Model
{
public function datetimes()
{
return $this->hasMany('App\Models\Service_detail');
}
public function scopeServiceId($query)
{
return $query->where('service_id', $service->id);
}
}
Now your query will be
Service::with(['contacts', 'locations.datetimes' =>function($q) use($serviceId){
$q->serviceId($serviceId);
}])->find($service->id);
There is no way to pass argument to a relationship function. If you do its highly likely that you will run into the N+1 query problem.

Select item by specific property

I'm working in Laravel 4, I can my models simplify to these:
class DayVariant extends \Eloquent {
public function chod()
{
return $this->belongsTo('Chod', 'chod_id');
}
}
class Chod extends \Eloquent {
public function meals()
{
return $this->belongsToMany('Meal');
}
}
class Meal extends \Eloquent {
public function mealProperties()
{
return $this->hasMany('MealsProperty');
}
}
class MealProperty extends \Eloquent {
public function propertyType()
{
return $this->belongsTo('PropertyType', 'property_type_id');
}
}
And I want select MealProperty by property_type_id. I was doing it this way:
$prop = $dayVariant->chod->meals->first()->mealProperties()->where('property_type_id','=', $foo)->first();
I need in this way get 5 from 70 the same mealsProperties for every meal. It works well, but I don't know how use eager loading for decreasing queries to database.
$dayVariant = DayVariant::with('breakfastChod.meals.mealProperties')->first();
I can do it this way and after it iterate over all mealProperties, but I'm looking for better way.
Maybe with constraints I can get only mealProperties which I will need and iterate over them.
Is there better way to get specific properties? If not, how can use constraints with my models?
I tried this, but it fails.
$dayVariant = DayVariant::whereHas('breakfastChod.meals.mealProperties', function($query)
{
$query->where('property_type_id', '=', $constants['nutr_ids']['kcal']);
})->first();
Thanks for every answer!
You can do it in the context of property or like you tried of dayVariant:
// starting from properties
$properties = MealProperty::whereIn('property_type_id',$foo)
->with('meal.chods.dayVariants')->get();
// or from dayVariant
$dayVariant = DayVariant::with(['chod.meals.mealProperties' => function ($q) use ($foo) {
$q->whereIn('property_type_id', $foo);
}])->first();

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