Octane環境下ではLaravelとLivewireのページネーションを併用しにくい
バージョン
- Laravel 9.x
- Livewire 2.x
- Octane 1.x (Vapor+Octane)
- PHP 8.1
WithPagination
Livewireのページネーションは普通に使うだけなら変わったことしてないように見えるけど詳しく見るとinitializeWithPagination()
でLivewire独自の動作に変更している。
if (class_exists(CursorPaginator::class)) {
CursorPaginator::currentCursorResolver(function ($pageName){
if (! isset($this->paginators[$pageName])) {
$this->paginators[$pageName] = request()->query($pageName, '');
}
return Cursor::fromEncoded($this->paginators[$pageName]);
});
}
Paginator::currentPageResolver(function ($pageName) {
if (! isset($this->paginators[$pageName])) {
$this->paginators[$pageName] = request()->query($pageName, 1);
}
return (int) $this->paginators[$pageName];
});
Paginator::defaultView($this->paginationView());
Paginator::defaultSimpleView($this->paginationSimpleView());
Paginator::currentPageResolver
やPaginator::defaultView
はここでstaticプロパティを変更している。
/**
* The current page resolver callback.
*
* @var \Closure
*/
protected static $currentPageResolver;
/**
* Set the current page resolver callback.
*
* @param \Closure $resolver
* @return void
*/
public static function currentPageResolver(Closure $resolver)
{
static::$currentPageResolver = $resolver;
}
Octaneだとstaticプロパティなことが困る原因。
- Livewireのページネーションを先に表示。この時にstaticプロパティが上書きされる。Octaneでは次のリクエストでも上書きされたまま。
- Laravelの通常のページネーションを表示しても上書きされたstaticプロパティを元に表示されるのでエラーになる。Octaneでなければ毎回リセットされるので影響はない。
試行錯誤
viewが違うのは
表示時に指定すればいいけど全部で指定は面倒。
{{ $posts->links('pagination::tailwind') }}
AppServiceProvider::boot()ではLaravelページネーションを表示時にstaticプロパティを再度上書きはできそうにない。
Paginator::defaultView('pagination::tailwind');
Paginator::defaultSimpleView('pagination::simple-tailwind');
links()で表示するタイミングでviewを指定する。
defaultView()はデフォルトなので指定すればデフォルトは使われない。(この時点でのデフォルトはLivewireが上書きしたviewファイル)
Resolverのリセット
PaginationState::resolveUsing()
でリセットはできそう。
Laravel内部ではここで使われている。
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
PaginationState::resolveUsing($this->app);
}
同じようにAppServiceProviderに書けばいいかと思ったけど解決しなかった。
viewと同じく表示時にコントローラーで毎回リセット。
use Illuminate\Pagination\PaginationState;
//...
public function index(Request $request)
{
PaginationState::resolveUsing(app());
$posts = Post::latest()->paginate();
return view('post.index')->with(compact('posts'));
}
面倒なことを除けばLaravel側のページネーションは直ったけど今度はLivewire側のページネーションでエラーが出るようになった。
OctaneのListenerでリセット(最善策)
config/octane.php
でListenerを設定してリクエストごとに初期化するのが現状での解決策っぽい。
RequestReceived::class => [
...Octane::prepareApplicationForNextOperation(),
...Octane::prepareApplicationForNextRequest(),
//
],
流れを追っていくとRequestReceived
イベント発生時に色々な初期化処理をしている。
prepareApplicationForNextOperation()
にはPrepareLivewireForNextOperation
があって
PrepareLivewireForNextOperation
ではLivewireのflushState()
を呼んでいる。
flushState()
ではページネーションはないので自分で行う。
まずListenerを作成。
sail art make:listener FlushPagination
もしくは
php artisan make:listener FlushPagination
FlushPagination.phpは以下
<?php
namespace App\Listeners;
use Illuminate\Pagination\PaginationState;
use Illuminate\Pagination\Paginator;
class FlushPagination
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
Paginator::useTailwind();
PaginationState::resolveUsing($event->sandbox);
}
}
config/octane.php
に追加。
RequestReceived::class => [
...Octane::prepareApplicationForNextOperation(),
...Octane::prepareApplicationForNextRequest(),
//
\App\Listeners\FlushPagination::class,
],
useTailwind()
は以下と同じ。Tailwindではないなら好きなように変更。
Paginator::defaultView('pagination::tailwind');
Paginator::defaultSimpleView('pagination::simple-tailwind');
$event->sandbox
でもapp()
でも同じはず。
これでviewの毎回指定は不要。
{{ $posts->links() }}
ServiceProviderやコントローラーでのPaginationState::resolveUsing()
も不要。
LaravelのページネーションとLivewireのページネーションを使ったページを行き来してもエラーは出ない。
普通に使って何も問題はなくなった。他に問題が出て来ないかはしばらく使ってみないと確認できない。
Author And Source
この問題について(Octane環境下ではLaravelとLivewireのページネーションを併用しにくい), 我々は、より多くの情報をここで見つけました https://qiita.com/pop-culture-studio/items/1864beaa4609fe3c7c58著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .