I'm using Laravel 5.6 -- Jquery Ajax
Here's the point
I'm having a search input placed in my navbar there's an eventlistener('keyup') on it.
Everytime keyup is fired, an AJAX GET request is send to
url : '{{action('PostController#searchAdmin')}}'
From web.php : Route::get('/search/admin', 'PostController#searchAdmin');
I made the return of that action a partial with data
return view('back.partials.searchResult', ['posts' => $posts, 'trashed' => $trashed]);
And I replace the content of the main tag with that partial
Everything is working properly except when the result count is greater than 10 (the breakpoint of pagination).
Pagination control links are all pointing to "search/admin?page=x" and when I click on it, this error is showing
Undefined variable: posts
I used $posts->links() to show the controls
I found a solution so I post it
In web.php
Route::get('/search', function(Request $request) {
$search = $request->search;
$trashed = Post::trash()->count();
$posts = Post::notTrash()
->where('title', 'like', '%' . $search . "%")
->orWhere('post_type' , 'like', '%' . $search . '%')
->paginate(10);
$posts->withPath('?search=' . $search);
return view('back.partials.searchResult', ['posts' => $posts, 'trashed' => $trashed, 'search' => $search]);
});
This code was for test purpose and will be soon exported in a new controller called SearchController
In my PostController
public function index(Request $request)
{
// GET parameters
$paginate = $request->input('paginate') ?? 10;
$search = $request->input('search') ?? null;
if($search !== null) {
$posts = $this->checkCategories($paginate, $search);
} else {
$posts = Post::notTrash()->orderBy('id', 'ASC')->paginate($paginate);
}
$trashed = Post::trash()->count();
$posts->withPath('?search=' . $search);
return view('back.index', ['posts' => $posts, 'trashed' => $trashed, 'search' => $search]);
}
Working with
private function checkCategories($paginate, $search)
{
$categories = Category::all();
foreach ($categories as $category) {
if(strpos(strtolower($category->name), $search) === false) {
// #TODO: Change for stripos
$posts = Post::notTrash()
->where('title', 'like', '%' . $search . '%')
->orWhere('post_type', 'like', '%' . $search . '%')
->paginate($paginate);
} else {
return Category::find($category->id)->posts()->paginate($paginate);
}
}
return $posts;
}
The index method now accept Request to handle get parameters when they are some.
In my views
#if($search !== null)
{{ $posts->appends($search)->links() }}
#else
{{ $posts->links() }}
#endif
Now replace
{{ $posts->links() }}
The solution was $var->**withPath()** and handling GET parameters
Related
I installed "Knp Paginator" and everything works fine but if i try to do a search in the search bar (this search bar does not depend on Knp Paginator) i have this error :
"Knp\Bundle\PaginatorBundle\Twig\Extension\PaginationExtension::render(): Argument #2 ($pagination) must be of type Knp\Bundle\PaginatorBundle\Pagination\SlidingPaginationInterface, array given, called in... /var/cache/dev/twig/36/36da62d992e743004744882a10f47b6d89340c107d735e823c151b7c459ca09f.php on line 214"
=>see image.
If i disable Knp Paginator, the search bar work again.
Thank you for your help.
this is my queryBuilder of search bar (ItemRepository):
public function findBySearch($search)
{
return $this->createQueryBuilder('a')
->andWhere('a.city LIKE :val')
->setParameter('val', '%' . $search . '%')
->orWhere('a.title LIKE :title')
->setParameter('title', '%' . $search . '%')
->orWhere('a.city LIKE :city')
->setParameter('city', '%' . $search . '%')
->orWhere('a.zipCode LIKE :zip')
->setParameter('zip', '%' . $search . '%')
->orWhere('a.hiddenDetail LIKE :hiddenDetail')
->setParameter('hiddenDetail', '%' . $search . '%')
->getQuery()
->getResult();
}
Controller (searchBar) :
/**
*#Route("/searchItem", name="searchItem")
*
*/
public function searchItem(Request $request, ItemRepository $itemRepository)
{
$search = $request->request->get('search');
$items = $itemRepository->findBySearch($search);
return $this->render('home/listItem.html.twig', [
'items' => $items
]);
}
Controller (Knp Paginator) :
public function listItem(ItemRepository $repository, PaginatorInterface $paginator, Request $request): Response
{
$data = $repository->findAll();
// PAGINANTION KNP/PAGINATOR
$items = $paginator->paginate(
$data,
$request->query->getInt('page', 1),
8
);
return $this->render('home/listItem.html.twig', [
'items' => $items,
]);
}
KNP is receiving an array from your findAll() function. You need to write a custom repo function to return the query builder itself, and KNP will complete the query for you with any extra necessities.
see https://symfonycasts.com/screencast/symfony4-doctrine-relations/pagination
It was fruitful in my endeavors.
Edit: Also, I would take another look at your andWhere()'s. You can set one parameter for all of them at once, and just reuse the search term, if that would work for your situation.
public function findBySearch($search)
{
return $this->createQueryBuilder('a')
->andWhere('
a.city LIKE :val
OR a.title LIKE :val
OR a.city LIKE :val
OR a.zipCode LIKE :val
OR a.hiddenDetail LIKE :val')
->setParameter('val', '%'.$search.'%')
->getQuery()
->getResult();
// if you want to use the paginator, leave these last two
// lines off. Return just the qb.
}
While making a request to my Laravel database something goes wrong. I'm trying to get different recipes on user input but Postman is returning 'No recipes found'.
My Laravel controller code:
public function search(Request $request) {
$fields = $request->validate([
'search' => 'required|string'
]);
// return response($request);
$recipes = Recipe::where('title', 'LIKE', '%'.$request.'%')->get();
if (count($recipes) > 0 ) {
return response($recipes);
} else {
return response('No recipes found');
}
}
if I return the response it returns "search": "maken" with the request http://127.0.0.1:8000/api/search?search=maken.
When I however hardcode the where clause to $recipes = Recipe::where('title', 'LIKE', 'maken')->get(); it returns some recipes and the search function works. Now I'm not sure whether the error is in my Postman request or in my search function in Laravel. Any help would be greatly appreciated!
You have to use $request->INPUT_NAME or $request->input('name') to get the value, so your code should be:
$recipes = Recipe::where('title', 'LIKE', '%'.$request->search.'%')->get();
Try this way
$recipes = Recipe::where('title', 'like', '%' . request('search') . '%')->get();
if ($recipes->count() > 0 ) {
return response($recipes);
} else {
return response('No recipes found');
}
i am trying to redirect using a function in my main controller with both variables and a message.
The message code is fine and is usually displayed by ->with('abo', 'messagetext').
The Problem is that not both types are redirected, only the variables (without the message) :(
The goal is to redirect the following variables: suchString, userId, suche
public function subscribe(Request $request)
{
$suchString = $request->input('suchString');
$userId = $request->input('userId');
Subscribe::create([
'abo_string' => $suchString,
'userid' => $userId
]);
$suche = Document::where( 'title', 'LIKE', '%' . $suchString . '%' )
->orWhere( 'category', 'LIKE', '%' . $suchString . '%' )
->orWhere( 'description', 'LIKE', '%' . $suchString . '%' )
->get();
$users = User::all();
return view('pages.search')->with('abo', 'messagetext');
}
You should try the compact() method to redirect your variable.
session()->flash( 'abo', 'Your message' );
return view('pages.search', compact('suchString', 'userId', 'suche' ));
You are returning a view() not a redirect()
And you can also chain with() as much as you like.
return redirect()->route('pages.search')
->with('abo', 'messagetext')
->with('suche', $suche)
->with('userId', $userId)
->with('suchString', $suchString);
Is likely what you want.
These will all be in the session on your next page view.
Im trying to figure out why my query is ignoring everything except the title and the description. The search button leading to the controller, is for filtering different type of ads , by category, by region, by price.
For example if now i search for existing ad and its found by title / keyword -> will always show, even if i choose a different region / category/ price range
Im trying to use something that will save me a lot of if statements to check if they exist in the request. Maybe other option si to use https://github.com/mohammad-fouladgar/eloquent-builder to build my query
public function index(Request $request)
{
$keyword = $request['keyword'];
$category_id = $request['category_id'];
$type_id = $request['type_id'];
$region_id = $request['region_id'];
$min_price = $request['min_price'];
$max_price = $request['max_price'];
$result = Ad::when($keyword, function ($q) use ($keyword) {
return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
})
->when($category_id, function ($q) use ($category_id) {
return $q->where('category_id', $category_id);
})
->when($region_id, function ($q) use ($region_id) {
return $q->where('region_id', '=', $region_id);
})
->when($type_id, function ($q) use ($type_id) {
return $q->where('adtype_id', '=', $type_id);
})
->when($min_price, function ($q) use ($min_price) {
return $q->where('price', '>=', $min_price);
})
->when($max_price, function ($q) use ($max_price) {
return $q->where('price', '<=', $max_price);
})
->paginate(8);
My get param url looks like that:
search?keyword=&category_id=0®ion_id=0&type_id=0&min_price=&max_price=
The produced query in mysql when i search for existing ad by its name and i look for a different category is:
select * from `ads` where `title` like '%test test%' or `description` like '%test test%' and `category_id` = '2' limit 8 offset 0
The ad is found, but the actual category is 1, not 2, same for all others optimal parameters.
You can edit your query to look for specific relations, using whereHas. This method will allow you to add customized constraints to a relationship constraint, such as checking the content of a comment.And to check max/min price, use where method. So, you can use it like this:
$result = Ad::when($keyword, function ($q) use ($keyword) {
return $q->where('title', 'like', '%' . $keyword . '%')->orWhere('description', 'like', '%' . $keyword . '%');
})
->whereHas('category_relation_name', function ($q) use ($category_id) {
return $q->where('category_id', $category_id);
})
->whereHas('region_relation_name', function ($q) use ($region_id) {
return $q->where('region_id', $region_id);
})
->whereHas('type_relation_name', function ($q) use ($type_id) {
return $q->where('adtype_id', $type_id);
})
->where('price', '>=', $min_price);
->where('price', '<=', $max_price);
->paginate(8);
I am trying to run a query through a relationship path. In human readable format:
Get collection of orders where $order->orderItem->product->sku is LIKE 'red-jumper';
I can create this manually using a whereHas query as follows:
$query->whereHas('orderItems', function($query) use($request){
$query->whereHas('product', function ($query) use($request){
$query->where('sku', 'LIKE', '%' . $request->search . '%');
});
});
However, if I want this to be dynamic and do not know the amount of levels in the relationships, how can I do this?
I would be looking for something lik:
$paths = [
0 => 'orderItems'
1 => 'product,
2 => 'sku'
];
$query->whereHas($paths[0], function($query) use($request, $paths){
$query->whereHas($paths[1], function ($query) use($request, $paths){
$query->whereHas($paths[2], function ($query) use($request, $paths) {
$query->whereHas($paths[3], function ($query) use ($request, $paths) {
$query->where('sku', 'LIKE', '%' . $request->search . '%');
});
});
});
});
Maybe there is a better way to do this all together?
There is a slightly better way in my opinion. You can use dot (.) notation for relationships and collections to turn your $path array into what you want. First we reduce the $path to a dotted relationship and separate the attribute you want to filter by later
$path = ['orderItems', 'product', 'sku']
$param = array_pop($path)
// $path = ['orderItems', 'product']
// $param = 'sku'
$dotPath = collect($path)->reduce(function ($c, $i) {
return $c . $i . '.';
});
// $dotPath = 'orderItems.product.'
$dotPath = substr($dotPath, 0, -1)
// $dotPath = 'orderItems.product'
And then we check with whereHas
$query->whereHas($dotPath, function ($query) use ($request, $param){
$query->where($param, 'LIKE', '%' . $request->search . '%');
})->get();