Paginate search result laravel - laravel-4

After some help in a previous post Laravel - Search Facility on site using Eloquent I now need to some help on paginating the result using the built in laravel pagination class.
public function search() //no parameter now
{
$q = Input::get('term');
if($q && $q != ''){
$searchTerms = explode(' ', $q);
$query = DB::table('wc_program'); // it's DB::table(), not DB::tables
if(!empty($searchTerms)){
foreach($searchTerms as $term) {
$query->where('JobRef', 'LIKE', '%'. $term .'%');
}
}
$results = $query->get();
dd($results); // for debugging purpose. Use a View here
}
}

Simply change get to paginate and provide number of items per page.
$results = $query->paginate(10);

Related

Removing existing Where clauses

I want to remove where clauses in some conditions:
$q = Thread::with('comments')->take(10);
if(strlen($input) < 4){
$result = $q->where('title', '~', "^$input$")->get();
if($result->isNotEmpty()){
return $result;
}
// if was empty:
}
// How to clean the where clause from the above here? because it affect the query below:
$result = $q->where('title', 'like', "%$input%")->get();
The problem is the first where clause affects the second one if the data was empty, How can i remove existing where clauses when needed ? also the newQuery() is not working in my case.
Note that i'm using two seperate statement in postgres ~ and 'like'
Something like reorder() for where clauses
Yes there is a way to do it
$q = Thread::with('comments')->take(10);
if(strlen($input) < 4){
$result = $q->where('title', '~', "^$input$")->get();
if($result->isNotEmpty()){
return $results;
}
}
// getQuery() is a query builder method that contains all the groupings, selects, orders, wheres, joins etc for the query that you are accessing or trying to build.
$q->getQuery()->wheres= [];
$result = $q->where('title', 'like', "%$input%")->get();
Use Conditional Clauses
$threads = Thread::with('comments')->when(strlen($input) < 4, function ($query) use ($input) {
return $query->where('title', '~', "^$input$");
}, function ($query) use ($input) {
return $query->where('title', 'like', "%$input%");
})->take(10)->get();
https://laravel.com/docs/8.x/queries#conditional-clauses
If you want to give it a second change I would write that logic like this. Comments are loaded only if they are needed.
if (strlen($input) < 4) {
$threads = Thread::where('title', '~', "^$input$")->take(10)->get();
if ($threads->isNotEmpty()) {
return $threads->load('comments');
}
}
return Thread::with('comments')->where('title', 'like', "%$input%")->take(10)->get();
if you cloning before add where
it works the same as deleting where
...
if(strlen($input) < 4){
$result = (clone $q)->where('title', '~', "^$input$")->get();
if($result->isNotEmpty()){
return $results;
}
}
$result = $q->where('title', 'like', "%$input%")->get();
...

Laravel filter of multiple variables from multiple models

