I have added left join inside with but it is not working at all.
Please suggest or guide.
$q = $q->leftJoin('product_sort_order', function ($join) {
$join->on('products.id', '=', 'product_sort_order.product_id');
$join->on('products.sub_category_id', '=', 'product_sort_order.type_id');
})->orderBy('product_sort_order.sort_order', 'ASC');
Controller code (trying to get category products with relationship)
$category = Category::query();
$category->where('status', '=', '1');
$category->where('id', $sub_category_id);
// $category->where('status', '!=', '2');
$category = $category->with([
'subproducts' => function ($q) use ($request, $sub_category_id) {
$q->select('products.*');
$q->where('products.status', '=', 1);
$q->where('products.is_pendding', '=', 0);
$q->where('products.sub_category_id', $sub_category_id);
if ($request->get('theme')) {
$q->Where('products.theme_id', 'LIKE', '%' . $request->get('theme') . '%');
}
if ($request->get('categories')) {
$q->where('products.category_id', getCategoryIdFromSlug($request->get('categories')));
}
if ($request->get('sections')) {
$q->where('products.section_category_id', getSectionIdFromSlug($request->get('sections')));
}
if ((App::getLocale()) == 'en') {
// $q->orderBy('product_name_lang->en');
} else {
// $q->orderBy('product_name_lang->fr');
}
if ($request->get_j0_product == true) {
$q->where('products.delivery', 'J0');
}
// $q->orderBy('sale_price', 'DESC');
// $q->orderBy('created_at', 'DESC');
// $q = $q->leftJoin('product_sort_order', function ($join) {
// $join->on('products.id', '=', 'product_sort_order.product_id');
// $join->on('products.sub_category_id', '=', 'product_sort_order.type_id');
// })->orderBy('product_sort_order.sort_order', 'ASC');
}
])->first();
model relationship inside category
public function subproducts(){
return $this->hasMany(Product::class,'sub_category_id','id');
}
Related
public function scopeSearch($query, $value)
{
$searchValues = explode(' ', $value);
if (!$value) return $query;
return $query->where(function ($q) use ($searchValues) {
foreach ($searchValues as $token) {
$q->orWhere('name', 'like', "%{$token}%");
$q->orWhere('street', 'like', "%{$token}%");
}
});
}
I want to search the data. This model also has
public function brands()
{
return $this->belongsToMany(Brand::class, 'dealer_brands');
}
public function province()
{
return $this->belongsTo(Province::class);
}
How can I get data from the relastionship. Like Dealer(model) has data Nmae = josh , brand_id = 1 {brand.name = samsung} , province_id = 2 (province.name = "aligora"). When I search Josh Samsung Alogora, I want to ge the data. When I only search aligora, I want to get the data of model having province aligora. hOW CAN I MODIFY CODE?
looking at your model relationships. This may work for you
public function scopeSearch($query, $value)
{
if (!$value) return $query;
$searchValues = explode(' ', $value);
return $query->where(function ($q) use ($searchValues) {
foreach ($searchValues as $token) {
$q->where('name', 'like', "%{$token}%")
->orWhere('street', 'like', "%{$token}%")
->orWhereHas('brands', function ($sub_q) use ($searchValues) {
$sub_q->where('name', 'like', "%{$token}%")
->orWhere('street', 'like', "%{$token}%");
})
->orWhereHas('province', function ($sub_q) use ($searchValues) {
$sub_q->where('name', 'like', "%{$token}%")
->orWhere('street', 'like', "%{$token}%");
});
}
});
}
I have no idea about column names in related tables so repeating name and street. you can change as per requirement
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 tried to make a search function based on 4 requests; categories, location, keyword, and sorting. The search function with 3 requests (location, categories, and sorting) works well and has correct output.
But the problem is, when my website sent request with keywords data, the output results are only the result from keywords request only, when I try to sent a location / categories requests, the output does not change (only the output of the keyword request only)
Here is the code I write:
public function getBy(Request $request) {
$categories = $request->all()['categories'];
$location = $request->all()['location'];
$sorting = $request->all()['sorting'];
$keyword = $request->all()['keyword'];
//--- sorting code ---
//keyword request
if ($keyword === null) {
$jobs = Job::query();
} else {
$jobs = Job::query()->where('job_title', 'LIKE', "%{$keyword}%")
->orWhere('title', 'LIKE', "%{$keyword}%")
->orWhere('description', 'LIKE', "%{$keyword}%")
->orWhereHas('users', function ($q) use ($keyword) {
$q->where('company_name', 'LIKE', "%{$keyword}%");
})->orWhereHas('categories', function ($q) use ($keyword) {
$q->where('category', 'LIKE', "%{$keyword}%");
})->orWhereJsonContains('tags', $keyword);
}
//location and categories request
if ($location === [] && $categories === []) {
$jobs;
} elseif ($location === []) {
$jobs->whereHas('categories', function ($q) use ($categories) {
$q->whereIn('slugs', $categories);
});
} elseif ($categories === []) {
$jobs->whereHas('location', function ($q) use ($location) {
$q->whereIn('city_name', $location);
});
} else {
$jobs->whereHas('categories', function ($q) use ($categories) {
$q->whereIn('slugs', $categories);
})->whereHas('location', function ($q) use ($location) {
$q->whereIn('city_name', $location);
});
}
//return as JSON
}
The main issue with your code is your locations and categories search query were not setting $jobs again. It should look like this:
$jobs = $jobs->whereHas('categories', function ($q) use ($categories) {
$q->whereIn('slugs', $categories);
});
This will set the $jobs variable to include the new conditions of the query.
I would also suggest not checking if $locations or $categories are empty, as they if statements for each are dealing with the condition already. Here is some refactored code:
public function getBy(Request $request) {
$sorting = $request->all()['sorting'];
//--- sorting code ---
//keyword request
if (! $keywords = request('keywords')) {
$jobs = Job::query();
} else {
$jobs = Job::query()->where('job_title', 'LIKE', "%{$keyword}%")
->orWhere('title', 'LIKE', "%{$keyword}%")
->orWhere('description', 'LIKE', "%{$keyword}%")
->orWhereHas('users', function ($q) use ($keyword) {
$q->where('company_name', 'LIKE', "%{$keyword}%");
})->orWhereHas('categories', function ($q) use ($keyword) {
$q->where('category', 'LIKE', "%{$keyword}%");
})->orWhereJsonContains('tags', $keyword);
}
foreach (['categories', 'locations'] as $field) {
if ($request->filled($field)) {
$jobs = $jobs->whereHas($field, function ($q) use ($field) {
$q->whereIn('slugs', request($field));
});
}
}
return $jobs->get()->toArray();
}
Here we loop through the categories and locations request data and see if the data is ->filled() (is defined and not empty). If so, we run the query.
Try this
public function getBy(Request $request) {
$categories = $request->categories;
$location = $request->location;
$sorting = $request->sorting;
$keyword = $request->keyword;
//--- sorting code ---
$jobs = Job::query();
//keyword request
if ($keyword !== null) {
$jobs = $jobs->where('job_title', 'LIKE', "%{$keyword}%")
->orWhere('title', 'LIKE', "%{$keyword}%")
->orWhere('description', 'LIKE', "%{$keyword}%")
->orWhereHas('users', function ($q) use ($keyword) {
$q->where('company_name', 'LIKE', "%{$keyword}%");
})->orWhereHas('categories', function ($q) use ($keyword) {
$q->where('category', 'LIKE', "%{$keyword}%");
})->orWhereJsonContains('tags', $keyword);
}
//location and categories request
if ($location === []) {
$jobs = $jobs->whereHas('categories', function ($q) use ($categories) {
$q->whereIn('slugs', $categories);
});
} elseif ($categories === []) {
$jobs = $jobs->whereHas('location', function ($q) use ($location) {
$q->whereIn('city_name', $location);
});
} else {
$jobs = $jobs->whereHas('categories', function ($q) use ($categories) {
$q->whereIn('slugs', $categories);
})->whereHas('location', function ($q) use ($location) {
$q->whereIn('city_name', $location);
});
}
return $jobs->get();
}
I am attempting to use the following
$orders = \App\Order::with([
'Customer' => function ($query) use ($filterFirst, $filterLast, $filterstate)
{
if($filterFirst)
{
$query->where('customers.first', 'LIKE', "{$filterFirst}%");
}
if($filterLast)
{
$query->where('customers.last', 'LIKE', "{$filterLast}%");
}
if ($filterstate)
{
$query->where('customers.state', '=', $filterstate);
}
},
'Group' => function ($query) use ($filtercategory)
{
if($filtercategory)
{
$query->where('order_groups.groupid', '=', $filtercategory);
}
},
'Group.ProductGroups' => function ($query) use ($filteractualcat)
{
if($filteractualcat)
{
$query->where('productgroups.cat', '=', $filteractualcat);
}
},
'Group.ProductGroups.Category',
'Doctor',
'Status' => function ($query) use ($filterstatus)
{
if ($filterstatus)
{
$query->whereIn('statuses.id', $filterstatus);
}
},
'Signed'
])->where(function ($query) use ($id, $filterlab, $filterStart, $filterEnd, $filterRep) {
if ($id)
{
$query->where('orders.id', $id);
}
if ($filterlab)
{
$query->where('orders.labid', $filterlab);
}
if ($filterStart || $filterEnd)
{
if ($filterStart && $filterEnd)
{
$query->whereBetween('orders.created_at', [$filterStart, $filterEnd]);
}
else
{
if ($filterStart && !$filterEnd)
{
$query->where('orders.created_at', '>=', $filterStart);
}
else
{
$query->where('orders.created_at', '<=', $filterEnd);
}
}
}
if ($filterRep)
{
$query->where('salesrep', $filterRep);
}
})->orderBy('orders.created_at', 'ASC');
However, when I run ->get on $orders I get the entire table of orders, and I just want to get the orders that match the Filters...
Any ideas on how I can accomplish this?
Use whereHas() to filter orders by customer filters:
$orders = \App\Order::whereHas('Customer', function ($query) use ($filterFirst, $filterLast, $filterstate) {
if ($filterFirst) {
$query->where('first', 'like', $filterFirst . '%');
}
if ($filterLast) {
$query->where('last', 'like', $filterLast . '%');
}
if ($filterstate) {
$query->where('state', $filterstate);
}
})
->get();
If you also want to load customers for orders, add with to the query.
I have the following function
public function index(Request $request)
{
$results = Service::whereHas('conditions', function ($query) use ($request){
$query->whereIn('id', $request->conditions);
})
->whereHas('locations', function ($query) use ($request){
$ran = false;
foreach($request->locations as $location)
{
if(!$ran)
{
$query->Where('town', 'like', '%'.$location.'%')
->orWhere('city', 'like', '%'.$location.'%');
}
else
{
$query->orWhere('town', 'like', '%'.$location.'%')
->orWhere('city', 'like', '%'.$location.'%');
}
$ran = true;
}
})
->with('types', 'contacts', 'locations.datetimes')->toSql();
dd($results);
}
which produces
select * from `services` where exists
(select * from `conditions` inner join `condition_service` on `conditions`.`id` = `condition_service`.`condition_id` where `services`.`id` = `condition_service`.`service_id` and `id` in (13, 14) and `conditions`.`deleted_at` is null)
and exists
(select * from `service_locations` inner join `service_location_service` on `service_locations`.`id` = `service_location_service`.`service_location_id` where `services`.`id` = `service_location_service`.`service_id` and
(`town` like 'manchester' or `city` like 'manchester' or `town` like 'crewe' or `city` like 'crewe')
and `service_locations`.`deleted_at` is null) and `services`.`deleted_at` is null
The problem is the whereHas on locations brings back all results, whereas I only want the result where the town/city is a match. Whats the best way to achieve this?
i think you need to group your location query using the callback which wraps the query in () and just process the first location directly remove it from array and iterate over loop. so below code should work in your case.
$results = Service::whereHas('conditions', function ($query) use ($request){
$query->whereIn('id', $request->conditions);
})
->whereHas('locations', function ($query) use ($request){
$locations = $request->locations;
$query->where(function($builder) use($locations){
$builder->where('town', 'like', '%' . $locations[0] . '%')
->orWhere('city', 'like', '%'.$locations[0].'%');
unset($locations[0]); //remove first item as it is processed
foreach($locations as $location) {
$builder->orWhere('town', 'like', '%'.$location.'%')
->orWhere('city', 'like', '%'.$location.'%');
}
});
});
let me know if you find any problem with it. :)
I managed to figure it out late last night.
I moved the with() to the top of the query and made a callback on locations.
public static function newGetSearchResults($request)
{
return Service::with(['types', 'contacts', 'locations.datetimes', 'locations' => function($query) use($request) {
$ran = false;
foreach($request->locations as $location)
{
if(!$ran)
{
$query->Where('town', 'like', '%'.$location.'%')
->orWhere('city', 'like', '%'.$location.'%');
}
else
{
$query->orWhere('town', 'like', '%'.$location.'%')
->orWhere('city', 'like', '%'.$location.'%');
}
$ran = true;
}
}])
->whereHas('conditions', function ($query) use ($request){
$query->whereIn('id', $request->conditions);
})->get();
}