leknoppix's avatar

Paging url rewrite

Hello everyone

I would like to modify the pagination urls of my website by replacing the urls of this type tags/toto?page=2 to tags/toto/2

I am currently working on modifying a RouteServiceProvider with this code:

$urlwithoutparams = request()->path();
                 redirect($urlwithoutparams.'/'.request()->input('page'), 301)->send();
                 exit();

Finally, for the pagination, I call, in my action, a line that I created:

<?php
$posts = Post::published()->orderBy('publish_date', 'desc')
             ->with('image', 'city')
             ->PaginateUri(10, $page);
.....

I get an array through the stroke, an array with a paginate entry and a paginationLinks entry.

Below is my PaginateTrait:

<?php

namespace App\Traits;

use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Pagination\Paginator;

PaginateTrait
{

     /**
      * Clean Scope Paginate Uri
      *
      * @return array<string,mixed>
      */
     public static function scopePaginateUri(Builder $query, int $items, ?int $page): array
     {
         $action = app('request')->route()->getActionName();
         $parameters = app('request')->route()->parameters();
         if (isset($parameters['sort']) && !is_numeric($parameters['sort'])) {
             $parameters['page'] = '##';
             $current_url = action(str_replace('App\Http\Controllers\', '', $action), $parameters);
         } elseif (isset($parameters['sort']) && is_numeric($parameters['sort'])) {
             $current_url = action(str_replace('App\Http\Controllers\', '', $action), $parameters);
             $current_url = str_replace((string) $parameters['sort'], '##', $current_url);
         } elseif (isset($parameters['slug'])) {
             $parameters['page'] = '##';
             $current_url = action(str_replace('App\Http\Controllers\', '', $action), $parameters);
         } else {
             $current_url = action(str_replace('App\Http\Controllers\', '', $action), $parameters);
             $current_url = $current_url . '/##';
         }
         Paginator::currentPageResolver(function () use ($page) {
             return $page;
         });
         $paginate = $query->paginate($items);
         $last_page = $paginate->toArray();
         $last_page = $last_page['last_page'];
         if ($page > $last_page) {
             $url = str_replace('/##', '', $current_url);
             header('Location: '. $url, true, 301);
         }
         $links = preg_replace('@href="(.*/?page=(\d+))"@U', 'href="' . str_replace('##', '', str_replace('//# #', '/', $current_url)) . '"', $paginate->links('pagination.default')->toHtml());
         return [
             'paginate' => $paginate,
             'paginationLinks' => $links,
         ];
     }
}

The problem is that when I access the value of $posts (in my example), I get the following errors when I try to access the element returned by the Trait:

Cannot access offset 'paginationLinks' on Illuminate\Database\Eloquent\Builder<App\Models\Post>.
Cannot access offset 'paginate' on Illuminate\Database\Eloquent\Builder<App\Models\Post>.

The problem that I detect, after research and analysis is at the level, I think of my trait. Indeed, the paginate() function does not exist in the Builder ($query). On the other hand, even if I understand the error, I do not see how to solve my concern. If any of you could help me or at least direct me, I would appreciate it. Thank you to all of you. If you have any questions, please don't hesitate to tell me.

Have a good evening.

0 likes
2 replies
jlrdw's avatar
jlrdw
Best Answer
Level 75

Check Github, there is an existing package that does this. However to make things stay easy, I suggest just leaving the pagination a regular query string.

Please or to participate in this conversation.