How to automatically append query string to laravel pagination links? - laravel-4

I am working on search filter on checkbox click, with Laravel and Ajax call. So I get results when I click on a checkbox. my query is as follows:
$editors = User::with(['editor.credentials','editor.specialties','editor.ratings']);
$temp=$editors->whereHas('editor', function($q) use ($a_data){
$q->whereHas('specialties',function($sq) use($a_data){
$sq->whereIn('specialty',$a_data);
});
})->paginate(2);
This gives me all the data I need. however how should I get the links for pagination?
$temp->setBaseUrl('editors');
$links = $temp->links()->render();
I am currently doing this and with $links which I am sending over as response to ajax call, I set the pagination with $links data. Now, I need to append the query to next page like page=2?query="something". I don't know how should I go about appending the remaining query result links to next page links. i.e. I don;t know what should come in the query="something" part. Can someone guide me. thanks

{{ $users->appends($_GET)->links() }}
It will append all query string parameters into pagination link

As of Laravel 7, you can call the withQueryString() method on your Paginator instance.
Quote from the documentation:
If you wish to append all current query string values to the pagination links you may use the withQueryString method:
{{ $users->withQueryString()->links() }}
See "Appending To Pagination Links": https://laravel.com/docs/7.x/pagination#displaying-pagination-results

Check the answer from #Arda, as it's global solution. Below you can find how to do it manually.
Use appends on Paginator:
$querystringArray = Input::only(['search','filter','order']); // sensible examples
// or:
$querystringArray = ['queryVar' => 'something', 'anotherVar' => 'something_else'];
$temp->appends($querystringArray);

Append all input except the actual page, form token and what you don't want to pass:
$paginatedCollection->appends($request->except(['page','_token']));

For the latest version of Laravel at the moment (5.2), you can just use the Request facade to retrieve the query string and pass that to your paginator's appends() method
$input = Request::input();
$myModelsPaginator = App\Models\MyModel::paginate();
$myModelsPaginator->appends($input);

