phplaravelpaginationoctobercms

Custom pagination in OctoberCMS


I have a code to do query from form:

Painting::where('type',input("type"))->where('material',input("material"))->whereHas('artist', function($q)
{
     $q->where('artist_slug', '=', $this->param('slug'));
})->paginate(15);

How can I do custom pagination with page numbers list? Or maybe dinamicaly loading


Solution

  • Check out the RainLab Blog Plugin it has a good example, also see here .

    But here is a more complete example if you want to add URL friendly paginations paintings/2 where 2 is the page number and/or handle URL parameters paintings/2?type=something&material=something

    In your Painting Model add a scope for listing paintings on the front-end :

    public function scopeListPaintings($query, $options)
        {
            extract(array_merge([
                'page'               =>  1,
                'perPage'            =>  30,
                'material'           =>  null,
                'type'               =>  null,
                'artistSlug'         =>  null,
            ], $options));
    
    
            if( !empty($artistSlug) ){
                $query->whereHas('artist', function($q)
                {
                    $q->where('artist_slug', $artistSlug );
                });
            }
    
            if( !empty($material) ){
                $query->where( 'material' , $material)
            }
    
            if( !empty($type) ){
                $query->where( 'type' , $type)
            }
    
    
            return $query->paginate( $perPage, $page );
    
        }
    

    Then in your Painting Component Define the properties and call the previous scope ;

        public $paintings ;
    
        public $pageNumber;
    
        public $perPage; 
    
        public $urlParams;
    
        public function defineProperties()
        {
            return [
                'pageNumber' => [
                    'title'       => 'Page #',
                    'description' => 'Paintings Page #',
                    'type'        => 'string',
                    'default'     => '{{ :page }}',
                ],
                'perPage' => [
                    'title'       => 'Paintings per page',
                    'type'        => 'string',
                    'default'     => '30',
                ]
    
                .. ect make sure to add it to your page markup
            ];
    
        }
    
        private function propertyOrParam($name, $default = null)
        {
            $value = $this->property($name, $default);
            if (substr($value, 0, 1) == ':')
                return $this->param($value, $default);
    
            return $value;
        }
    
        public function getPaintings()
        {
            /** Pagination */
            $this->pageNumber    = $this->propertyOrParam('pageNumber') ;
            $this->perPage       = $this->propertyOrParam('perPage'); 
    
            /** Url Params if exist */ 
            $params = Request::query()
            $this->page['urlParams']   =  $this->urlParams  =  !empty( $params ) ? http_build_query( $params ) : null ;
    
            return (new Painting)->ListPaintings([
                    'page'          => $this->pageNumber, 
                    'perPage'       => $this->perPage,
                    'type'          => input('type'),
                    'material'      => input('material'),
                    'artistSlug'    => $this->propertyOrParam('slug')
                ]);
        }
    
        public function onRun()
        {
    
            $this->page['paintings'] = $this->paintings   = $this->getPaintings() ;
    
            // Redirect to Last page if page # not found in request
            if ($this->pageNumber >  $this->paintings->lastPage() && $this->pageNumber > 1){
                return Redirect::to($this->currentPageUrl([ $this->paramName('pageNumber') =>  $this->paintings->lastPage().$this->urlParams ]));
            }
    
        }
    

    Then your can create a global partial in your theme to handle paginations - You can reuse it all over your site - add the following snippet ( Borrowed from the Forum Plugin ) ;

    Pagination.htm

        {% set paginationEnabled =
        records.currentPage > 1 or
        records.lastPage > 1 or
        records.lastPage > records.currentPage
        %}
    
        {% if paginationEnabled %}
        {# How many pages to display around the current page #}
        {% set n = 2 %}
    
        {% set currentPageZeroBased = records.currentPage-1 %}
    
        {% set pageLinks = [] %}
        {% set pageSet = [] %}
    
        {% set startOffset = max(currentPageZeroBased - n, 0) %}
        {% if (startOffset + 2*n+1) > (records.lastPage-1) %}
        {% set startOffset = max(records.lastPage - 2*n - 1, 0) %}
        {% endif %}
    
        {% for page in 1..records.lastPage %}
        {% set pageLinks = pageLinks|merge([page]) %}
        {% endfor %}
    
        {% set activeBlock = pageLinks|slice(startOffset, 2*n + 1) %}
    
        {% if startOffset > 0 %}
        {% set pageSet = pageSet|merge([1]) %}
    
        {% if startOffset > 1 %}
        {% set pageSet = pageSet|merge(['...']) %}
        {% endif %}
        {% endif %}
    
        {% set pageSet = pageSet|merge(activeBlock) %}
    
        {% set diffToEnd = (records.lastPage-1) - (startOffset + 2*n+1) + 1 %}
    
        {% if diffToEnd > 0 %}
        {% if diffToEnd > 1 %}
        {% set pageSet = pageSet|merge(['...']) %}
        {% endif %}
    
        {% set pageSet = pageSet|merge([records.lastPage]) %}
        {% endif %}
    
    
        <div>
            <div>
               <div>
    
                   <div>
                       <span>Records&nbsp;&nbsp;<b>{{records.firstItem|trim}}&nbsp;-&nbsp;{{records.lastItem|trim}}</b>&nbsp;Of&nbsp;{{ records.total|number_format(0, '.', ',')}}</span>
                       <span>Page {{ records.currentPage }} of {{ records.lastPage }}</span>
                   </div>
    
               </div>
            </div>
            <div>
                <ul>
    
                    {% if records.currentPage > 1 %}
                    <li>
                        <a href="{{ this.page.baseFileName|page( { page : (records.currentPage-1) ~ urlParams }) }}" title="Previous"><i class="fa fa-angle-left"></i></a>
                    </li>
                    {% endif %}
    
                    {% for page in pageSet %}
                    {% if page == '...' %}
                    <li>
                        <a href="javascript:void(0)" type="button" class="disabled">{{ page }}</a>
                    </li>
                    {% else %}
                    <li class="{{ page == records.currentPage ? 'active' }}">
                        <a href="{{ this.page.baseFileName|page({ page : page ~ urlParams })  }}">{{ page }}</a>
                    </li>
                    {% endif %}
                    {% endfor %}
    
                    {% if records.lastPage > records.currentPage %}
                    <li>
                        <a href="{{ this.page.baseFileName|page({ page : (records.currentPage+1) ~ urlParams }) }}" title="Next"><i class="fa fa-angle-right"></i></a>
                    </li>
                    {% endif %}
                </ul>
            </div>
        </div>
    
    
        {% endif %}
    

    Then in your page or component ;

    {% for painting in paintings %}
     ....
    {% endfor %}
    
    // Add the pagination
    
    {% partial "pagination" records=paintings  %}