webfox / laravel-inertia-dataproviders
封装 Inertia 视图逻辑的数据提供者
Requires
- php: ^8.2
- illuminate/contracts: ^11.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- inertiajs/inertia-laravel: <2
- jetbrains/phpstorm-attributes: ^1.0
- larastan/larastan: ^v2.9
- nunomaduro/collision: ^v8.1
- orchestra/testbench: ^v9.0
- pestphp/pest: ^v2.34
- pestphp/pest-plugin-laravel: ^v2.3
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^10.5
Suggests
- inertiajs/inertia-laravel: Needed for basic inertia functionality
README
数据提供者封装 Inertia 视图逻辑,使您的控制器保持简洁。
安装
通过 composer 安装此包
composer require webfox/laravel-inertia-dataproviders
可选地发布配置文件
php artisan vendor:publish --provider="Webfox\InertiaDataProviders\InertiaDataProvidersServiceProvider"
我们假设您已经安装了 Laravel 的 Inertia 适配器。
此包解决了什么问题?
Laravel 的控制器本应保持简洁。我们已经有表单请求来提取验证和授权逻辑,而我们的显示逻辑在视图中,那么为什么我们还要坚持让控制器处理为这些视图获取数据呢?
这在引入了类似懒加载属性等概念的情况下,在 Inertia 应用中表现得尤为明显。
数据提供者将 Inertia 视图的数据组合提取到它们自己的类中。如果您的应用程序中的多个路由或控制器需要特定的数据,Inertia 数据提供者可能会非常有用。
不再需要 40 行的控制器方法来获取数据了!
用法
使用数据提供者
数据提供者利用了 Inertia::render
可以接受 Arrayable
的特性。它们也可以用作数据数组中的离散属性。
use App\Models\Demo; use App\DataProviders\DemoDataProvider; class DemoController extends Controller { public function show(Demo $demo) { return Inertia::render('DemoPage', new DemoDataProvider($demo)); } public function edit(Demo $demo) { return Inertia::render('DemoPage', [ 'some' => 'data', 'more' => 'data', 'demo' => new DemoDataProvider($demo), ]); } }
数据提供者是什么样的?
数据提供者可以放在任何地方,但在这个例子中我们将使用 App/Http/DataProviders
。
最简单的数据提供者只是一个扩展 DataProvider
的类,任何公共方法或属性都将作为数据提供给页面。
一个功能齐全的数据提供者可能如下所示
<?php declare(strict_types=1); namespace App\Http\DataProviders; use Inertia\LazyProp; use App\Services\InjectedDependency; use Webfox\InertiaDataProviders\DataProvider; class DemoDataProvider extends DataProvider { public function __construct( /* * All public properties are automatically available in the page * This would be available to the page as `demo` */ public Demo $demo; ) { /* * Data providers have a `staticData` property, which you can use to add any data that doesn't warrant a full * property or separate method */ $this->staticData = [ /* * This will be available to the page as `title` */ 'title' => $this->calculateTitle($demo), ]; } /* * All public methods are automatically evaluated as data and provided to the page. * ALWAYS included on first visit, OPTIONALLY included on partial reloads, ALWAYS evaluated * This would be available to the page as `someData`. * Additionally these methods are resolved through Laravel's service container, so any parameters will be automatically resolved. */ public function someData(InjectedDependency $example): array { return [ 'some' => $example->doThingWith('some'), 'more' => 'data', ]; } /* * If a method returns a `Closure` it will be evaluated as a lazy property. * ALWAYS included on first visit, OPTIONALLY included on partial reloads, ONLY evaluated when needed * Additionally the callback methods are resolved through Laravel's service container, so any parameters will be automatically resolved. * @see https://inertia.laravel.net.cn/partial-reloads#lazy-data-evaluation */ public function quickLazyExample(): Closure { return function(InjectedDependency $example): string { return $example->formatName($this->demo->user->name); }; } /* * If a method is typed to return a LazyProp, it will only be evaluated when requested following inertia's rules for lazy data evaluation * NEVER included on first visit, OPTIONALLY included on partial reloads, ONLY evaluated when needed * Additionally the lazy callback methods are resolved through Laravel's service container, so any parameters will be automatically resolved. * @see https://inertia.laravel.net.cn/partial-reloads#lazy-data-evaluation */ public function lazyExample(): LazyProp { return Inertia::lazy( fn (InjectedDependency $example) => $example->aHeavyCalculation($this->demo) ); } /* * `protected` and `private` methods are not available to the page */ protected function calculateTitle(Demo $demo): string { return $demo->name . ' Demo'; } }
使用多个数据提供者
有时您可能需要返回多个数据提供者,DataProvider::collection
是您的方法。集合中的每个数据提供者都将被评估并合并到页面的数据中,来自数据提供者的后续值将覆盖早期数据提供者的值。
use App\Models\Demo; use App\DataProviders\TabDataProvider; use App\DataProviders\DemoDataProvider; class DemoController extends Controller { public function show(Demo $demo) { return Inertia::render('DemoPage', DataProvider::collection( new TabDataProvider(current: 'demo'), new DemoDataProvider($demo), )); } }
您还可以根据条件将数据提供者包含在集合中
use App\Models\Demo; use App\DataProviders\TabDataProvider; use App\DataProviders\DemoDataProvider; use App\DataProviders\EditDemoDataProvider; use App\DataProviders\CreateVenueDataProvider; class DemoController extends Controller { public function show(Demo $demo) { return Inertia::render('DemoPage', DataProvider::collection( new TabDataProvider(current: 'demo'), new DemoDataProvider($demo), )->when($demo->has_venue, function (DataProviderCollection $collection) use($demo) { $collection->push(new CreateVenueDataProvider($demo)); }) ->unless($demo->locked, function (DataProviderCollection $collection) use($demo) { $collection->push(new EditDemoDataProvider($demo)); })); } }
或者您可以使用 DataProviderCollection::add
方法在稍后添加数据提供者到集合
use App\Models\Demo; use App\DataProviders\TabDataProvider; use App\DataProviders\DemoDataProvider; use App\DataProviders\CreateVenueDataProvider; class DemoController extends Controller { public function show(Demo $demo) { $pageData = DataProvider::collection( new TabDataProvider(current: 'demo'), new DemoDataProvider($demo), ); if($demo->has_venue) { $pageData->add(new CreateVenueDataProvider($demo)); } return Inertia::render('DemoPage', $pageData); } }
如果您需要将整个数据集作为数组返回,例如用于 JSON 响应,您可以使用 toNestedArray()
use App\Models\Demo; use Illuminate\Http\Request; use App\DataProviders\TabDataProvider; use App\DataProviders\DemoDataProvider; use App\DataProviders\CreateVenueDataProvider; class DemoController extends Controller { public function show(Request $request, Demo $demo) { return (new DemoDataProvider($demo))->toNestedArray(); } }
属性名称格式化
可以通过在配置文件中将 attribute_name_formatter
设置来配置属性名称格式。
该包包含三个格式化程序,位于命名空间 \Webfox\InertiaDataProviders\AttributeNameFormatters
下,但您可以自由创建自己的。
AsWritten
这是默认格式化程序。输出属性名称将与输入名称相同。例如,名为 $someData
的属性和名为 more_data()
的方法将在页面中作为 someData
和 more_data
可用。
SnakeCase
此格式化程序将属性名称转换为 snake_case。
例如,名为 $someData
的属性和名为 more_data()
的方法将在页面中作为 some_data
和 more_data
可用。
CamelCase
此格式化程序将属性名称转换为 camelCase。
例如,名为 $someData
的属性和名为 more_data()
的方法将在页面中作为 someData
和 moreData
可用。
变更日志
请参阅变更日志以获取有关最近变更的更多信息。
贡献
我们欢迎所有对项目做出贡献的人。
许可证
MIT 许可证 (MIT)。请参阅许可证文件以获取更多信息。