نسخه:

پایگاه داده: صفحه بندی

معرفی

در چارچوب های دیگر، صفحه بندی می تواند بسیار دردناک باشد. امیدواریم رویکرد لاراول به صفحه‌بندی، نفسی تازه باشد. صفحه‌بندی لاراول با سازنده پرس و جو و ORM Eloquent یکپارچه شده است و صفحه‌بندی راحت و آسان رکوردهای پایگاه داده را با پیکربندی صفر فراهم می‌کند.

به‌طور پیش‌فرض، HTML ایجاد شده توسط صفحه‌بندی‌کننده با چارچوب Tailwind CSS سازگار است . با این حال، پشتیبانی از صفحه بندی بوت استرپ نیز در دسترس است.

Tailwind JIT

اگر از نماهای صفحه‌بندی پیش‌فرض Tailwind لاراول و موتور JIT Tailwind استفاده می‌کنید، باید مطمئن شوید که tailwind.config.js فایل‌های برنامه شما content به نماهای صفحه‌بندی لاراول ارجاع دارند تا کلاس‌های Tailwind آن‌ها پاک نشود:

content: [
'./resources/**/*.blade.php',
'./resources/**/*.js',
'./resources/**/*.vue',
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
],

استفاده پایه

صفحه بندی نتایج سازنده پرس و جو

روش های مختلفی برای صفحه بندی آیتم ها وجود دارد. ساده ترین روش استفاده از paginate متد در سازنده پرس و جو یا پرس و جوی Eloquent است . این paginate روش به طور خودکار از تنظیم "محدود" و "offset" درخواست بر اساس صفحه فعلی که توسط کاربر مشاهده می شود، مراقبت می کند. به طور پیش فرض، صفحه فعلی با مقدار آرگومان page رشته پرس و جو در درخواست HTTP شناسایی می شود. این مقدار به‌طور خودکار توسط لاراول شناسایی می‌شود و همچنین به‌طور خودکار در لینک‌های تولید شده توسط صفحه‌نماگر درج می‌شود.

در این مثال، تنها آرگومان ارسال شده به paginate متد، تعداد مواردی است که می‌خواهید در هر صفحه نمایش داده شوند. در این مورد، اجازه دهید مشخص کنیم که می خواهیم 15 موارد را در هر صفحه نمایش دهیم:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
 
class UserController extends Controller
{
/**
* Show all application users.
*/
public function index(): View
{
return view('user.index', [
'users' => DB::table('users')->paginate(15)
]);
}
}

صفحه بندی ساده

این paginate روش، تعداد کل رکوردهای مطابق با پرس و جو را قبل از بازیابی رکوردها از پایگاه داده شمارش می کند. این کار به این دلیل انجام می شود که صفحه بندی کننده بداند در مجموع چند صفحه رکورد وجود دارد. با این حال، اگر قصد ندارید تعداد کل صفحات را در رابط کاربری برنامه خود نشان دهید، پرس و جو تعداد رکوردها غیر ضروری است.

بنابراین، اگر فقط نیاز دارید که پیوندهای ساده «بعدی» و «قبلی» را در رابط کاربری برنامه‌تان نمایش دهید، می‌توانید از این simplePaginate روش برای انجام یک پرس و جوی کارآمد استفاده کنید:

$users = DB::table('users')->simplePaginate(15);

صفحه بندی نتایج شیوا

همچنین می توانید پرس و جوهای Eloquent را صفحه بندی کنید . در این مثال، مدل را صفحه بندی می کنیم App\Models\User و نشان می دهیم که قصد داریم 15 رکورد در هر صفحه نمایش دهیم. همانطور که می بینید، نحو تقریباً با صفحه بندی نتایج سازنده پرس و جو یکسان است:

use App\Models\User;
 
$users = User::paginate(15);

البته، می‌توانید paginate متد را پس از تعیین محدودیت‌های دیگر روی کوئری فراخوانی کنید، مانند where بندهای:

$users = User::where('votes', '>', 100)->paginate(15);

همچنین می‌توانید simplePaginate هنگام صفحه‌بندی مدل‌های Eloquent از این روش استفاده کنید:

$users = User::where('votes', '>', 100)->simplePaginate(15);

به طور مشابه، می توانید از cursorPaginate روش برای صفحه بندی مدل های Eloquent استفاده کنید:

$users = User::where('votes', '>', 100)->cursorPaginate(15);

چندین نمونه صفحه‌کننده در هر صفحه

گاهی اوقات ممکن است لازم باشد دو صفحه‌نمای جداگانه را در یک صفحه که توسط برنامه شما ارائه می‌شود، رندر کنید. با این حال، اگر هر دو نمونه صفحه‌بندی‌کننده از page پارامتر رشته query برای ذخیره صفحه فعلی استفاده کنند، دو صفحه‌کننده با هم تضاد خواهند داشت. برای حل این تضاد، می توانید نام پارامتر رشته پرس و جو را که می خواهید برای ذخیره صفحه فعلی صفحه بندی کننده از طریق آرگومان سوم ارائه شده به متدهای، paginate و simplePaginate و ارسال کنید cursorPaginate :

use App\Models\User;
 
$users = User::where('votes', '>', 100)->paginate(
$perPage = 15, $columns = ['*'], $pageName = 'users'
);

صفحه بندی مکان نما

در حالی که paginate و simplePaginate با استفاده از عبارت "offset" SQL پرس و جو ایجاد می کند، صفحه بندی مکان نما با ساخت بندهای "where" کار می کند که مقادیر ستون های مرتب شده موجود در پرس و جو را مقایسه می کند و کارآمدترین عملکرد پایگاه داده موجود را در بین تمام روش های صفحه بندی لاراول ارائه می دهد. این روش صفحه بندی به ویژه برای مجموعه داده های بزرگ و رابط های کاربری پیمایش "بی نهایت" مناسب است.

بر خلاف صفحه‌بندی مبتنی بر افست، که شامل یک شماره صفحه در رشته جستجوی URLهای تولید شده توسط صفحه‌بندی کننده است، صفحه‌بندی مبتنی بر مکان‌نما یک رشته «مکان‌نما» را در رشته جستجو قرار می‌دهد. مکان نما یک رشته رمزگذاری شده است که حاوی مکانی است که پرس و جوی صفحه بندی شده بعدی باید صفحه بندی را شروع کند و جهتی که باید صفحه بندی شود:

http://localhost/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0

می‌توانید یک نمونه صفحه‌نمای مبتنی بر مکان‌نما را از طریق cursorPaginate روش ارائه‌شده توسط سازنده پرس و جو ایجاد کنید. این متد یک نمونه از Illuminate\Pagination\CursorPaginator :

$users = DB::table('users')->orderBy('id')->cursorPaginate(15);

هنگامی که یک نمونه صفحه‌بندی مکان‌نما را بازیابی کردید، می‌توانید نتایج صفحه‌بندی را همانطور که معمولاً هنگام استفاده از متدهای paginate و نمایش می‌دهید، نمایش دهید simplePaginate . برای اطلاعات بیشتر در مورد روش‌های نمونه ارائه شده توسط صفحه‌نمای مکان‌نما، لطفاً به مستندات روش نمونه‌ای صفحه‌نمای مکان‌نما مراجعه کنید .

جستجوی شما باید حاوی یک بند "ترتیب بر اساس" باشد تا از صفحه بندی مکان نما استفاده کنید. علاوه بر این، ستون هایی که پرس و جو بر اساس آنها مرتب شده اند باید متعلق به جدولی باشند که صفحه بندی می کنید.

مکان نما در مقابل صفحه بندی افست

برای نشان دادن تفاوت‌های بین صفحه‌بندی افست و صفحه‌بندی مکان‌نما، اجازه دهید چند نمونه پرس و جوی SQL را بررسی کنیم. هر دو پرس و جوی زیر هر دو "صفحه دوم" نتایج را برای یک users جدول به ترتیب توسط id :

# Offset Pagination...
select * from users order by id asc limit 15 offset 15;
 
# Cursor Pagination...
select * from users where id > 15 order by id asc limit 15;

پرس و جو صفحه بندی مکان نما مزایای زیر را نسبت به صفحه بندی افست ارائه می دهد:

  • برای مجموعه داده های بزرگ، صفحه بندی مکان نما عملکرد بهتری را ارائه می دهد اگر ستون های "ترتیب بر اساس" ایندکس شوند. این به این دلیل است که بند "offset" تمام داده های قبلاً مطابقت شده را اسکن می کند.
  • برای مجموعه‌های داده با نوشتن مکرر، صفحه‌بندی افست ممکن است رکوردها را رد کند یا موارد تکراری را نشان دهد اگر نتایج اخیراً به صفحه‌ای که کاربر در حال مشاهده آن است اضافه یا از آن حذف شده باشد.

