A simple Laravel package for creating blocks using drag and drop.
- PHP >= 8.1
- Laravel >= 10.0
composer require thinhnx/laravel-page-builder
php artisan page-builder:install
Console will confirm you to run migration and run seeder, please type yes
and press enter.
The configuration file is located at config/page-builder.php
.
<?php
return [
// default locale when you have one locale
'default_locale' => 'en',
// All supported locales
'locales' => [
'en',
'vi',
],
// Route config
'route' => [
'prefix' => 'page-builder',
'as' => 'page-builder.',
'middleware' => ['web'],
],
// Name for tables
'tables' => [
'block' => 'pagebuilder_blocks',
'block_translation' => 'pagebuilder_block_translations',
'blockable' => 'pagebuilder_blockables',
],
// The models are used in the package; you can use your own models, as long as they inherit the models below
'models' => [
'block' => \Thinhnx\LaravelPageBuilder\Models\Block::class,
'block_translation' => \Thinhnx\LaravelPageBuilder\Models\BlockTranslation::class,
'blockable' => \Thinhnx\LaravelPageBuilder\Models\Blockable::class,
],
// Cache config
'cache' => [
'enabled' => true,
'time' => 60 * 60 * 24,
'keys' => [
'blocks' => 'pagebuilder_blocks',
],
],
];
Example for a model. You need use HasBlocks
trait in the model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Thinhnx\LaravelPageBuilder\Models\Traits\HasBlocks;
class Page extends Model
{
use HasBlocks;
protected $fillable = ['name'];
protected function setFormatItem(array &$data, Model $block): void
{
$data['content'] = $block->type === 'text' ? e($data['content']) : $data['content'];
}
public function getFormatItem(array|Model $data, Model $block): array|Model
{
$data['content'] = $block->type === 'text' ? htmlspecialchars_decode($data['content']) : $data['content'];
return $data;
}
}
In the Page model above, I override two functions: setFormatItem()
and getFormatItem()
. The purpose is to escape when saving and retrieving data of blocks. You can rewrite these 2 functions depending on your purpose.
On the create/edit Page screen, you use Facade function PageBuilder::render()
to render the block editor view.
Below is an example of the create page screen:
@extends('layouts.app')
@section('content')
<form action="/pages/create" method="post">
@csrf
<div class="mb-3">
<label class="form-label" for="name">Name<label>
<input class="form-control" name="name" required />
</div>
<div>
{{ PageBuilder::render() }}
</div>
</form>
@endsection
Below is an example of the edit page screen:
@extends('layouts.app')
@section('content')
<form action="/pages/{{ $page->id }}" method="post">
@csrf
@method('PUT')
<div class="mb-3">
<label class="form-label" for="name">Name<label>
<input class="form-control" name="name" required />
</div>
<div>
{{ PageBuilder::render($page) }}
</div>
</form>
@endsection
Data of blocks data will be contained in the hidden inputs tag named prefix blocks
.
You use the syncBlockItems()
function to synchronize new block items and the existing block items of the model according to locale.
Example:
<?php
$data = json_decode($request->get('blocks'), true);
// For default locale
$page->syncBlockItems($data[config('page-builder.default_locale')]);
// For multiple locales
foreach (config('page-builder.locales') as $locale) {
$page->syncBlockItems($data[$locale], $locale);
}
By default, I have created three blocks:
- Text
- Two Columns
- There Columns
Each block will have its own view file. You can change them in the path resources/views/vendor/page-builder/blocks
.
Create a new block with the following command:
php artisan page-builder:block:create
The console screen will ask you to enter the locale name, type and specify if it is a layout type (a layout type can contain blocks).
After running the command, a block view will be created at the path resources/views/vendor/page-builder/blocks/[type].blade.php
.
When updating a block view, you need to note:
- There must be only one root div tag and it must have the class
block-content
. - For block where
is_layout
isfalse
, you must add the classblock-content
to the tag containing the block's content (example: input, textarea, ...). - For block where
is_layout
istrue
, you must add the classsortable-column
and the attributedata-column="0,1,2,.."
to the tag you want to be a column.
See files: text.blade.php
, layout-2.blade.php
, layout-3.blade.php
at path resources/views/vendor/page-builder/blocks
for more details.
Views used in this package are located at resources/views/vendor/page-builder
. You can update them to suit your project.
Below is the structure of the view files:
π blocks // block views folder
|- π layout-2.blade.php // Two Columns block view
|- π layout-3.blade.php // Three Columns block view
|- π text.blade.php // Text block view
π paritals
|- π block.blade.php // block view used in preview for recursive
|- π modal-preview.blade.php // preview modal view
π page-builder.blade.php // blocks editor view
π preview.blade.php // preview iframe view used in preview modal
The package assets are located at public/packages/thinhnx/page-builder
.
You can update them to suit your project.
composer test
- Fork the repository.
- Create a new branch (git checkout -b feature-branch).
- Commit your changes (git commit -m 'Add new feature').
- Push to the branch (git push origin feature-branch).
- Create a Pull Request.
This package is open-sourced software licensed under the MIT license.
If you have any issues, please open an issue on GitHub.
Love using this package? Consider buying me a coffee to support ongoing development! Every little bit helps keep this project alive.