Goodmorning
I'm trying to make a filter with multiple variables for example I want to filter my products on category (for example 'fruit') and then I want to filter on tag (for example 'sale') so as a result I get all my fruits that are on sale. I managed to write seperate filters in laravel for both category and tag, but if I leave them both active in my productsController they go against eachother. I think I have to write one function with if/else-statement but I don't know where to start. Can somebody help me with this please?
These are my functions in my productsController:
public function productsPerTag($id){
$tags = Tag::all();
$products = Product::with(['category','tag','photo'])->where(['tag_id','category_id'] ,'=', $id)->get();
return view('admin.products.index',compact('products','tags'));
}
public function productsPerCategory($id){
$categories = Category::all(); //om het speciefieke id op te vangen heb ik alle categories nodig
$products = Product::with(['category','tag','photo'])->where('category_id', '=', $id)->get();
return view('admin.products.index',compact('products','categories'));
}
These are my routes in web.php. I guess this will also have to change:
Route::get('admin/products/tag/{id}','AdminProductsController#productsPerTag')->name('admin.productsPerTag');
Route::get('admin/products/category/{id}','AdminProductsController#productsPerCategory')->name('admin.productsPerCategory');
For filter both
change your URL like
Route::get('admin/products/tag/{tag_id?}/{category_id?}','AdminProductsController#productsPerTag')->name('admin.productsPerTag');
Make your function into the controller like
public function productsPerTag($tagId = null, $categoryId = null){
$tags = Tag::all();
$categories = Category::all();
$query = Product::with(['category','tag','photo']);
if ($tagId) {
$query->where(['tag_id'] ,'=', $tagId);
}
if ($tagId) {
$query->where(['category_id'] ,'=', $categoryId);
}
$products = $query->get();
return view('admin.products.index',compact('products','tags', 'categories'));
}
You are trying to filter in your query but you pass only 1 parameter to your controller, which is not working.
1) You need to add your filters as query params in the URL, so your url will look like:
admin/products/tag/1?category_id=2
Query parameters are NOT to be put in the web.php. You use them like above when you use the URL and are optional.
2) Change your controller to accept filters:
public function productsPerTag(Request $request)
{
$categoryId = $request->input('category_id', '');
$tags = Tag::all();
$products = Product::with(['category', 'tag', 'photo'])
->where('tag_id', '=', $request->route()->parameter('id'))
->when((! empty($categoryId)), function (Builder $q) use ($categoryId) {
return $q->where('category_id', '=', $categoryId);
})
->get();
return view('admin.products.index', compact('products', 'tags'));
}
Keep in mind that while {id} is a $request->route()->parameter('id')
the query parameters are handled as $request->input('category_id') to retrieve them in controller.
Hope It will give you all you expected outcome if any modification needed let me know:
public function productList($tag_id = null , $category_id = null){
$tags = Tag::all();
$categories = Category::all();
if($tag_id && $category_id) {
$products = Product::with(['category','tag','photo'])
->where('tag_id' , $tag_id)
->where('category_id' , $category_id)
->get();
} elseif($tag_id && !$category_id) {
$products = Product::with(['category','tag','photo'])
->where('tag_id' , $tag_id)
->get();
} elseif($category_id && !$tag_id) {
$products = Product::with(['category','tag','photo'])
->where('category_id' , $category_id)
->get();
} elseif(!$category_id && !$tag_id) {
$products = Product::with(['category','tag','photo'])
->get();
}
return view('admin.products.index',compact(['products','tags','products']));
}
Route:
Route::get('admin/products/tag/{tag_id?}/{category_id?}','AdminProductsController#productsPerTag')->name('admin.productsPerTag');

Laravel combine query with if statement

Im working on product filtering using AJAX. Is there any possible way to produce same output as picture shown below using query builder?
I have tried union but it’s not working.
I hope this example gives idea , Try this one
use multiple if statement and get data into DB using joins .
function datatables($request) {
$data = $this->leftJoin('blog_category', 'blog_category.blog_category_uuid', '=', 'blog_detail.blog_category_uuid')
->where('blog_detail.blog_detail_is_deleted', 'NO');
if ($request->search['value'] != null && $request->search['value'] != '') {
$keyword = $request->search['value'];
$data = $data->where(function($query) use ($keyword) {
// $query->orWhere('activity_type.activity_type_name', 'LIKE', '%' . $keyword . '%');
$query->orWhere('blog_detail.blog_detail_title', 'LIKE', '%' . $keyword . '%');
});
}
if (isset($request->order[0]['dir'])) {
$data = $data->orderBy('blog_detail.blog_detail_id', $request->order[0]['dir']);
} else {
$data = $data->orderBy('blog_detail.blog_detail_created_date');
}
$datacount = $data->count();
$dataArray = $data->select('blog_detail.*', 'blog_category.blog_category_name' , DB::raw('DATE_FORMAT(blog_detail.blog_detail_created_date,"%Y-%m-%d") as blog_detail_date'));
if ($request->length == -1) {
$dataArray = $dataArray->get();
} else {
$dataArray = $dataArray->skip($request->start)->take($request->length)->get();
}
return [$datacount, $dataArray];
}
In laravel you can create a model for product say Product. Then the query will be like
$products = Product::where('product_status', '1');
if ($request->input('minimum_price') && $request->input('maximum_prize')) {
$products = $products->whereBetween('product_prize', array($request->input('minimum_price'), $request->input('maximum_prize')));
}
if ($request->input('brand')){
$brand_filter = implode("','", $request->input('brand'));
$products = $products->whereIn('product_brand', $brand_filter);
}
$products = $products->get();
after the execution $products contains the products after query.

