okipa/laravel-brickables

此包已被废弃且不再维护。未建议替代包。

简化页面内容砖块管理。

3.2.0 2023-01-23 08:41 UTC

This package is auto-updated.

Last update: 2023-11-16 11:48:03 UTC


README

此包已被废弃,如果您仍需要使用,请谨慎使用。
如果您感兴趣,请fork此包并赋予它新的生命!

Laravel Brickables

Latest Stable Version Total Downloads Build Status Coverage Status License: MIT

此包允许您将内容砖块关联到Eloquent模型,并提供一个可完全自定义的管理面板来管理它们。

此包附带了一些预构建的砖块。您可以直接使用它们,但您绝对应该将它们视为示例:自定义它们或创建新的它们已被设计得尽可能简单!🔥

觉得这个包有帮助?请考虑支持我的工作!

Donate Donate

兼容性

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)。有关更多信息,请参阅许可文件