Only take first filter parameter
mateo2181 opened this issue · 2 comments
I want to filter related models with one to many relations but always is taken only the first parameter.
For example:
http://localhost:8000/p/profile/search?sport=8&residence_country=12 return only users with sport id 8 but not with residence country id 12.
http://localhost:8000/p/profile/search?residence_country=12&sport=8 return only users with residence country id 12 but not with sport id 8 .
Someone had this problem?
USER MODEL:
class User extends Authenticatable implements HasMedia, MustVerifyEmail
{
use HasRoleAndPermission;
use Notifiable;
use SoftDeletes;
use HasMediaTrait;
use Filterable;
use Messagable;
use Billable;
protected $table = 'users';
public function athlete()
{
return $this->hasOne('App\Models\Athlete');
}
public function scout()
{
return $this->hasOne('App\Models\Scout');
}
}
ATHLETE MODEL:
class Athlete extends Model
{
use DatesFormat;
use Filterable;
protected $table = 'athletes';
protected $fillable = [
'nationality_id',
'second_nationality_id',
'residence_country_id',
'residence_city',
'date_of_birth',
'phone',
'sport_id',
'secondary_sport_id',
'sporting_goal',
'professional_start_date',
'professional_end_date',
'height',
'gender',
'status',
'emailTutor',
'firstnameTutor',
'lastnameTutor',
'phoneTutor',
'user_id'
];
public function residenceCountry()
{
return $this->belongsTo('App\Models\Country','residence_country_id');
}
public function sport()
{
return $this->belongsTo('App\Models\Sport')->withTrashed();
}
SCOUT MODEL:
class Scout extends Model
{
protected $table = 'scouts';
protected $fillable = ['nationality_id', 'residence_country_id','user_id','sport_id','phone'];
protected $with = [
'currentEntity',
'nationality',
'residenceCountry'
];
public function user()
{
return $this->belongsTo('App\Models\User','user_id');
}
public function sport()
{
return $this->belongsTo('App\Models\Sport')->withTrashed();
}
public function residenceCountry()
{
return $this->belongsTo('App\Models\Country','residence_country_id');
}
}
USER FILTER:
class UserFilter extends ModelFilter
{
public $relations = [];
public function fullname($name)
{
return $this->where(function($q) use ($name)
{
$names = explode(" ",$name);
return $q->where('firstname', 'LIKE', "%$name%")
->orWhere('lastname', 'LIKE', "%$name%")
->orWhereIn('lastname',$names)
->whereIn('firstname',$names)
->orWhere('email','LIKE',"%$name%");
});
}
public function sport($sport)
{
return $this->whereHas('athlete', function($q) use ($sport) {
return $q->where('sport_id', $sport)->orWhere('secondary_sport_id', $sport);
})->orWhereHas('scout', function($q) use ($sport) {
return $q->where('sport_id', $sport);
});
}
public function gender($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('gender', $value);
});
}
public function age($value)
{
$arrayNumbers = explode('-',$value);
$ageFrom = (int)$arrayNumbers[0];
$ageTo = (int)$arrayNumbers[1];
$from = Carbon::now()->subYears((int)($ageTo+1));
$from = $from->format('Y-m-d');
$to = Carbon::now()->subYears($ageFrom)->format('Y-m-d');
\Log::info($from);
\Log::info($to);
if($this->input('typeUser') == 'Scout' || $this->input('typeUser') == '') return true;
return $this->related('athlete', function($q) use ($from,$to) {
return $q->where('date_of_birth','>', $from)->where('date_of_birth','<=', $to);
});
}
public function status($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('status', $value);
});
}
public function sportingGoal($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('sporting_goal', $value);
});
}
public function residenceCountry($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('residence_country_id', $value);
})->orWhereHas('scout', function($q) use ($value) {
return $q->where('residence_country_id', $value);
});
}
public function nationality($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('nationality_id', $value);
})->orWhereHas('scout', function($q) use ($value) {
return $q->where('nationality_id', $value);
});
}
}
This is going to be because you're chaining with OR
outside of subqueries. A model filter runs methods in the order it encounters the input. With your current model filter you're creating:
$sport = 8;
$residence = 12;
User::whereHas('athlete', function($q) use ($sport) {
return $q->where('sport_id', $sport)->orWhere('secondary_sport_id', $sport);
})
->orWhereHas('scout', function($q) use ($sport) {
return $q->where('sport_id', $sport);
})
->whereHas('athlete', function($q) use ($value) {
return $q->where('residence_country_id', $residence);
})
->orWhereHas('scout', function($q) use ($value) {
return $q->where('residence_country_id', $residence);
});
Which is why only one of your constraints is being matched.
Wrapping any method using an OR
statement in a subquery would fix this:
<?
class UserFilter extends ModelFilter
{
public $relations = [];
public function fullname($name)
{
return $this->where(function($q) use ($name)
{
$names = explode(" ",$name);
return $q->where('firstname', 'LIKE', "%$name%")
->orWhere('lastname', 'LIKE', "%$name%")
->orWhereIn('lastname',$names)
->whereIn('firstname',$names)
->orWhere('email','LIKE',"%$name%");
});
}
public function sport($sport)
{
return $this->where(function($query) use ($sport)
{
$this->whereHas('athlete', function($q) use ($sport) {
return $q->where('sport_id', $sport)->orWhere('secondary_sport_id', $sport);
})->orWhereHas('scout', function($q) use ($sport) {
return $q->where('sport_id', $sport);
});
});
}
public function gender($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('gender', $value);
});
}
public function age($value)
{
$arrayNumbers = explode('-',$value);
$ageFrom = (int)$arrayNumbers[0];
$ageTo = (int)$arrayNumbers[1];
$from = Carbon::now()->subYears((int)($ageTo+1));
$from = $from->format('Y-m-d');
$to = Carbon::now()->subYears($ageFrom)->format('Y-m-d');
\Log::info($from);
\Log::info($to);
if($this->input('typeUser') == 'Scout' || $this->input('typeUser') == '') return true;
return $this->related('athlete', function($q) use ($from,$to) {
return $q->where('date_of_birth','>', $from)->where('date_of_birth','<=', $to);
});
}
public function status($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('status', $value);
});
}
public function sportingGoal($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('sporting_goal', $value);
});
}
public function residenceCountry($value)
{
return $this->where(function($query) use ($value)
{
return $query->whereHas('athlete', function($q) use ($value) {
return $q->where('residence_country_id', $value);
})->orWhereHas('scout', function($q) use ($value) {
return $q->where('residence_country_id', $value);
});
});
}
public function nationality($value)
{
return $this->where(function($query) use ($value)
{
return $this->whereHas('athlete', function($q) use ($value) {
return $q->where('nationality_id', $value);
})->orWhereHas('scout', function($q) use ($value) {
return $q->where('nationality_id', $value);
});
});
}
}
Thanks you!! Now works perfectly!