This package extends Backpack/CRUD. See all features added bellow.
To do this without any modification on your controller or others package, this package:
- is able to override all Backpack/CRUD views;
- extends CrudPanel class.
In your terminal:
composer require novius/laravel-backpack-crud-extended
Then, if you are on Laravel 5.4 (no need for Laravel 5.5 and higher), register the service provider to your config/app.php
file:
'providers' => [
...
Novius\Backpack\CRUD\CrudServiceProvider::class,
];
If you have already published backpack-crud views, this package will not work.
You have to remove views into resources/views/vendor/backpack/crud/
, or to override them with:
php artisan vendor:publish --provider="Novius\Backpack\CRUD\CrudServiceProvider" --force
Some options that you can override are available.
php artisan vendor:publish --provider="Novius\Backpack\CRUD\CrudServiceProvider" --tag="config"
- Permissions can be applied automatically to CRUD Controllers : deny access if user hasn't the permission linked to the route =>
apply_permissions
option - Permissions can be automatically created for all Crud Controllers used in you application (4 permissions will be created : list, update, create, delete) =>
create_permissions_while_browsing
option - Permissions can be automatically given to the logged user (useful in local environment) =>
give_permissions_to_current_user_while_browsing
option
- This feature require : Laravel-Backpack/PermissionManager
- You have to publish config file :
php artisan permissions:generate // Insert permissions in database for each CRUD controllers.
- Set to true each options that you want activate
Your CrudController must extend \Novius\Backpack\CRUD\Http\Controllers\CrudController
You can now split your create/edit inputs into multiple boxes.
In order to use this feature, you just need to specify the box name for each of your fields.
$this->crud->addField([
'name' => 'title',
'label' => "My Title",
'type' => 'text',
'box' => 'Box name here'
]);
You can also specify some options to each box:
$this->crud->setBoxOptions('Details', [
'side' => true, // Place this box on the right side?
'class' => "box-info", // CSS class to add to the div. Eg, <div class="box box-info">
'collapsed' => true, // Collapse this box by default?
]);
If you forget to specify a tab name for a field, Backpack will place it in the last box.
You can specify manually a default box in the crud file. If your field doesn't have the box attribute, this field will be displayed in this default box.
$this->crud->setDefaultBox('YourBoxName');
Fields type can now be a classname:
$this->crud->addField([
'name' => 'username',
'label' => "My username",
'type' => \My\Other\Package\Field\Foo::class,
]);
This allows you to propose new field types in external packages. Your Field class must implement Field Contract.
Set a custom dictionary for a specific crud:
$this->crud->setLangFile('backpack::crud/movie');
This dictionary will then be used in the CRUD views.
You can use it in your own views like this:
{{ trans($crud->getLangFile().'.add') }}
If you use Upload CRUD Field, you can implement this Trait on your Model to automatically upload / delete file(s) on server.
Example:
// Article Model
class Article extends \Backpack\NewsCRUD\app\Models\Article
{
use Sluggable, SluggableScopeHelpers;
use HasTranslations;
use UploadableFile;
protected $fillable = ['slug', 'title', 'content', 'image', 'status', 'category_id', 'featured', 'date', 'document', 'document_2'];
protected $translatable = ['slug', 'title', 'content'];
public function uploadableFiles(): array
{
return [
['name' => 'document'],
['name' => 'document_2', 'slug' => 'title']
];
}
}
// ArticleCrudController
$this->crud->addField([
'label' => 'Image',
'name' => 'image',
'type' => 'image',
'upload' => true,
'crop' => true, // set to true to allow cropping, false to disable
'aspect_ratio' => 0, // ommit or set to 0 to allow any aspect ratio
'prefix' => '/storage/',
]);
$this->crud->addField([
'label' => 'Document',
'name' => 'document',
'type' => 'upload',
'upload' => true,
'prefix' => '/storage/',
]);
$this->crud->addField([
'label' => 'Document 2',
'name' => 'document_2',
'type' => 'upload',
'upload' => true,
'prefix' => '/storage/',
]);
A validation rule exists to easily validate CRUD request with "upload" field.
Example of usage in your requests files:
public function rules()
{
return [
'name' => 'required|min:2|max:191',
'document' => 'file_upload_crud:pdf,docx', // the parameters must be valid mime types
];
}
public function messages()
{
return [
'file_upload_crud' => 'The :attribute must be a valid file.',
];
}
If you use the Image CRUD Field, you can implement this trait on your model to automatically manage saving and deleting the image on the server.
Example:
namespace App\Models;
use Backpack\CRUD\CrudTrait;
use Illuminate\Database\Eloquent\Model;
use Novius\Backpack\CRUD\ModelTraits\UploadableImage;
class Example extends Model
{
use CrudTrait;
use UploadableImage;
protected $fillable = ['title', 'image', 'thumbnail'];
public function uploadableImages()
{
return [
[
'name' => 'image', // The attribute name where to store the image path
'slug' => 'title', // The attribute name from which to generate the image file name (optionnal)
],
[
'name' => 'thumbnail',
],
];
}
}
If you want to perform some custom actions on your image after saving or deleting it :
namespace App\Models;
use Backpack\CRUD\CrudTrait;
use Illuminate\Database\Eloquent\Model;
use Novius\Backpack\CRUD\ModelTraits\UploadableImage;
class Example extends Model
{
use CrudTrait;
use UploadableImage {
imagePathSaved as imagePathSavedNative;
imagePathDeleted as imagePathDeletedNative;
}
protected $fillable = ['title', 'image', 'thumbnail'];
public function uploadableImages()
{
return [
[
'name' => 'image', // The attribute name where to store the image path
'slug' => 'title', // The attribute name from which to generate the image file name (optionnal)
],
[
'name' => 'thumbnail',
],
];
}
/**
* Callback triggered after image saved on disk
*/
public function imagePathSaved(string $imagePath, string $imageAttributeName = null, string $diskName = null)
{
if (!$this->imagePathSavedNative()) {
return false;
}
// Do what you want here
return true;
}
/**
* Callback triggered after image deleted on disk
*/
public function imagePathDeleted(string $imagePath, string $imageAttributeName = null, string $diskName = null)
{
if (!$this->imagePathDeletedNative()) {
return false;
}
// Do what you want here
return true;
}
}
If you want to store the images in the MediaLibrary provided by Spatie, use the trait SpatieMediaLibrary\UploadableImage
instead of UploadableImage
.
For example with the MediaLibrary you can easily manage conversions (crop, resize, ...).
Both traits UploadableImage
and SpatieMediaLibrary\UploadableImage
are compatible with the translation package provided by Spatie.
In the case of translatable images with SpatieMediaLibrary\UploadableImage
, the name of the collection where the image is stored is composed of the name of the attribute and the locale, separated by a dash (eg. image-en
, image-fr
, ...).
You can set a custom value to some routes.
- Index route : used with "back to all" button or breadcrumb's link. Available with
$crud->indexRoute()
. - Reorder route : used with "Reorder button". Available with
$crud->reorderRoute()
.
Example of usage in your CrudController :
// Set a custom index route
$this->crud->setIndexRoute('crud.slide.index', ['slideshow' => (int) request('slideshow')]);
// Set a custom reorder route
$this->crud->setReorderRoute('crud.slide.reorder', ['slideshow' => (int) request('slideshow')]);
Run the tests with:
./test.sh
Run php-cs with:
./cs.sh
Contributions are welcome! Leave an issue on Github, or create a Pull Request.
This package is under GNU Affero General Public License v3 or (at your option) any later version.
However, this package requires Backpack\CRUD, which is under YUMMY license: if you use it in a commercial project, you have to buy a backpack license.