Undefined variable '$category'. when using queries [closed] - laravel

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
intelephense is giving me a syntax error in when writing this code, clearly $category was passed so what is the problem?
public function scopeFilter($query, array $filters)
{
$query->when($filters['search'] ?? false, function ($query, $search) {
$query->where('title', 'like', '%' . $search . '%')->orWhere('body', 'like', '%' . $search . '%');
});
$query->when(
$filters['category'] ?? false,
function ($query, $category) {
$query
->whereExists(
function ($query) {
$query->from('categories')
->whereColumn('categories.id', 'posts.category_id')
->where('categories.slug', $category);
}
);
}
);
}

You can pass the necessary variables from the parent scope into the closure with the use keyword.
$query->when(
$filters['category'] ?? false,
function ($query, $category) {
$query
->whereExists(
function ($query) use ($category) {
$query->from('categories')
->whereColumn('categories.id', 'posts.category_id')
->where('categories.slug', $category);
}
);
}
);

Related

Laravel 8 relationship search returning empty result

I have this query:
$orders = Order::with(['company', 'products', 'user', 'status', 'seller'])->orderBy('id', 'DESC')->select('orders.*');
And it returns the relevant results as expected in a yajra datatable instance.
Now I would like to narrow down this result even more. I use it this way:
$orders = $orders->whereHas('user', function ($q) use ($request){
$q->searchFullName($request->seller);
});
I have created a scope in the model and it works for another function on my website. However it returns no results when calling it like that.
Even if I call the whereHas using a where statement, still the result is empty:
$orders = $orders->whereHas('user', function ($q) use ($request){
$q->where('first_name', 'like', '%'.$request->seller.'%');
});
The seller parameter is not empty. Even if I use a hardcoded string, the results are always empty.
The searchFullName method:
public function scopesearchFullName($query, $value){
return $query->where('first_name', 'LIKE', "%$value%")
->orWhere('middle_name', 'LIKE', "%$value%")
->orWhere('last_name', 'LIKE', "%$value%");
}
Full controller:
public function listOrdersData(Request $request)
{
if(!$request->ajax())
return Redirect::route('/');
$loggedUser = Auth::user();
if($loggedUser->hasRole('Super Administratör'))
$orders = Order::with(['company', 'products', 'user', 'status', 'seller'])->orderBy('orders.id', 'DESC')->select('orders.*');
else
$orders = Order::with(['company', 'products', 'user', 'status', 'seller'])->where('company_id', $loggedUser->company_id)->orderBy('id', 'DESC')->select('orders.*');
if (!empty($request->seller) && $request->seller != 'all') {
$orders = $orders->whereHas('user', function ($q) use ($request){
$q->searchFullName($request->seller);
});
}
return DataTables::of($orders)
->addColumn('products', function($orders) {
$products = "";
foreach($orders->products as $product)
$products = $products . $product->name . "<br>";
return $products;
})
->editColumn('company', function($orders){ return $orders->company->name; })
->editColumn('price', '{{$price}} kr')
->editColumn('user', function($orders){
return $orders->user->full_name;
})
->addColumn('seller', function($orders){
return $orders->seller->full_name;
})
->addColumn('status', function($orders){
return '<span class="chip lighten-4 purple purple-text">'. $orders->status->localized . '</span>';
})
->addColumn('contract', '<i class="material-icons">file_download</i>')
->addColumn('edit', '<i class="material-icons">edit</i>')
->rawColumns(['products', 'status', 'edit', 'contract'])
->make(true);
}
The issue is with scope method
public function scopesearchFullName($query, $value){
return $query->where('first_name', 'LIKE', "%".$value."%")
->orWhere('middle_name', 'LIKE', "%".$value."%")
->orWhere('last_name', 'LIKE', "%".$value."%");
}
Also make sure that only those user record returns who has orders.
Also for searching sellers order
$orders = $orders->whereHas('seller', function ($q) use ($request){
$q->searchFullName($request->seller);
});
so in Order model
public function seller()
{
return $this->belongsTo(User::class, 'seller_id', 'id');
}

Laravel with where like condition in relationship

I have a WorkPackage model with below relationship.
public function work_items()
{
return $this->hasMany(WorkItem::class);
}
And WorkPackage has 'title','project_id' columns and work_items has 'title','work_package_id' columns. Now I want to search user typed keyword is matching with title in both table.
Here is my tried function
public function getWorkPackageProposals($projectId, $title)
{
$result['data'] = $this->workPackage->with(['work_items' => function ($query) {
$query->where('title', 'LIKE', "%{$title}%");
}])
->where('project_id', $projectId)
->where('title', 'LIKE', "%{$title}%")
->get();
return $result;
}
but its not working.
Please find the below code for I used to create object of WorkPackage.
public function __construct(WorkPackage $workPackage)
{
$this->workPackage = $workPackage;
$this->setModel(WorkPackage::class);
$this->workItemRepository = app(WorkItemRepository::class);
}
whereHas() works to specify additional filters for the related model to check :
$result['data'] = $this->workPackage->whereHas('work_items', function ($query) use ($title) {
$query->where('title', 'LIKE', "%{$title}%");
})
->where('project_id', $projectId)
->where('title', 'LIKE', "%{$title}%")
->get();
return $result;
Below code works for me. Thanks to everyone for help to get right answer.
$result['data'] = $this->workPackage->with(['work_items' => function ($q) use ($title) {
$q->where('title', 'LIKE', "%{$title}%");
}])
->where('project_id', $projectId)
->where('title', 'LIKE', "%{$title}%")
->get();
return $result;
I think your problem will be solved with join method:
$result = $this->workPackage
->join('work_items', 'work_packages.id', '=', 'work_items.package_id')
->where('work_items.title', 'LIKE', '%{$term}%')
->orWhere('work_packages.title', 'LIKE', '%{$term}%')
->get();