Laravel pagination with problems

i have a simple question as i do not know which line i should add into to get laravel pagination. (->paginate(5).
public function index(Request $request)
{
$codeSearch = $request->get('code');
$descriptionSearch = $request->get('description');
//$tmp = Category::all()->toArray();
$tmp = Category::where('code','like','%' .$codeSearch. '%')->where('description','like','%' .$codeSearch. '%')->get()->toArray();
$category = array();
foreach ($tmp as $key => $row) {
$policy = Category::find($row['parent_id']);
$tmpResult = new Category();
$tmpResult->id = $row['id'];
$tmpResult->code = $row['code'];
$tmpResult->description = $row['description'];
$tmpResult->parent_id = $policy['description'];
$tmpResult->status = $row['status'];
array_push($category, $tmpResult);
}
return view('category.index', compact('category'));
}
Paginate can't be called on the collection, so you have to run it on the query, by simply replace ->get() with ->paginate(5) like this
$tmp = Category::where('code','like','%' .$codeSearch. '%')
->where('description','like','%' .$codeSearch. '%')
->paginate(5)
->toArray();
Try
$tmp = Category::where('code','like','%' .$codeSearch. '%')->where('description','like','%' .$codeSearch. '%')->paginate(5);
In view
#foreach($tmp as $tm)
//whatever operation you like to do
#endforeach
{{$tmp->links()}}
The following ->get(), ->first(), all() get the results from the database and so does ->paginate(5), so I would suggest that you replace ->get() with paginate(5) an you can get rid of toArray() because the result will be a collection with which you can use foreach() or get a value by index.
As you need an array in your condition, then you can simply convert the final array into a collection object and use the pagination concept.
$items = [
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item10'
];
// Get current page form url e.x. &page=1
$currentPage = LengthAwarePaginator::resolveCurrentPage();
// Create a new Laravel collection from the array data
$itemCollection = collect($items);
// Define how many items we want to be visible in each page
$perPage = 1;
// Slice the collection to get the items to display in current page
$currentPageItems = $itemCollection->slice(($currentPage * $perPage) - $perPage, $perPage)->all();
// Create our paginator and pass it to the view
$paginatedItems= new LengthAwarePaginator($currentPageItems , count($itemCollection), $perPage);
// set url path for generted links
$paginatedItems->setPath($request->url());
return view('items_view', ['items' => $paginatedItems]);
It would probably be easier to have a relationship setup for a Category's parent. Then you can load the parent when you retrieve the categories.
class Category extends Model
{
...
public function parent()
{
return $this->belongsTo(self::class);
}
}
I feel like your search is probably trying to do an OR WHERE, search the code field for this value or the description:
$categories = Category::with('parent')
->where('code', 'like', '%' .$codeSearch. '%')
->orWhere('description', 'like', '%' .$codeSearch. '%')
->paginate(5);
Then in your view if you want the parent category's description you can get it through the relationship:
#foreach ($categories as $category)
parent description: {{ $category->parent->description }}
#endforeach

Paginate / Search Laravel issue

After a couple of conversations on here i'm finally getting somewhere but after the pagintion now works when i got to search?page=2 i get a json array of the logged in user and not page 2 of the results.
Here's my controller:
public function search()
{
$q = Input::get('term');
if($q && $q != ''){
$searchTerms = explode(' ', $q);
$query = DB::table('wc_program');
if(!empty($searchTerms)){
foreach($searchTerms as $term) {
$query->where('JobRef', 'LIKE', '%'. $term .'%');
$query->orwhere('Road', 'LIKE', '%'. $term .'%');
}
}
$results = $query->paginate(10);
return View::make('layouts.results', compact('results'));
}
}
Route:
Route::get('/search', 'HomeController#search');
So how can i work around this?
You need to append query string to the pagination.
in your controller, pass the query string to the view.
return View::make('layouts.results', compact('results', 'q'));
In your view (results.blade.php):
append the query string to the pagination otherwise in page 2 you will not get any result.
<?php echo $results->appends(array('term' => $q))->links(); ?>

Resources