okipa / laravel-brickables
简化页面内容砖块管理。
Requires
- php: 8.1.*|8.2.*
- illuminate/contracts: ^9.0|^10.0
- spatie/eloquent-sortable: 4.0.2
Requires (Dev)
- brianium/paratest: ^6.4
- laravel/pint: ^1.1
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0
- orchestra/testbench: ^7.0|^8.0
- phpmd/phpmd: ^2.11
README
此包已被废弃,如果您仍需要使用,请谨慎使用。
如果您感兴趣,请fork此包并赋予它新的生命!
此包允许您将内容砖块关联到Eloquent模型,并提供一个可完全自定义的管理面板来管理它们。
此包附带了一些预构建的砖块。您可以直接使用它们,但您绝对应该将它们视为示例:自定义它们或创建新的它们已被设计得尽可能简单!🔥
觉得这个包有帮助?请考虑支持我的工作!
兼容性
Laravel版本 | PHP版本 | 包版本 |
---|---|---|
^9.0 | ^10.0 | 8.1.* | 8.2.* | ^3.2 |
^8.0 | ^9.0 | ^8.1 | ^8.2 | ^3.1 |
^8.0 | ^9.0 | ^8.0 | ^8.1 | ^3.0 |
^7.0 | ^8.0 | ^7.4 | ^8.0 | ^2.0 |
^5.8 | ^6.0 | ^7.0 | ^7.1 | ^7.2 | ^7.3 | ^7.4 | ^1.0 |
升级指南
使用方法
将内容砖块关联到Eloquent模型
$page = Page::find(1); // Associate one content brick $page->addBrick(OneTextColumn::class, ['text' => 'Text']); // Or associate several content bricks at once $page->addBricks([ [OneTextColumn::class, ['text' => 'Text']], [TwoTextColumns::class, ['text_left' => 'Left text', 'text_right' => 'Right text']] ]);
在视图中显示砖块
{{-- All at once --}} {!! $page->displayBricks() !!} {{-- Or one by one --}} {{ $page->getFirstBrick(OneTextColumn::class) }}
在视图中显示与模型相关的砖块管理面板
{{ $page->displayAdminPanel() }}
目录
安装
通过composer安装包
composer require okipa/laravel-brickables
然后,发布并运行数据库迁移
php artisan vendor:publish --tag=laravel-brickables:migrations php artisan migrate
最后,为了利用智能加载砖块CSS和JS资源,请将以下指令添加到您的blade布局中,如下所示
{{-- layout.blade.php --}} <html> <head> @brickablesCss </head> <body> @yield('content') @brickablesJs </body> </html>
配置
发布包配置
php artisan vendor:publish --tag=laravel-brickables:config
⚠️您可能需要运行composer dump-autoload
来在配置文件中更改路径后。
视图
发布包视图
php artisan vendor:publish --tag=laravel-brickables:views
翻译
本包中使用的所有单词和句子均可翻译。
查看如何在Laravel官方文档中翻译它们: https://laravel.net.cn/docs/localization#using-translation-strings-as-keys。
以下是默认可翻译的单词和句子列表
内容砖块
没有保存的内容砖块。
内容
左侧内容
右侧内容
砖块数据
添加
编辑
更新
销毁
取消
上移
下移
已创建 :model > :brickable 的条目。
已更新 :model > :brickable 的条目。
已删除 :model > :brickable 的条目。
您还必须定义 validation.attributes.brickable_types
的翻译。
最后,您必须翻译每个已注册的砖块标签翻译。
实现
模型
实现 HasBrickables
接口,并使用 HasBrickablesTrait
特性,将其应用于您希望与内容砖块关联的任何 Eloquent 模型。
use Illuminate\Database\Eloquent\Model; use Okipa\LaravelBrickables\Contracts\HasBrickables; use Okipa\LaravelBrickables\Traits\HasBrickablesTrait; class Page extends Model implements HasBrickables { use HasBrickablesTrait; // ... }
路由
添加内容砖块管理面板所需的基本 web
路由。
Brickables::routes();
这些路由默认使用 Okipa\LaravelBrickables\Controllers\BricksController
控制器。
要自定义管理面板操作,您可以在砖块路由组内部或外部添加路由。
Brickables::routes(function(){ // Inside the routes group: will benefit from the CRUDBrickable middleware. }); // Outside the route group: will not benefit from the CRUDBrickable middleware.
查看 赋予砖块额外能力 部分以获取更多有关自定义可能性的信息。
如何做
为模型定义砖块约束
在您的 Eloquent 模型中,您可以可选地定义约束
- 定义模型有权管理的砖块
- 定义模型必须拥有的每个砖块的最小数量
- 定义模型可以拥有的每个砖块的最大数量
use Illuminate\Database\Eloquent\Model; use Okipa\LaravelBrickables\Contracts\HasBrickables; use Okipa\LaravelBrickables\Traits\HasBrickablesTrait; class Page extends Model implements HasBrickables { use HasBrickablesTrait; public array $brickables = [ 'can_only_handle' => [OneTextColumn::class], // By default all registered brickables can be handled. 'number_of_bricks' => [OneTextColumn::class => ['min' => 1, 'max' => 3]], // By default, there are no number restrictions. ]; // ... }
在此示例中
Page
模型只能处理OneTextColumn
砖块。- 管理面板只允许管理
OneTextColumn
砖块。 - 如果只剩下一个
OneTextColumn
砖块,则管理面板不允许删除该砖块。 - 如果已添加了 3 个,则管理面板不允许添加更多
OneTextColumn
砖块。 - 程序性地清除此模型的所有砖块将保留位置最高的
OneTextColumn
。 - 程序性地添加第 4 个
OneTextColumn
砖块将引发ModelHasReachedMaxNumberOfBricksException
。
重要提示:您可以通过将其最大数设置为 0
来禁用模型对砖块管理的权限。
添加内容砖块
将单个内容砖块关联到 Eloquent 模型
$brick = $page->addBrick(OneTextColumn::class, ['text' => 'Text']);
您还可以一次性关联多个内容砖块
$bricks = $page->addBricks([ [OneTextColumn::class, ['text' => 'Text']], [TwoTextColumns::class, ['text_left' => 'Left text', 'text_right' => 'Right text']] ]);
更新内容砖块
只需像更新任何其他 Eloquent 模型实例一样更新您的内容砖块
// As data are stored in json, you will have to process this way: https://github.com/laravel/framework/pull/15464#issuecomment-247642772. $brick->data = ['text' => 'Another text']; $brick->save();
删除内容砖块
只需像删除任何其他 Eloquent 模型实例一样删除您的内容砖块
$brick->delete();
清除与 Eloquent 模型关联的所有内容砖块,或仅清除特定类型的砖块
$page->clearBricks(); $page->clearBricks([OneTextColumn::class]);
清除所有内容砖块,但保留特定的内容砖块
$page->clearBricksExcept($bricksCollection);
注意
- 根据Eloquent模型中定义的
砖块约束数量,这些方法可以将保留最小砖块数量,而不是删除目标砖块。
设置内容砖块顺序
默认情况下,所有砖块按其创建顺序排序(最后创建的排在末尾)。
Brick
模型使用spatie/eloquent-sortable
包来处理内容砖块的位置。
要了解如何使用此第三方包,请查看其文档:https://github.com/spatie/eloquent-sortable。
您可能会注意到,砖块顺序管理已经在提供的
管理面板中处理,并且您可以直接使用它。
检索内容砖块
检索与Eloquent模型关联的所有内容砖块,或仅检索具有特定砖块类型的内容砖块。
$bricks = $page->getBricks(); $bricks = $page->getBricks(OneTextColumn::class);
获取与Eloquent模型关联的第一个内容砖块,或具有特定砖块类型的内容砖块。
$brick = $page->getFirstBrick(); $brick = $page->getFirstBrick(OneTextColumn::class);
查询内容砖块
由于每个可砖块都可以指定自己的砖块模型,因此您应查询内容砖块,然后将它们转换为与它们相关的可砖块中定义的模型。
$rawBricks = Brick::where('model_type', Page::class)->where('model_id', 1)->where('brickable_type', OneTextColumn::class)->get(); $bricks = Brickables::castBricks($rawBricks);
显示内容砖块
在视图中显示单个内容砖块。
{{ $page->getFirstBrick(OneTextColumn::class) }}
或显示与Eloquent模型关联的所有内容砖块。
{!! $page->displayBricks() !!}
或仅显示给定砖块类型的内容砖块。
{!! $page->displayBricks([OneTextColumn::class, TwoTextColumns::class]) !!}
检索砖块
获取所有已注册的砖块。
$registeredBrickables = $page->getRegisteredBrickables();
获取所有允许添加到Eloquent模型的砖块。
$additionableBrickables = $page->getAdditionableBrickables();
从砖块实例检索砖块。
$brickable = $page->getFirstBrick(OneTextColumn::class)->brickable;
管理模型内容砖块
使用现成的管理面板来管理相关模型内容砖块。
{!! $page->displayAdminPanel() !!}
通过发布来自定义管理面板视图。
💡提示
- 强烈建议添加javascript确认请求以拦截内容砖块的删除操作,否则删除操作将直接执行而无需用户同意。
创建自己的砖块
在您的app/vendor/Brickables
目录中创建一个新的砖块类,该类扩展了类。
在您的砖块类中,您可以覆盖扩展的抽象Brickable
类中的任何方法来自定义砖块行为。
<?php namespace App\Vendor\LaravelBrickables\Brickables; use Okipa\LaravelBrickables\Abstracts\Brickable; class MyNewBrickable extends Brickable { public function validateStoreInputs(): array { return request()->validate(['text' => ['required', 'string']]); } public function validateUpdateInputs(): array { return request()->validate(['text' => ['required', 'string']]); } // Alternative example: use a form request to validate your inputs and return the validated fields. //public function validateStoreInputs(): array //{ // return app(MyNewBrickableStoreFormRequest::class)->validated(); //} }
然后,在config('brickables.registered')
数组中注册它。
<?php return [ 'registered' => [ // Other brickables declarations... App\Vendor\LaravelBrickables\Brickables\MyNewBrickable::class, ], ];
最后,在resources/views/vendor/laravel-brickables/my-new-brickable
目录中创建砖块视图(您可以在MyNewBrickable
类中自定义视图路径)
- 将在前端显示您的
MyNewBrickable
砖块的brick
视图。 - 将在管理面板中嵌入表单输入的
form
视图,用于CRUD您的MyNewBrickable
砖块。
您应该查看现有的砖块实现以熟悉其管理。
您的砖块现在已准备好与Eloquent模型关联。
定义砖块CSS和JS资源
您有定义CSS和JS资源以自定义每个砖块渲染的可能性。
此外,此包嵌入了一个智能资源管理系统:它确定哪些砖块实际上显示在页面上,并且只加载一次资源,即使砖块在页面上使用多次。
为了使用此功能,请确保您已按照安装部分中的说明实现了@brickablesCss
和@brickablesJs
指令。
然后,定义您的砖块使用哪些资源
<?php namespace App\Vendor\LaravelBrickables\Brickables; use Okipa\LaravelBrickables\Abstracts\Brickable; class MyNewBrickable extends Brickable { // ... protected function setCssResourcePath(): string|null { return mix('/css/brickables/my-new-brickable.css'); } protected function setJsResourcePath(): string|null { return mix('/js/brickables/my-new-brickable.js'); } }
最后,在页面最后显示的砖块下使用@brickableResourcesCompute
指令
{{-- page.blade.php --}} @extends('laravel-brickables::layout') @section('content') {{ $page->getFirstBrick(OneTextColumn::class) }} {{ $page->displayBricks([TwoTextColumns::class]) }} @brickableResourcesCompute @endsection
⚠️ 重要:请注意,您必须始终从声明brickablesCss
和@brickablesJs
指令的视图的子视图中声明@brickableResourcesCompute
指令。如您在示例中看到的那样,@brickableResourcesCompute
blade指令是在page.blade.php
视图中调用的,该视图是layout.blade.php
的子视图(其中声明了brickablesCss
和@brickablesJs
)。这是此包能够知道页面上实际显示哪些砖块、智能加载资源的唯一方法。
赋予砖块额外能力
要向您的砖块添加功能,您必须在砖块相关砖模型和砖控制器中实现额外的处理。
让我们从上一个示例中的MyNewBrickable
中添加图像管理能力。
首先创建一个MyNewBrickableBrick
模型,它将扩展Okipa\LaravelBrickables\Models\Brick
以赋予此砖块图像管理能力。
<?php namespace App; use Okipa\LaravelBrickables\Models\Brick; use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; class MyNewBrickableBrick extends Brick implements HasMedia { // Image management example with the spatie/laravel-medialibrary package. use InteractsWithMedia; // Optimize query by eager loading media relations. protected $with = ['media']; // ... }
然后,创建一个MyNewBrickableBricksController
模型,它将扩展Okipa\LaravelBrickables\Controllers\BricksController
,您将在其中添加图像管理处理。
<?php namespace App\Http\Controllers; use Okipa\LaravelBrickables\Controllers\BricksController; class MyNewBrickableBricksController extends BricksController { // ... protected function stored(Request $request, Brick $brick): void { // Image management example with the spatie/laravel-medialibrary package $brick->addMediaFromRequest('image')->toMediaCollection('bricks'); } protected function updated(Request $request, Brick $brick): void { // Image management example with the spatie/laravel-medialibrary package if ($request->file('image')) { $brick->addMediaFromRequest('image')->toMediaCollection('bricks'); } } // ... }
不要忘记验证您的表单输入
class MyNewBrickable extends Brickable { public function validateStoreInputs(): array { return request()->validate([ 'text' => ['required', 'string'], 'image' => ['required', 'mimetypes:image/jpeg,image/png', 'dimensions:min_width=240,min_height=160', 'max:5000'], ]); } public function validateUpdateInputs(): array { return request()->validate([ 'text' => ['required', 'string'], 'image' => ['nullable', 'mimetypes:image/jpeg,image/png', 'dimensions:min_width=240,min_height=160', 'max:5000'], ]); } }
最后,让您的砖块使用您的MyNewBrickableBrick
模型和MyNewBrickableBricksController
控制器
<?php namespace App\Vendor\LaravelBrickables\Brickables; use App\MyNewBrickableBrick; use App\Http\Controllers\MyNewBrickableBricksController; use Okipa\LaravelBrickables\Abstracts\Brickable; class MyNewBrickable extends Brickable { // ... protected function setBrickModelClass(): string { return MyNewBrickableBrick::class; } protected function setBricksControllerClass(): string { return MyNewBrickableBricksController::class; } // ... }
就是这样,您的自定义模型和控制器现在将被MyNewBrickable
砖块使用。
从请求中获取Eloquent模型
对于导航目的,检索Eloquent模型可能很有用。
此辅助程序将在砖块表单视图(砖块创建和编辑请求)中导航时返回相关模型。
// You can pass a custom request in the parameters. If none is given, the current request is used. $model = Brickables::getModelFromRequest();
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献。
安全
如果您发现任何与安全相关的问题,请通过电子邮件arthur.lorent@gmail.com联系,而不是使用问题跟踪器。
致谢
许可
MIT 许可证(MIT)。有关更多信息,请参阅许可文件。