Eloquent - how to add a join in the hasMany relationship? - laravel

I have a typical hasMany method:
public function earmarks() {
return $this->hasMany('App\Earmark');
}
But how do I add a join and some other conditions to this relationship when I use the ->with('earmarks') to retrieve them? I want to add:
->join('locations', 'locations.id', '=', 'earmarks.location')
->select('earmarks.*', 'locations.location AS em_location')
->orderBy('date', 'asc');

OK, figured out I need a closure in my with() clause, like this:
$updated_laptops = Laptop::with([
'earmarks' => function($q) {
$q
->join('locations', 'locations.id', '=', 'earmarks.location')
->select('earmarks.*', 'locations.location AS em_location')
->orderBy('date', 'asc');
}
])->addJoins()->selectListCols()->find($request->IDs)->keyBy('id');

this worked for me
public function earmarks() {
return $this->hasMany('App\Earmark', 'labtop_id', 'id')
->join('locations', 'locations.id', '=', 'earmarks.location')
->select('earmarks.*', 'locations.location AS em_location')
->orderBy('date', 'asc')->get();
}
it can be a attribute in Labtop Model and be serializable in Labtop json object like this :
public function GetEarmarksAttribute() {
return $this->hasMany('App\Earmark', 'labtop_id', 'id')
->join('locations', 'locations.id', '=', 'earmarks.location')
->select('earmarks.*', 'locations.location AS em_location')
->orderBy('date', 'asc')->get();
}
protected $appends = array('earmarks');

When you defined a hasMany method in the Location model (e.g. \App\Models\Location.php)
public function earmarks() {
return $this->hasMany('App\Earmark');
}
You can return a Location object in Controller (e.g. LocationController.php ):
public function show($id)
{
$location = \App\Models\Location::find($id);
return view('locations.show)
->with('location', $location);
}
Then in the view (e.g. locations\show.blade.php), you can retrieve the data like this:
#foreach ($location->earmarks->sortBy('date') as $earmark )
<p>{{ $earmark->attribute_name }}</p>
#endforeach

Related

Search result with multiple tables relation in Laravel6

I'm trying to make search function with relation.
I could display all result using relation And an another code, simple one table search and get result works fine.
but I can't combine those two.
Could you teach me how to combine multiple tables into search function please?
public function order(Request $request)
{
$data = $request->all();
$products = Product::All();
$products = Product::with('categori')
->join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->get();
$products = Product::when($data['categori_id'], function ($query, $categori_id) {
return $query->where('categori_id', $categori_id);
})->
when($data['color_id'], function ($query, $color_id) {
return $query->where('color_id', $color_id);
})->get();
//return view('result_fb', compact('images'));
$data = array(
'title' => 'index',
'no' => 1,
'products' => $products,
);
return view('product.result', $data);
}
I am not sure if you need 'categori' relation to be loaded or not as there are few $products without it. For general, you can combine all your $products queries to one as follows:
$products = Product::join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->when($data['categori_id'], function ($query, $categori_id) use ($data) {
return $query->where('categori_id', $data['categori_id']);
})
->when($data['color_id'], function ($query) use ($data) {
return $query->where('color_id', $data['color_id']);
})->get();
If you want to use eager loading with eloquent rather then join, you can use like
$products = Product::with(['creator','categori','branch','user','color'])
->when($data['categori_id'], function ($query, $categori_id) use ($data) {
return $query->where('categori_id', $data['categori_id']);
})
->when($data['color_id'], function ($query) use ($data) {
return $query->where('color_id', $data['color_id']);
})->get();
But for that you Product model should have relations with same name as follows for categori relation:
class Product extends Model
{
public function categori()
{
return $this->belongsTo(Categori::class,'categori_id','id);
}
}
Same way you have to define for all relation used for product.
Try this:
$products = Product::with('categori')
->join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->when($data['categori_id'], function ($query, $categori_id) {
return $query->where('categori_id', $categori_id);
})
->when($data['color_id'], function ($query, $color_id) {
return $query->where('color_id', $color_id);
})
->get();

I can't use variable in a function whereHas

I'm new with laravel. I can't use $class _id in a function whereHas. What should I do?
public function show($classroom_id)
{
$classrooms = Group::whereHas('members', function ($query) {
$query->where([['user_id', '=', Auth::id()], ['classroom_id', $classroom_id]]);
})->get();
return response()->json($classrooms);
}
See use (classroom_id)
$groups = Group::whereHas('natures', function($q) use($classroom_id)
{
$q->where('classroom_id', '=', $classroom_id);
});

Laravel search with relations

I have the following relations in my Laravel application
class Item extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
and
class Category extends Model
{
public function item()
{
return $this->hasMany('App\Item');
}
}
I want to implement search functionality so I have created the following Eloquent query:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query->where('item_name','LIKE','%'.$q.'%')
->orWhere('item_description','LIKE','%'.$q.'%');
})
->paginate(10);
This is working as expected and returns the search results for 'q' based on the name and the description of the item.
As a next step, I would like to also search for the category_name. Because of the relation, I have the category_id stored in the Items table, but I would like to use the category_name in my Eloquent query.
Anyone could provide some help?
Based on feedback received, I tried:
Suggestion 1:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query
->where('item_name', 'LIKE' ,'%'.$q.'%')
->orWhere('item_description', 'LIKE' ,'%'.$q.'%');
})
->whereHas('category', function (Category $query) use ($q) {
$query->where('category_name', $q);
})
=> this gives following error message:
Argument 1 passed to
App\Http\Controllers\ItemController::App\Http\Controllers{closure}()
must be an instance of App\Http\Controllers\App\Category, instance of
Illuminate\Database\Eloquent\Builder given
Suggestion 2:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query
->where('item_name', 'LIKE' ,'%'.$q.'%')
->orWhere('item_description', 'LIKE' ,'%'.$q.'%');
})
->whereHas('category', function ($query) use ($q) {
$query->where('category_name', $q);
})
=> this does not result any search result anymore (also not for item_name and item_description).
Solution
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query
->where('item_name', 'LIKE' ,'%'.$q.'%')
->orWhere('item_description', 'LIKE' ,'%'.$q.'%');
})
->orWhereHas('category', function ($query) use ($q) {
$query->where('category_name', $q);
})
->sortable(['id' => 'desc'])
->paginate(10);
As you already described relation to Category in your Item model, you have to use just whereHas method:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query->where('item_name','LIKE','%'.$q.'%')
->orWhere('item_description','LIKE','%'.$q.'%');
})
->orWhereHas('category', function ($query) use ($q) {
$query->where('category_name', 'LIKE', "%$q%");
})
->paginate(10);
You could add a whereHas and constrain it. For example:
$items = Item::where('item_type', '=', 'type1')
->where(function($query) use ($q) {
$query->where('item_name','LIKE','%'.$q.'%')
->orWhere('item_description','LIKE','%'.$q.'%');
})
->whereHas('category', function($query) {
$query->where('category_name', 'name');
})
->paginate(10);

join query result in "Call to a member function leftJoin() on null"