Add this anywhere in your app (e.g routes.php, filters.php or anything that's autoloaded), no need to edit any pagination codes that is written already. This works flawlessly using view composers, and you don't need to know any query string parameters:
////////PAGINATION QUERY STRING APPEND
View::composer(Paginator::getViewName(), function($view) {
$queryString = array_except(Input::query(), Paginator::getPageName());
$view->paginator->appends($queryString);
});
//////////////////

Inspired from previous answers I ended up using the service container for both frontend + api support.
In your AppServiceProvider#boot() method:
$this->app->resolving(LengthAwarePaginator::class, function ($paginator) {
return $paginator->appends(array_except(Input::query(), $paginator->getPageName()));
});

you can used request helper in view as same
{{ $users->appends(request()->query())->links() }}

in your view where you display pagination...
{{ $results->appends(Request::except('page'))->links() }}
appends keeps the query string value except "page". not sure if it will work with POST request

{{ $users->appends(Request::only(['filter','search']))->links()}}

Updating #rasmus answer for Laravel 8.
In your AppServiceProvider boot method, add the following lines and your existing query string will be be used for all pagination links
$this->app->resolving(Paginator::class, function ($paginator) {
return $paginator->appends(Arr::except(Request::query(), $paginator->getPageName()));
});
$this->app->resolving(LengthAwarePaginator::class, function ($paginator) {
return $paginator->appends(Arr::except(Request::query(), $paginator->getPageName()));
});
And for completeness, use these classes:
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Request;

Related

Laravel Pagination on POST request

Im using Laravel v7 and i have a question about pagination.
So far im using 2 routes, 1rst to return a view with all rows from database, and 2nd receives an input and returns that view with the rows filtered by that input value.
But im using pagination, and on the 2nd route, when i try to go to 2nd page it gives me an error:
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The GET method is not supported for this route. Supported methods: POST.
I've tried to change my form method to GET but i need that the token doesn't appear on the page URL and beside that, when i go to 2nd page, it returns all the rows again.
Thats my code so far:
Routes:
Route::get('concessions', 'ConcessionController#index')->name('concessions.index');
Route::post('concessions/search', 'ConcessionController#search')->name('concessions.search');
Controller
class ConcessionController extends Controller
{
public function index()
{
$concessions = DB::table('concessions')->paginate(12);
return view('admin.concessions.index', compact('concessions'));
}
public function search(Request $request)
{
$name = $request->name;
$concessions = Concession::where('name', 'like', '%' . $name . '%')->paginate(12);
return view('admin.concessions.index', compact('concessions', 'name'));
}
}
Any way to do that?
Laravel pagination only works with get parameters.
You should use GET method for your search page. POST requests aren't meant for the purpose of displaying data. Why? There are many reasons, but to be short I will give you three examples :
1. When you access the first page, you get the data by GET request,
not POST request. So if you want to use POST request, you
need to access the page as POST request by sending data with
POST method.
2. With GET parameters, let's say you are on 5th page - you can
copy the link and paste it to friend and he will be able to view
the same content as you. With POST this is impossible.
3. You can not use back button with POST requests, if you manage to
get pagination to work.
POST requests are useful when you need to submit data to the server, in order to create new record, for example.
So I suggest you to change your route type to GET.
From my perspective, if you change your route code similar to below code, it will work properly with both methods of GET and POST.
Route::any('concessions/search', 'ConcessionController#search')->name('concessions.search');

API request with multiple body inputs

I am new to laravel this is how I make an API with one single body item
$shops_categories=ShopsCategories::all()->where('title',$request->title);
how to request more than an item in the body for example title , email , password ?
Eloquent allows you to chain as many where as required. So you are able to do
$shops_categories = ShopsCategories::where('title',$request->title)->where('email',$request->email)->where('password',$request->email)->get();
You can do it like so:
$cats = ShopsCategories::query()->where(['title' => $title, 'email'=>$email, 'name'=>$name]);
i guess you are performing query operation in controller itself which is not recommended,please create an instance for the model and make a function call to model and in the model you can return like
return $this::where('id','=',$id)->get()
and also please try to avoid using text/string in where condition instead use id's or unique values
You can also convert request to array using all()
//$request->all() is same as ['title'=> 'my title', ...]
$shops_categories=ShopsCategories::where($request->all())->get();

Get part of url from Laravel named route

Is there a possibility to get the part of url, that is defined in route?
For example with this route:
Route::get('/editor/{id}', 'EditorController#editor')->name('editorNew');
after using mentioned functionality, let's say route_link(); i would like to get:
$route_link = route_link('editorNew', array('id' => 1));
//$route_link containts "/editor/1"
I tried to use route(), but i got http://localhost/app/public/editor-new/1 instead of /editor-new/1 and that's not what i wanted.
For clarity need this functionality to generate links depending on machine, that the app is fired on (integration with Shopify).
You can use route method to get the relative path by passing false in the third parameter as:
route('editorNew', [1], false); // returns '/editor-new/1'
You could use the following:
$route_link = route('editorNew', [1]);
1 is the first value that will be on the route, at this moment {id}.
If you want to use the paramater (id) in your method, it will be the following:
public function editor($id) {
//your code
}
And in the view you could use:
Route::input('id');
Hope this works!

Get last part of current URL in Laravel 5 using Blade

How to get the last part of the current URL without the / sign, dynamically?
For example:
In www.news.com/foo/bar get bar.
In www.news.com/foo/bar/fun get fun.
Where to put the function or how to implement this in the current view?
Of course there is always the Laravel way:
request()->segment(count(request()->segments()))
You can use Laravel's helper function last. Like so:
last(request()->segments())
This is how I did it:
{{ collect(request()->segments())->last() }}
Use basename() along with Request::path().
basename(request()->path())
You should be able to call that from anywhere in your code since request() is a global helper function in Laravel and basename() is a standard PHP function which is also available globally.
The Route object is the source of the information you want. There are a few ways that you can get the information and most of them involve passing something to your view. I strongly suggest not doing the work within the blade as this is what controller actions are for.
Passing a value to the blade
The easiest way is to make the last part of the route a parameter and pass that value to the view.
// app/Http/routes.php
Route::get('/test/{uri_tail}', function ($uri_tail) {
return view('example')->with('uri_tail', $uri_tail);
});
// resources/views/example.blade.php
The last part of the route URI is <b>{{ $uri_tail }}</b>.
Avoiding route parameters requires a little more work.
// app/Http/routes.php
Route::get('/test/uri-tail', function (Illuminate\Http\Request $request) {
$route = $request->route();
$uri_path = $route->getPath();
$uri_parts = explode('/', $uri_path);
$uri_tail = end($uri_parts);
return view('example2')->with('uri_tail', $uri_tail);
});
// resources/views/example2.blade.php
The last part of the route URI is <b>{{ $uri_tail }}</b>.
Doing it all in the blade using the request helper.
// app/Http/routes.php
Route::get('/test/uri-tail', function () {
return view('example3');
});
// resources/views/example3.blade.php
The last part of the route URI is <b>{{ array_slice(explode('/', request()->route()->getPath()), -1, 1) }}</b>.
Try request()->segment($number) it should give you a segment of the URL.
In your example, it should probably be request()->segment(2) or request()->segment(3) based on the number of segments the URL has.
YourControllor:
use Illuminate\Support\Facades\URL;
file.blade.php:
echo basename(URL::current());
It was useful for me:
request()->path()
from www.test.site/news
get -> news
I just had the same question. In the meantime Laravel 8. I have summarised all the possibilities I know.
You can test it in your web route:
http(s)://127.0.0.1:8000/bar/foo || baz
http(s)://127.0.0.1:8000/bar/bar1/foo || baz
Route::get('/foo/{lastPart}', function(\Illuminate\Http\Request $request, $lastPart) {
dd(
[
'q' => request()->segment(count(request()->segments())),
'b' => collect(request()->segments())->last(),
'c' => basename(request()->path()),
'd' => substr( strrchr(request()->path(), '/'), 1),
'e' => $lastPart,
]
)->where('lastPart', 'foo,baz'); // the condition is only to limit
I prefer the variant e).
As #Qevo had already written in his answer. You simply make the last part part of the request. To narrow it down you can put the WHERE condition at the route.
Try with:
{{ array_pop(explode('/',$_SERVER['REQUEST_URI'])) }}
It should work well.

Lumen Blade result to array gives empty value

When I put the following code in my controller in Lumen it returns an empty value for the 'info' key, which should contain the Blade template:
$return = array();
$return['cities'] = $cities;
$return['info'] = view('popup/dialog')->with('result',$result);
return $return;
This returns the following
{"cities":["Den Helder"],"info":{}}
But when I only return the 'info' value, it will show the Blade template
return $return['info'];
I'm using this implementation in an websocket environment. I want to keep the websocket calls to a minimum. So it would be great to return the contents of the template, within the dataset.
Hope you can help.
Offtopic: I'm reading for a couple of years on this site, but this is my first post. If I'm doing something wrong, please tell me.
Thanks in advance!
You need to use the render() method to generate the HTML content of you view.
This should work:
$return['info'] = view('popup/dialog')->with('result',$result)->render();
http://laravel.com/api/5.0/Illuminate/View/View.html#method_render

Resources