Laravel dynamic query

I have a GET form with three filters.
make
Year
country
I need to get all posts from db. But filter the results based on these three filters.
If a country is selected, get posts for that country only or all countries.
if a make is selected, get posts for that make only or all makes
if a year is selected, get posts for that year only or all years
how to write one query that filters all these three options. What I have done is used if and else statements and written different queries for each scenario. That's 9 queries to get one information. Can we make it dynamic and just have one query?
My Example query:
public function search(Request $request)
{
$search=$request->input('search');
if($request->input('country') == "all")
{
$posts = Post::where('status','Published')->orderBy('status_change','DESC')
->where('status','Published')
->where(function($query) use ($search){
$query->where('title','LIKE','%'.$search.'%');
$query->orWhere('model','LIKE','%'.$search.'%');
$query->orWhere('notes','LIKE','%'.$search.'%');
$query->orWhere('description','LIKE','%'.$search.'%');
})
->paginate(25);
}
else
{
$posts = Country::where('country_name', $request->input('country'))->first()->posts()->orderBy('status_change','DESC')
->where('status','Published')
->where(function($query) use ($search){
$query->where('title','LIKE','%'.$search.'%');
$query->orWhere('model','LIKE','%'.$search.'%');
$query->orWhere('notes','LIKE','%'.$search.'%');
$query->orWhere('description','LIKE','%'.$search.'%');
})
->paginate(25);
}
return view('welcome')
->with('published_posts',$posts)
;
}
I think something like this would work:
/**
* #param Request $request
*/
function search(Request $request)
{
$postsQuery = Post::where('status', 'Published');
if ($request->has('country')) {
$country = $request->country;
// assuming relationships are setup correclty
$postsQuery->whereHas('country', function ($query) use ($country) {
$query->where('country_name', 'LIKE', $country);
});
}
if ($request->has('search')) {
$postsQuery->where(function ($query) use ($search) {
$query->where('title', 'LIKE', '%' . $request->search . '%');
$query->orWhere('model', 'LIKE', '%' . $request->search . '%');
$query->orWhere('notes', 'LIKE', '%' . $request->search . '%');
$query->orWhere('description', 'LIKE', '%' . $request->search . '%');
});
}
$postsQuery->orderBy('status_change', 'DESC')->paginate(25);
return view('welcome')->with('published_posts', $result);
}
I used 'when' method.
$make = null;
$year = null;
$country = null;
if($request->filled('make')){
$make = $request->query('make');
}
if($request->filled('year')){
$year = $request->query('year');
}
if($request->filled('country')){
$country = $request->query('country');
}
$posts = DB::table('posts')
->when($make, function($query, $make){
return $query->where("make", "=", $make);
})
->when($year, function($query, $year){
return $query->whereYear("year", "=", $year);
})
->when($country, function($query, $country){
return $query->where('country', "like", $country);
})
->get();
Check out the Laravel Docs:
Check out an article here

return all the posts where author.username equals $username

I have a posts model that has this relationship to the User:
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
i am building a search function and I have this code
public function index(Request $request)
{
$search = $request->search;
$filter = $request->filter;
$append = array();
$posts = Post::with('author')->with('categories')->latest();
if($search){
switch ($filter) {
case 'username':
$posts->author->where('username', 'LIKE', '%'. $search . '%');
break;
}
$append += array('search' => $search);
$append += array('filter' => $filter);
}
$posts = $posts->paginate(3);
$posts->appends($append);
return view('core.blog.posts.index', compact('posts'));
}
I get
Undefined property: Illuminate\Database\Eloquent\Builder::$author
How do I add where that looks for author based on his username? I must be able to add this condition in an if case
You want to use whereHas() to searched based on a relation. This will return only posts that have an author with the username.
switch ($filter) {
case 'username':
$posts->whereHas('author', function($q) use($search) {
$q->where('username', 'LIKE', '%'. $search . '%');
});
break;
}
UPDATE
If you need conditional where, you can do this:
$postSelector = Post::with('categories');
if($search){
switch ($filter) {
case 'username':
$postSelector->with(['author' => function($q) use($search) {
$q->where('username', 'LIKE', '%'. $search . '%');
}]);
break;
}
$posts = $postSelector->get();

Is there a way for Eloquent whereHas to only get() the matching results?

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();
}

Resources