با این حال، صفحه بندی مکان نما دارای محدودیت های زیر است:

  • مانند simplePaginate صفحه بندی مکان نما فقط می تواند برای نمایش پیوندهای "بعدی" و "قبلی" استفاده شود و از ایجاد پیوند با شماره صفحه پشتیبانی نمی کند.
  • این مستلزم آن است که ترتیب حداقل بر اساس یک ستون منحصر به فرد یا ترکیبی از ستون های منحصر به فرد باشد. ستون های دارای null مقادیر پشتیبانی نمی شوند.
  • عبارات پرس و جو در بندهای "ترتیب بر اساس" فقط در صورتی پشتیبانی می شوند که نام مستعار داشته باشند و به عبارت "انتخاب" نیز اضافه شوند.
  • عبارات پرس و جو با پارامترها پشتیبانی نمی شوند.

ایجاد یک صفحه‌نما به صورت دستی

گاهی اوقات ممکن است بخواهید یک نمونه صفحه بندی را به صورت دستی ایجاد کنید و مجموعه ای از مواردی را که قبلاً در حافظه دارید به آن ارسال کنید. بسته به نیازتان می‌توانید این کار را با ایجاد یک یا نمونه انجام دهید Illuminate\Pagination\Paginator . Illuminate\Pagination\LengthAwarePaginator Illuminate\Pagination\CursorPaginator

نیازی به دانستن تعداد کل آیتم ها در مجموعه نتیجه نیست Paginator . CursorPaginator با این حال، به این دلیل، این کلاس ها روشی برای بازیابی فهرست صفحه آخر ندارند. LengthAwarePaginator تقریبا همان آرگومان‌هایی را می‌پذیرد که Paginator ; با این حال، نیاز به شمارش تعداد کل موارد در مجموعه نتیجه دارد.

به عبارت دیگر، Paginator مربوط به simplePaginate متد در سازنده پرس و جو، CursorPaginator مربوط به cursorPaginate متد، و LengthAwarePaginator مربوط به paginate متد است.

هنگامی که به صورت دستی یک نمونه صفحه‌کننده ایجاد می‌کنید، باید آرایه‌ای از نتایج را که به صفحه‌بندی‌کننده ارسال می‌کنید، به‌صورت دستی «برش» کنید. اگر مطمئن نیستید که چگونه این کار را انجام دهید، تابع array_slice PHP را بررسی کنید.

سفارشی کردن URL های صفحه بندی

به‌طور پیش‌فرض، پیوندهای ایجاد شده توسط صفحه‌نگار با URI درخواست فعلی مطابقت دارند. با این حال، روش صفحه‌بندی‌کننده withPath به شما اجازه می‌دهد تا URI مورد استفاده صفحه‌کننده را هنگام ایجاد پیوندها سفارشی کنید. به عنوان مثال، اگر می خواهید صفحه بندی کننده پیوندهایی مانند ایجاد کند http://example.com/admin/users?page=N ، باید /admin/users به withPath روش زیر بروید:

use App\Models\User;
 
Route::get('/users', function () {
$users = User::paginate(15);
 
$users->withPath('/admin/users');
 
// ...
});

افزودن مقادیر رشته کوئری

می توانید با استفاده از روش به رشته پرس و جو پیوندهای صفحه بندی اضافه کنید appends . به عنوان مثال، برای الحاق sort=votes به هر پیوند صفحه بندی، باید با شماره زیر تماس بگیرید appends :

use App\Models\User;
 
Route::get('/users', function () {
$users = User::paginate(15);
 
$users->appends(['sort' => 'votes']);
 
// ...
});

withQueryString اگر می خواهید تمام مقادیر رشته پرس و جو درخواست فعلی را به پیوندهای صفحه بندی اضافه کنید، می توانید از این روش استفاده کنید :

$users = User::paginate(15)->withQueryString();

افزودن قطعات هش

اگر نیاز به اضافه کردن یک "پاره درهم" به URL های تولید شده توسط صفحه بندی کننده دارید، می توانید از این fragment روش استفاده کنید. به عنوان مثال، برای الحاق #users به انتهای هر پیوند صفحه بندی، باید fragment روشی را مانند زیر فراخوانی کنید:

$users = User::paginate(15)->fragment('users');

نمایش نتایج صفحه بندی

هنگام فراخوانی paginate متد، نمونه ای از را دریافت خواهید کرد Illuminate\Pagination\LengthAwarePaginator ، در حالی که فراخوانی simplePaginate متد، نمونه ای از را برمی گرداند Illuminate\Pagination\Paginator . و در نهایت، فراخوانی cursorPaginate متد نمونه ای از Illuminate\Pagination\CursorPaginator .

