1

I have this code in controller, so I need to paginate and sort by using distance, I dont know how to do this, Im new to laravel , thanks in advance

$stores = [];
foreach (session('storeinfo') as $storeInfo) {
$store = Storeinfo::find($storeInfo['id']);
if ($store) {
    $store->distance = $storeInfo['distance'];
    $stores[] = $store;

 $stores = collect([]);

 if (!Collection::hasMacro('paginate')) {
Collection::macro('paginate', function ($perPage = 25, $page = null, $options = []) {
    $options['path'] = $options['path'] ?? request()->path();
    $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
    return new LengthAwarePaginator(
        $this->forPage($page, $perPage)->values(),
        $this->count(),
        $perPage,
        $page,
        $options
    );
    });   
   }
  }
 }

return view('stores.archive',compact('stores'));

Im placing id into session using this:

 $allstores= Storeinfo::all();
foreach ($allstores as $allstore) {
Session::push('storeinfo', [
'id' => $allstore->id,
'distance' => $miles
]);  

}}

where $mile comes from calculation of distance enter code here

2
  • Model::find(... is typically used for finding a single item(row) in a table. Pagination doesn't apply to a single item. Can you provide more context to your problem? How are you placing storeinfo items into session? Is $storeInfo['id'] a foreign key? I'm assuming you have a Store to StoreInfo model relationship, if so, the code in these models will be useful here. Commented Jul 30, 2019 at 18:02
  • updated my question Commented Jul 30, 2019 at 18:06

1 Answer 1

3

First, I would create a collection instance of your $stores array:

$stores = collect([]);

I prefer using the push() api of the collection to add items:

$stores->push($store);

Second, the collection instance doesn't provide a native way to paginate so you need to add a macro:

use Illuminate\Support\Collection;
use Illuminate\Pagination\Paginator; 
use Illuminate\Pagination\LengthAwarePaginator;

...

if (!Collection::hasMacro('paginate')) {
    Collection::macro('paginate', function ($perPage = 25, $page = null, $options = []) {
        $options['path'] = $options['path'] ?? request()->path();
        $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
        return new LengthAwarePaginator(
            $this->forPage($page, $perPage)->values(),
            $this->count(),
            $perPage,
            $page,
            $options
        );
    });
}

I personally added the above macro in AppServiceProvider so that I can use it anywhere in my project. This should be located in the app/Providers directory.

To paginate you simply need to call the paginate() macro you just created:

$stores->paginate(15);

If you wish to set the current page or path, you may do so:

$stores->paginate(15, 1, ['path' => 'your/custom/path']);

To sort, all you need to do is used the desired sortBy method to achieve your results.

Per the docs, sortBy takes a string:

$sorted = $collection->sortBy('price');

Or a callback:

$sorted = $collection->sortBy(function ($product, $key) {
    return count($product['colors']);
});

The method, sortByDesc() works the same way as sortBy().

Sign up to request clarification or add additional context in comments.

16 Comments

Class 'App\Http\Controllers\Collection' not found
add a use statement to the top of your controller: use Illuminate\Support\Collection. If you use the helper you shouldn't need this.
are you getting into your conditional: if ($store) {?
You are now reassigning $stores. This is why it is empty. You only need to do $stores = collect([]); once. Where you had it originally before your foreach.
its working fine now im working to show the number of pages down the blade
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.