페이지네이션

CodeIgniter는 테마 적용이 간단하고, 모델과 함께 동작하며, 단일 페이지에서 여러 페이지네이터를 지원할 수 있는 매우 간단하지만 유연한 페이지네이션 라이브러리를 제공합니다.

라이브러리 로드

CodeIgniter의 모든 서비스와 마찬가지로 Config\Services를 통해 로드할 수 있지만, 일반적으로 수동으로 로드할 필요는 없습니다:

<?php

$pager = service('pager');

모델과 함께 페이지네이션

대부분의 경우 데이터베이스에서 가져온 결과를 페이지네이션하기 위해 Pager 라이브러리를 사용합니다. Model 클래스를 사용할 때 내장된 paginate() 메서드를 사용하여 현재 배치의 결과를 자동으로 가져오고 컨트롤러에서 사용할 수 있도록 Pager 라이브러리를 설정할 수 있습니다. 심지어 page=X 쿼리 변수를 통해 현재 URL에서 표시해야 할 현재 페이지를 읽습니다.

애플리케이션에서 페이지네이션된 사용자 목록을 제공하려면 컨트롤러 메서드는 다음과 같이 구성됩니다:

<?php

namespace App\Controllers;

use App\Models\UserModel;

class UserController extends BaseController
{
    public function index()
    {
        $model = model(UserModel::class);

        $data = [
            'users' => $model->paginate(10),
            'pager' => $model->pager,
        ];

        return view('users/index', $data);
    }
}

이 예시에서는 먼저 UserModel의 새 인스턴스를 생성합니다. 그런 다음 뷰로 보낼 데이터를 채웁니다. 첫 번째 요소는 데이터베이스에서 가져온 users 결과로, 올바른 페이지를 위해 페이지당 10명의 사용자를 반환합니다. 뷰에 전달해야 하는 두 번째 항목은 Pager 인스턴스 자체입니다. 편의를 위해 모델은 사용한 인스턴스를 유지하여 공개 속성 $pager에 저장합니다. 따라서 해당 값을 가져와 뷰의 $pager 변수에 할당합니다.

페이지네이션을 위한 쿼리 사용자 정의

모델에서 페이지네이션을 위한 쿼리를 사용자 정의하려면 paginate() 메서드 전에 쿼리 빌더 메서드를 추가할 수 있습니다.

WHERE 추가

WHERE 조건을 추가하려면 조건을 직접 지정할 수 있습니다:

use App\Models\UserModel;

// In your Controller.
$model = model(UserModel::class);

$data = [
    'users' => $model->where('ban', 1)->paginate(10),
    'pager' => $model->pager,
];

조건을 별도의 메서드로 이동할 수 있습니다:

<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
    // ...

    public function banned()
    {
        $this->builder()->where('ban', 1);

        return $this; // This will allow the call chain to be used.
    }
}
use App\Models\UserModel;

// In your Controller.
$model = model(UserModel::class);

$data = [
    'users' => $model->banned()->paginate(10),
    'pager' => $model->pager,
];

JOIN 추가

다른 테이블을 조인할 수 있습니다:

<?php

namespace App\Models;

use CodeIgniter\Model;

class NewsModel extends Model
{
    protected $table = 'news';

    // ...

    public function getPagination(?int $perPage = null): array
    {
        $this->builder()
            ->select('news.*, category.name')
            ->join('category', 'news.category_id = category.id');

        return [
            'news'  => $this->paginate($perPage),
            'pager' => $this->pager,
        ];
    }
}

중요

Model::paginate() 메서드는 모델의 ModelQuery Builder 인스턴스를 사용한다는 점을 이해하는 것이 중요합니다. 따라서 $db->query()는 쿼리를 즉시 실행하고 쿼리 빌더와 연관되지 않으므로 $db->query()와 함께 Model::paginate()를 사용하려고 하면 동작하지 않습니다.

쿼리 빌더로 작성할 수 없는 복잡한 SQL 쿼리가 필요한 경우 $db->query()Manual Pagination을 사용해 보십시오.

여러 결과 페이지네이션

두 개의 다른 결과 집합에서 링크를 제공해야 하는 경우 데이터를 분리하여 유지하기 위해 대부분의 페이지네이션 메서드에 그룹 이름을 전달할 수 있습니다:

<?php

namespace App\Controllers;

use App\Models\PageModel;
use App\Models\UserModel;

class UserController extends BaseController
{
    public function index()
    {
        $userModel = model(UserModel::class);
        $pageModel = model(PageModel::class);

        $data = [
            'users' => $userModel->paginate(10, 'group1'),
            'pages' => $pageModel->paginate(15, 'group2'),
            'pager' => $userModel->pager,
        ];

        echo view('users/index', $data);
    }
}
?>