این اشیاء چندین روش ارائه می دهند که مجموعه نتایج را توصیف می کنند. علاوه بر این روش های کمکی، نمونه های صفحه بندی کننده تکرار کننده هستند و ممکن است به عنوان یک آرایه حلقه شوند. بنابراین، هنگامی که نتایج را بازیابی کردید، می توانید نتایج را نمایش دهید و پیوندهای صفحه را با استفاده از Blade ارائه دهید :

<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
 
{{ $users->links() }}

این links روش پیوندها را به بقیه صفحات در مجموعه نتیجه نمایش می دهد. هر یک از این پیوندها قبلاً حاوی متغیر رشته پرس و جو مناسب هستند page . به یاد داشته باشید، HTML تولید شده توسط این links روش با چارچوب Tailwind CSS سازگار است .

وقتی صفحه‌بندی پیوندهای صفحه‌بندی را نمایش می‌دهد، شماره صفحه فعلی و همچنین پیوندهای سه صفحه قبل و بعد از صفحه فعلی نمایش داده می‌شود. با استفاده از این onEachSide روش، می‌توانید کنترل کنید که چه تعداد پیوند اضافی در هر طرف صفحه جاری در پنجره کشویی میانی پیوندهای ایجاد شده توسط صفحه‌بندی کننده نمایش داده می‌شود:

{{ $users->onEachSide(5)->links() }}

تبدیل نتایج به JSON

کلاس‌های صفحه‌نمای لاراول Illuminate\Contracts\Support\Jsonable قرارداد Interface را پیاده‌سازی می‌کنند و toJson روش را آشکار می‌کنند، بنابراین تبدیل نتایج صفحه‌بندی به JSON بسیار آسان است. همچنین می‌توانید یک نمونه صفحه‌نما را با بازگرداندن آن از یک مسیر یا عملکرد کنترل‌کننده به JSON تبدیل کنید:

use App\Models\User;
 
Route::get('/users', function () {
return User::paginate();
});

JSON از صفحه‌بندی کننده شامل اطلاعات متا مانند total ،،، و غیره current_page خواهد بود. last_page رکوردهای نتیجه از طریق data کلید در آرایه JSON در دسترس هستند. در اینجا نمونه ای از JSON ایجاد شده با برگرداندن یک نمونه صفحه بندی از یک مسیر است:

{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"first_page_url": "http://laravel.app?page=1",
"last_page_url": "http://laravel.app?page=4",
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"path": "http://laravel.app",
"from": 1,
"to": 15,
"data":[
{
// Record...
},
{
// Record...
}
]
}

سفارشی کردن نمای صفحه بندی

به طور پیش فرض، نماهایی که برای نمایش پیوندهای صفحه بندی ارائه می شوند با چارچوب Tailwind CSS سازگار هستند . با این حال، اگر از Tailwind استفاده نمی‌کنید، می‌توانید دیدگاه‌های خود را برای ارائه این پیوندها تعریف کنید. هنگام فراخوانی links متد در یک نمونه صفحه‌بندی، می‌توانید نام view را به عنوان اولین آرگومان به متد ارسال کنید:

{{ $paginator->links('view.name') }}
 
<!-- Passing additional data to the view... -->
{{ $paginator->links('view.name', ['foo' => 'bar']) }}

با این حال، ساده ترین راه برای سفارشی کردن نماهای صفحه بندی، صادر کردن آنها به resources/views/vendor دایرکتوری با استفاده از vendor:publish دستور زیر است:

php artisan vendor:publish --tag=laravel-pagination

این دستور view ها را در دایرکتوری برنامه شما قرار می دهد resources/views/vendor/pagination . فایل tailwind.blade.php درون این فهرست با نمای صفحه‌بندی پیش‌فرض مطابقت دارد. شما می توانید این فایل را برای تغییر HTML صفحه بندی ویرایش کنید.

اگر می‌خواهید فایل دیگری را به عنوان نمای صفحه‌بندی پیش‌فرض تعیین کنید، می‌توانید صفحه‌بندی‌کننده defaultView و defaultSimpleView متدها را در boot متد کلاس خود فراخوانی کنید App\Providers\AppServiceProvider :

<?php
 
namespace App\Providers;
 
use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Paginator::defaultView('view-name');
 
Paginator::defaultSimpleView('view-name');
}
}

با استفاده از بوت استرپ

