I am caught in a very weird situation as there is something in my query that won't work if the value of whereHas
is changed. To explain it better, first, look at this query:
$table_data = Pengelola::with('pekerjaan_aktif.cu','pendidikan_tertinggi')
->whereHas('pekerjaan', function($query) use ($id,$tipe){
$query->where('tipe',$tipe)->where('id_tempat',$id)
->where(function($q){
$q->where('sekarang','1')->orWhere('selesai','>',date('Y-m-d'));
});
})->select('*',DB::raw('
(SELECT name from pengelola_pekerjaan WHERE pengelola.id = pengelola_pekerjaan.id_pengelola) as pekerjaan_name,
(SELECT tingkat from pengelola_pekerjaan WHERE pengelola.id = pengelola_pekerjaan.id_pengelola) as pekerjaan_tingkat,
(SELECT name from pengelola_pendidikan WHERE pengelola.id = pengelola_pendidikan.id_pengelola) as pendidikan_name,
(SELECT tingkat from pengelola_pendidikan WHERE pengelola.id = pengelola_pendidikan.id_pengelola) as pendidikan_tingkat
'))->get();
What it does is... I have 3 different table one is pengelola
, pengelola_pendidikan
that I called in with as pendidikan_tertinggi
, pengelola_pekerjaan
that I called in with as pekerjaan_aktif
and in whereHas
as pekerjaan
.
and to more understand it here are my three models:
this is pengelola
model
class Pengelola extends Model {
use FilterPaginateOrder, LogsActivity;
protected $table = 'pengelola';
protected static $logFillable = true;
public static $rules = [
'nik'=>'required',
'name'=>'required',
'email' => 'email'
];
protected $fillable = [
'nim','nik','name','tempat_lahir','tanggal_lahir','kelamin','agama','status','alamat','hp','email','gambar','darah','tinggi','berat','kontak'
];
protected $filter = [
'nim','nik','name','tempat_lahir','tanggal_lahir','kelamin','agama','status','alamat','hp','email','darah','tinggi','berat','kontak','created_at','updated_at'
];
public function getNameAttribute($value){
return !empty($value) ? $value : '-';
}
public static function initialize()
{
return [
'nim' => '','nik' => '','name' => '','tempat_lahir' => '','tanggal_lahir' => '','kelamin' => '','agama' => '','status' => '','alamat' => '','hp' => '','email' => '','darah' => '','tinggi' => '','berat' => '','kontak' => ''
];
}
public function pendidikan(){
return $this->hasMany('App\PengelolaPendidikan','id_pengelola','id');
}
public function pendidikan_tertinggi(){
return $this->hasOne('App\PengelolaPendidikan','id_pengelola','id')->orderBy('tingkat','desc')->latest();
}
public function pekerjaan(){
return $this->hasMany('App\PengelolaPekerjaan','id_pengelola','id');
}
public function pekerjaan_aktif(){
return $this->hasOne('App\PengelolaPekerjaan','id_pengelola','id')->where('sekarang','1')->orWhere('selesai','>',date('Y-m-d'))->latest();
}
public function keluarga(){
return $this->hasMany('App\PengelolaKeluarga','id_pengelola','id');
}
public function anggotacu(){
return $this->hasMany('App\PengelolaAnggotaCU','id_pengelola','id');
}
public function organisasi(){
return $this->hasMany('App\PengelolaOrganisasi','id_pengelola','id');
}
}
this is pengelola_pendidikan
class PengelolaPendidikan extends Model {
use FilterPaginateOrder, LogsActivity;
protected $table = 'pengelola_pendidikan';
protected static $logFillable = true;
protected $fillable = [
'id_pengelola','name','tingkat','tempat','mulai','selesai','sekarang'
];
protected $filter = [
'name','tingkat','tempat','mulai','selesai','sekarang','created_at','updated_at'
];
public function getNameAttribute($value){
return !empty($value) ? $value : '-';
}
public static function initialize()
{
return [
'name' => '','tingkat' => '','tempat' => '','mulai' => '','selesai' => '','sekarang' => ''
];
}
}
and here is pengelola_pekerjaan
class PengelolaPekerjaan extends Model {
use FilterPaginateOrder, LogsActivity;
protected $table = 'pengelola_pekerjaan';
protected static $logFillable = true;
protected $fillable = [
'id_pengelola','id_tempat','tipe','name','tingkat','mulai','selesai','sekarang'
];
protected $filter = [
'id_tempat','tipe','name','tingkat','mulai','selesai','sekarang','created_at','updated_at'
];
public function getNameAttribute($value){
return !empty($value) ? $value : '-';
}
public static function initialize()
{
return [
'id_tempat' => 0,'tipe' => '','name' => '','tingkat' => '','mulai' => '','selesai' => '','sekarang' => ''
];
}
public function pengelola(){
return $this->belongsTo('App\Pengelola','id_pengelola','id');
}
public function lembaga(){
return $this->belongsTo('App\Lembaga','id_tempat','id')->select(array('id','name'));
}
public function cu(){
return $this->belongsTo('App\Cu','id_tempat','id')->select(array('id','no_ba','name'))->withTrashed();
}
}
and as you can see in whereHas
I am using 2 external variables which are $tipe
and $id
, so this query is working fine if my $tipe = 1
but when my $tipe
is not 1
then it won't return anything.
and then if I change my $table_data
query to be this (only remove select at pengelola_pendidikan
) then it will work for any $tipe
$table_data = Pengelola::with('pekerjaan_aktif.cu','pendidikan_tertinggi')
->whereHas('pekerjaan', function($query) use ($id,$tipe){
$query->where('tipe',$tipe)->where('id_tempat',$id)
->where(function($q){
$q->where('sekarang','1')->orWhere('selesai','>',date('Y-m-d'));
});
})->select('*',DB::raw('
(SELECT name from pengelola_pekerjaan WHERE pengelola.id = pengelola_pekerjaan.id_pengelola) as pekerjaan_name,
(SELECT tingkat from pengelola_pekerjaan WHERE pengelola.id = pengelola_pekerjaan.id_pengelola) as pekerjaan_tingkat
'))->get();
So what is really happen? and for those who wonder why I need this kind of select, it is because I need to have a column alias that appears at the root of the returned json for my trait FilterPaginateOrder
that handles searching, sorting, pagination. and to do that I need to have pekerjaan_name
instead of pekerjaan_aktif.name
(for example) for sorting purpose to this trait.
trait FilterPaginateOrder {
protected $operators = [
'equal_to' => '=',
'not_equal' => '<>',
'less_than' => '<',
'greater_than' => '>',
'less_than_or_equal_to' => '<=',
'greater_than_or_equal_to' => '>=',
'in' => 'IN',
'not_in' => 'NOT_IN',
'like' => 'LIKE',
'between' => 'BETWEEN'
];
public function scopeFilterPaginateOrder($query)
{
$request = request();
$v = Validator::make($request->all(), [
'column' => 'required|in:'.implode(',', $this->filter),
'direction' => 'required|in:asc,desc',
'per_page' => 'required|integer|min:1',
'search_operator' => 'required|in:'.implode(',', array_keys($this->operators)),
'search_column' => 'required|in:'.implode(',', $this->filter),
'search_query_1' => 'max:255',
'search_query_2' => 'max:255'
]);
if($v->fails()) {
//for debug
// dd($v->messages());
}
return $query->orderBy($request->column, $request->direction)
->where(function($query) use ($request) {
// check if search query is empty
if($request->has('search_query_1')) {
// determine the type of search_column
// check if its related model, eg: customer.id
if($this->isRelatedColumn($request)) {
list($relation, $relatedColumn) = explode('.', $request->search_column);
return $query->whereHas($relation, function($query) use ($relatedColumn, $request) {
return $this->buildQuery(
$relatedColumn,
$request->search_operator,
$request,
$query
);
});
} else {
// regular column
return $this->buildQuery(
$request->search_column,
$request->search_operator,
$request,
$query
);
}
}
})
->paginate($request->per_page);
}
protected function isRelatedColumn($request)
{
return strpos($request->search_column, '.') !== false;
}
protected function buildQuery($column, $operator, $request, $query)
{
switch ($operator) {
case 'equal_to':
case 'not_equal':
case 'less_than':
case 'greater_than':
case 'less_than_or_equal_to':
case 'greater_than_or_equal_to':
$query->where($column, $this->operators[$operator], $request->search_query_1);
break;
case 'in':
$query->whereIn($column, explode(',', $request->search_query_1));
break;
case 'not_in':
$query->whereNotIn($column, explode(',', $request->search_query_1));
break;
case 'like':
$query->where($column, 'like', '%'.$request->search_query_1.'%');
break;
case 'between':
$query->whereBetween($column, [
$request->search_query_1,
$request->search_query_2
]);
break;
default:
throw new Exception('Invalid Search Operator', 1);
break;
}
return $query;
}
}
So what I need is a solution for having a root field that created from select as from relation table column ( pendidikan_name
instead of pendidikan_tertinggi.name
and also cu_name
instead of pekerjaan_aktif.cu.name
at my json return) for it to work with my FilterPaginateOrder
trait.
To me this is more about joins and a SQL issue than Laravel Eloquent's problem.
Try to debug with DB::connection()->enableQueryLog();
at the begining of the code, and after the call to you model, you can use DB::getQueryLog()
So this way you will be able to check the generated query and fix whatever is causing the issue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.