<!-- In your view file: -->
<?= $pager->links('group1') ?>
<?= $pager->simpleLinks('group2') ?>

페이지 수동 설정

반환할 결과 페이지를 지정해야 하는 경우 3번째 인수로 페이지를 지정할 수 있습니다. 표시할 페이지를 제어하기 위해 기본 $_GET 변수와 다른 방식을 사용하는 경우 유용합니다.

<?php

use App\Models\UserModel;

$userModel = model(UserModel::class);
$page      = 3;

$users = $userModel->paginate(10, 'group1', $page);

페이지의 URI 세그먼트 지정

페이지 쿼리 파라미터 대신 페이지 번호에 URI 세그먼트를 사용할 수도 있습니다. 네 번째 인수로 사용할 세그먼트 번호를 지정하면 됩니다. 그러면 페이저가 생성하는 URI가 https://domain.tld/foo/bar?page=[pageNumber] 대신 https://domain.tld/foo/bar/[pageNumber]처럼 표시됩니다.

<?php

$users = $userModel->paginate(10, 'group1', null, $segment);

참고: $segment 값은 URI 세그먼트 수에 1을 더한 값보다 클 수 없습니다.

수동 페이지네이션

알려진 데이터를 기반으로 페이지네이션을 생성해야 할 때가 있습니다. makeLinks() 메서드로 링크를 수동으로 생성할 수 있으며, 각각 첫 번째, 두 번째, 세 번째 파라미터로 현재 페이지, 페이지당 결과 수, 전체 항목 수를 받습니다:

<?php

namespace App\Controllers;

class UserController extends BaseController
{
    public function index()
    {
        // ...

        $pager = service('pager');

        $page    = (int) ($this->request->getGet('page') ?? 1);
        $perPage = 20;
        $total   = 200;

        // Call makeLinks() to make pagination links.
        $pager_links = $pager->makeLinks($page, $perPage, $total);

        $data = [
            // ...
            'pager_links' => $pager_links,
        ];

        return view('users/index', $data);
    }
}
?>

<!-- In your view file: -->
<?= $pager_links ?>

기본적으로 링크를 일반적인 방식으로 일련의 링크로 표시하지만, 네 번째 파라미터로 템플릿 이름을 전달하여 사용되는 표시 템플릿을 변경할 수 있습니다. 자세한 내용은 다음 섹션에서 확인할 수 있습니다:

$pager->makeLinks($page, $perPage, $total, 'template_name');

이전 섹션에서 설명한 대로 페이지 쿼리 파라미터 대신 페이지 번호에 URI 세그먼트를 사용할 수도 있습니다. makeLinks()의 다섯 번째 파라미터로 사용할 세그먼트 번호를 지정합니다:

$pager->makeLinks($page, $perPage, $total, 'template_name', $segment);

참고: $segment 값은 URI 세그먼트 수에 1을 더한 값보다 클 수 없습니다.

한 페이지에 여러 페이저를 표시해야 하는 경우 그룹을 정의하는 추가 파라미터가 유용할 수 있습니다:

<?php

$pager = service('pager');
$pager->setPath('path/for/my-group', 'my-group'); // Additionally you could define path for every group.
$pager->makeLinks($page, $perPage, $total, 'template_name', $segment, 'my-group');

페이지네이션 라이브러리는 기본적으로 HTTP 쿼리에 page 쿼리 파라미터를 사용하며 (그룹이 없거나 default 그룹 이름이 지정된 경우), 사용자 정의 그룹 이름에는 page_[groupName]을 사용합니다.

예상 쿼리만으로 페이지네이션

기본적으로 모든 GET 쿼리가 페이지네이션 링크에 표시됩니다.

예를 들어, URL https://domain.tld?search=foo&order=asc&hello=i+am+here&page=2에 접근할 때 다른 링크와 함께 3페이지 링크를 다음과 같이 생성할 수 있습니다:

<?php

echo $pager->links();
// Page 3 link: https://domain.tld?search=foo&order=asc&hello=i+am+here&page=3

only() 메서드를 사용하면 이미 예상된 쿼리로만 제한할 수 있습니다:

<?php

echo $pager->only(['search', 'order'])->links();
// Page 3 link: https://domain.tld?search=foo&order=asc&page=3

page 쿼리는 기본적으로 활성화되어 있습니다. 그리고 only()는 모든 페이지네이션 링크에 작용합니다.