لاراول شامل نماهای صفحه بندی است که با استفاده از Bootstrap CSS ساخته شده است . برای استفاده از این نماها به جای نماهای پیش‌فرض Tailwind، می‌توانید صفحه‌بندی useBootstrapFour یا useBootstrapFive متدهای درون boot متد کلاس خود را فراخوانی کنید App\Providers\AppServiceProvider :

use Illuminate\Pagination\Paginator;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Paginator::useBootstrapFive();
Paginator::useBootstrapFour();
}

روش‌های نمونه Paginator / LengthAwarePaginator

هر نمونه صفحه‌بندی اطلاعات اضافی صفحه‌بندی را از طریق روش‌های زیر ارائه می‌کند:

روش شرح
$paginator->count() تعداد موارد صفحه فعلی را دریافت کنید.
$paginator->currentPage() شماره صفحه فعلی را دریافت کنید.
$paginator->firstItem() شماره نتیجه اولین مورد را در نتایج بدست آورید.
$paginator->getOptions() گزینه های صفحه بندی را دریافت کنید.
$paginator->getUrlRange($start, $end) محدوده ای از URL های صفحه بندی ایجاد کنید.
$paginator->hasPages() تعیین کنید که آیا موارد کافی برای تقسیم به چند صفحه وجود دارد یا خیر.
$paginator->hasMorePages() تعیین کنید که آیا موارد بیشتری در فروشگاه داده وجود دارد یا خیر.
$paginator->items() موارد مربوط به صفحه فعلی را دریافت کنید.
$paginator->lastItem() شماره نتیجه آخرین مورد را در نتایج بدست آورید.
$paginator->lastPage() شماره صفحه آخرین صفحه موجود را دریافت کنید. (هنگام استفاده در دسترس نیست simplePaginate ).
$paginator->nextPageUrl() آدرس صفحه بعدی را دریافت کنید.
$paginator->onFirstPage() تعیین کنید صفحه‌بندی در صفحه اول است یا خیر.
$paginator->perPage() تعداد مواردی که باید در هر صفحه نشان داده شود.
$paginator->previousPageUrl() آدرس صفحه قبل را دریافت کنید.
$paginator->total() تعداد کل موارد منطبق را در ذخیره‌گاه داده تعیین کنید. (هنگام استفاده در دسترس نیست simplePaginate ).
$paginator->url($page) نشانی اینترنتی شماره صفحه معین را دریافت کنید.
$paginator->getPageName() متغیر رشته کوئری مورد استفاده برای ذخیره صفحه را دریافت کنید.
$paginator->setPageName($name) متغیر رشته کوئری مورد استفاده برای ذخیره صفحه را تنظیم کنید.
$paginator->through($callback) هر مورد را با استفاده از پاسخ به تماس تغییر دهید.

روش‌های نمونه صفحه‌نمای مکان‌نما

هر نمونه صفحه‌بندی مکان‌نما اطلاعات صفحه‌بندی اضافی را از طریق روش‌های زیر فراهم می‌کند:

روش شرح
$paginator->count() تعداد موارد صفحه فعلی را دریافت کنید.
$paginator->cursor() نمونه مکان نما فعلی را دریافت کنید.
$paginator->getOptions() گزینه های صفحه بندی را دریافت کنید.
$paginator->hasPages() تعیین کنید که آیا موارد کافی برای تقسیم به چند صفحه وجود دارد یا خیر.
$paginator->hasMorePages() تعیین کنید که آیا موارد بیشتری در فروشگاه داده وجود دارد یا خیر.
$paginator->getCursorName() متغیر رشته کوئری مورد استفاده برای ذخیره مکان نما را دریافت کنید.
$paginator->items() موارد مربوط به صفحه فعلی را دریافت کنید.
$paginator->nextCursor() نمونه مکان نما را برای مجموعه آیتم های بعدی دریافت کنید.
$paginator->nextPageUrl() آدرس صفحه بعدی را دریافت کنید.
$paginator->onFirstPage() تعیین کنید صفحه‌بندی در صفحه اول است یا خیر.
$paginator->onLastPage() تعیین کنید صفحه‌بندی در آخرین صفحه است یا خیر.
$paginator->perPage() تعداد مواردی که باید در هر صفحه نشان داده شود.
$paginator->previousCursor() نمونه مکان نما را برای مجموعه موارد قبلی دریافت کنید.
$paginator->previousPageUrl() آدرس صفحه قبل را دریافت کنید.
$paginator->setCursorName() متغیر رشته کوئری مورد استفاده برای ذخیره مکان نما را تنظیم کنید.
$paginator->url($cursor) نشانی اینترنتی یک نمونه مکان نما را دریافت کنید.