thinhnx / laravel-page-builder
Library for creating blocks on Laravel pages
Requires
- php: ^8.1
- astrotomic/laravel-translatable: ^11.16
- kalnoy/nestedset: ^6.0
- laravel/framework: ^v10|^v11|^v12
Requires (Dev)
- jaschilz/php-coverage-badger: ^2.0
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^10.5
- squizlabs/php_codesniffer: ^3.11
This package is auto-updated.
Last update: 2025-05-24 03:41:32 UTC
README
A simple Laravel package for creating blocks using drag and drop.
DEMO
Requirements
- PHP >= 8.1
- Laravel >= 10.0
Installation
1. Installation via Composer:
composer require thinhnx/laravel-page-builder
2. Running install command:
php artisan page-builder:install
Console will confirm you to run migration and run seeder, please type yes
and press enter.
Configuration
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', ], ], ];
Usage
1. Applying to a model
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); }
2. Creating a new block
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.
3. Views
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
4. Assets
The package assets are located at public/packages/thinhnx/page-builder
.
You can update them to suit your project.
Testing
composer test
Contributing
- 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.
License
This package is open-sourced software licensed under the MIT license.
Support
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.