I am trying to run a join query from my controller on laravel but i am getting "Call to a member function leftJoin() on null"
public function tracking_groupindividual(Request $request)
{
$user_id = $request->user_id;
$group_id = $request->group_id;
$get_group_individual_details = DB::table('group_usermapping as gu')
->select(
'um.user_id',
'um.user_name',
'um.image_path',
'um.mobile_number',
'ul.latitude',
'ul.longitude',
'um.isnearby_on',
'gu.isadmin',
'um.profile_status',
'ul.timedout'
)
->join('user_master as um','gu.user_id','=','um.user_id')
->join('groupusers_location as ul','ul.user_id','=','um.user_id','ul.group_id','=','gu.group_id')
->where(function ($query) use ($group_id) {
$query->where('gu.group_id', '=', $group_id)
->where('gu.isactive','=','1')->where('um.isactive','=','1');
})->get();
return $get_group_individual_details;
}
I found a problem in the second join and fixed it
public function tracking_groupindividual(Request $request)
{
$user_id = $request->user_id;
$group_id = $request->group_id;
$get_group_individual_details = DB::table('group_usermapping as gu')
->select(
'um.user_id',
'um.user_name',
'um.image_path',
'um.mobile_number',
'ul.latitude',
'ul.longitude',
'um.isnearby_on',
'gu.isadmin',
'um.profile_status',
'ul.timedout'
)
->join('user_master as um','gu.user_id','=','um.user_id')
->join('groupusers_location as ul', function ($join) {
$join->on('ul.user_id','=','um.user_id')
->where('ul.group_id','=','gu.group_id');
})
->where(function ($query) use ($group_id) {
$query->where('gu.group_id', '=', $group_id)
->where('gu.isactive','=','1')->where('um.isactive','=','1');
})->get();
return $get_group_individual_details;
}
try to use DB::raw() with aliases!!!
$get_group_individual_details = DB::table(DB::raw('group_usermapping as gu'))
->join(DB::raw('user_master as um'),DB::raw('gu.user_id'),'=',DB::raw('um.user_id'))
->join(DB::raw('groupusers_location as ul'),DB::raw('ul.user_id'),'=',DB::raw('um.user_id'),DB::raw('ul.group_id'),'=',DB::raw('gu.group_id'))
->select(DB::raw('um.user_id'),DB::raw('um.user_name'),DB::raw('um.image_path'),DB::raw('um.mobile_number'),DB::raw('ul.latitude'),DB::raw('ul.longitude'),DB::raw('um.isnearby_on'),DB::raw('gu.isadmin'),DB::raw('um.profile_status'),DB::raw('ul.timedout'))
->where(function ($query) use ($group_id) {
$query->where(DB::raw('gu.group_id'), '=', $group_id)->where(DB::raw('gu.isactive'),'=','1')->where(DB::raw('um.isactive'),'=','1');
})->get();
return $get_group_individual_details;
and replace use Illuminate\Support\Facades\DB; with use DB;

Laravel 5.3 eloquent 3 table join using models

I read this post which helped, but need more guidance please.
I need a set of Results for a particular $batteryid (on Result) and a particular $age (on Test model) and a particular $gender (from Athlete). Each Test belongs to one athlete. Each test has many results.
Model Battery:
class Battery extends Model{
public function results(){
return $this->hasMany('App\Result');
}
}
Model Result:
class Result extends Model{
public function test(){
return $this->belongsTo('App\Test', 'test_id');
}
public function battery(){
return $this->belongsTo('App\Battery', 'battery_id');
}
}
Model Test:
class Test extends Model{
public function athlete(){
return $this->belongsTo('App\Athlete', 'athlete_id');
}
public function results(){
return $this->hasMany('App\Result');
}
}
I get the correct results with the following, but it's two queries:
$tests = Test::whereHas('Athlete', function($query) use($gender){
$query->wheregender($gender);
})->where('age', $age)->get();
$test_ids = $tests->pluck('id');
$results = Result::where('battery_id', '=', $battery)
->whereIn('test_id', $test_ids)
->get();
I'd like to use model approach, but am completely stuck. test.age not recognised and not sure how to get the age from athlete model. My attempt:
$results = Result::with('test')
->where('test.age', '=', $age)
->join('batteries', 'batteries.id', '=', 'test.battery_id')
//->where('test->athlete().gender', '=' $gender)
->where('battery_id', '=', $battery)
->get();
You can use whereHas for the condition and with method for eager loading it.
$results = Result::whereHas('test', function($q) use ($age) {
$q->where('age', '=', $age);
$q->whereHas('athlete', function ($q) {
$q->where('gender', 'male');
});
})
->with('test')
->whereHas('battery', function($q) use($battery) {
$q->where('battery_id', '=', $battery);
})
->with('battery')
->get();

Resources