Fluent Interface for Laravel Backpack - Define resources once and get all CRUD configurations ready!

Overview

CRUD Resource for Laravel Backpack

Latest Version on Packagist Total Downloads The Whole Fruit Manifesto

This package allows creating CRUD panels for Backpack for Laravel administration panel using fluent field definitions.

This is heavily inspired by Laravel Nova.

What does it offer?

  • Define Resources once, get all configurations ready for CRUD panels πŸš€
  • Get IDE hints - these are all PHP classes πŸ˜‰
  • Avoid long, nested, hard-to-remember array configurations πŸ₯±
  • Embrace the elegance of Object-Oriented API with Fluent Interface Pattern βš™οΈ

Installation

Via Composer

composer require figlabhq/crud-resource-for-backpack

Usage

  1. Create a new class defining the fields required for your model. Here is how it'd look for standard Laravel User model:

    <?php declare(strict_types=1);
    
    namespace App\CrudResources;
    
    use FigLab\CrudResource\CrudResource;
    use App\Models\User;
    use FigLab\CrudResource\Fields\Email;
    use FigLab\CrudResource\Fields\Password;
    use FigLab\CrudResource\Fields\Select;
    use FigLab\CrudResource\Fields\Text;
    
    class UserCrudResource extends CrudResource
    {
        public function fields(): array
        {
            return [
                Text::make('Name')
                    ->sortable(),
    
                Email::make('Email'),
    
                Password::make('Password')
                    ->size(6)
                    ->onlyOnForms(),
    
                Password::make('Confirm Password', 'password_confirmation')
                    ->size(6)
                    ->onlyOnForms(),
            ];
        }
    }
  2. In your Crud controller, call the relevant methods:

    <?php declare(strict_types=1);
    
    namespace App\Http\Controllers;
    
    use App\CrudResources\User\UserCrudResource;
    
    class UserCrudController extends CrudController
    {
        private UserCrudResource $crudResource;
    
        public function setup()
        {
            $this->crud->setModel(\App\Models\User::class);
            $this->crud->setRoute(config('backpack.base.route_prefix') . '/users');
            $this->crud->setEntityNameStrings('user', 'users');
    
            $this->crudResource = new UserCrudResource($this->crud);
        }
    
        protected function setupListOperation(): void
        {
            $this->crudResource->buildList();
        }
        
        protected function setupCreateOperation(): void
        {
            $this->crud->setValidation(UserStoreRequest::class);
    
            $this->crudResource->buildCreateForm();
        }
        
        protected function setupUpdateOperation(): void
        {
            $this->crud->setValidation(UserUpdateRequest::class);
    
            $this->crudResource->buildUpdateForm();
        }
    }
  3. Enjoy a fully-functional CRUD panel πŸŽ‰

    User Listing

    User Create/Update

Documentation

Coming soon...stay tuned πŸ˜…

Change log

Changes are documented here on Github. Please see the Releases tab.

Contributing

Please see contributing.md for a todolist and how-tos.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

This project was released under MIT, so you can install it on top of any Backpack & Laravel project. Please see the license file for more information.

However, please note that you do need Backpack installed, so you need to also abide by its YUMMY License. That means in production you'll need a Backpack license code. You can get a free one for non-commercial use (or a paid one for commercial use) on backpackforlaravel.com.

Comments
  • [Feature Request] How to use a custom field

    [Feature Request] How to use a custom field

    Feature Request

    What I am trying to achieve

    Any way to use a custom field, or a field provided by a third-party addon (eg toggle) using this resource syntax... but without having to create a class for it too?

    How I see it implemented

    Maybe a CustomField object, that would take in not only the field label/name, but also the type?

        CustomField::make('agreed')->type('toggle'),
    

    What I've already tried to fix it

    Nada πŸ‘€ Just spitballing here.

    Would I be able to work on this myself and submit a PR

    Sure.

    enhancement good first issue 
    opened by tabacitu 0
  • Add field-level and resource-level validation support

    Add field-level and resource-level validation support

    Related Issues

    Original Issue: #3

    Context and Purposes

    In order to further simplify the usage of a CrudResource, the validations rules for the fields should reside in the CrudResource itself and/or to the fields themselves.

    Challenges and Solutions

    Field-level Validation Rules

    In this update, we have added both the above support. Here's an example of using field level validation rules:

    public function fields(): array
    {
        $id = $this->crud->getRequest()->input('id') ?? $this->crud->getRequest()->route('id');
    
        return [
            Text::make('Name')
                ->rules('required', 'min:5', 'max:255')
                ->sortable(),
    
            Email::make('Email')
                ->rules('required')
                ->creationRules('unique:users,email')
                ->updateRules('unique:users,email,'.$id),
    
            Password::make('Password')
                ->size(6)
                ->rules(['confirmed', 'min:8'])
                ->onlyOnForms(),
    
            Password::make('Confirm Password', 'password_confirmation')
                ->size(6)
                ->creationRules('required')
                ->onlyOnForms(),
        ];
    }
    

    As shown in the example, there are three methods to use:

    • rules: adds the validation rule for both create and update forms
    • creationRules: adds the validation rule only for create form
    • updateRules: adds the validation rule only for update form

    Resource-level Validation Rules

    In addition to the field-level validation, the validation rules/messages can also be added to the CrudResource itself. Example:

    /** @inheritDoc */
    public function validationRules(): array
    {
        $id = $this->crud->getRequest()->get('id') ?? $this->crud->getRequest()->route('id');
    
        $rules = [
            'name' => 'required|min:5|max:255',
            'role' => 'required',
        ];
    
        $rules['email'] = $this->crud->getOperation() === 'create'
            ? 'required|unique:users,email'
            : 'required|unique:users,email,'.$id;
    
        $rules['password'] = $this->crud->getOperation() === 'create'
            ? 'required|confirmed'
            : 'confirmed';
    
        return $rules;
    }
    
    /** @inheritDoc */
    public function validationMessages(): array
    {
        return [
            'name.required' => 'You gotta give it a name, man.',
            'name.min' => 'You came up short. Try more than 2 characters.',
        ];
    }
    
    opened by phpfour 1
  • [Feature Request] Auto-call the correct build method, depending on the operation type

    [Feature Request] Auto-call the correct build method, depending on the operation type

    Feature Request

    What I am trying to achieve

    If/after #4 is implemented, this is how a BookCrudController could look like:

    <?php
    
    namespace App\Http\Controllers\Admin;
    
    use App\Http\Requests\BookRequest;
    use App\CrudResources\BookCrudResource;
    use Backpack\CRUD\app\Http\Controllers\CrudController;
    use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
    
    /**
     * Class BookCrudController
     * @package App\Http\Controllers\Admin
     * @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
     */
    class BookCrudController extends CrudController
    {
        use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
    
        private BookCrudResource $crudResource;
    
        /**
         * Configure the CrudPanel object. Apply settings to all operations.
         *
         * @return void
         */
        public function setup()
        {
            $this->crudResource = new BookCrudResource();
        }
    
        /**
         * Define what happens when the List operation is loaded.
         *
         * @see  https://backpackforlaravel.com/docs/crud-operation-list-entries
         * @return void
         */
        protected function setupListOperation()
        {
            $this->crudResource->buildList();
        }
    
        /**
         * Define what happens when the Create operation is loaded.
         *
         * @see https://backpackforlaravel.com/docs/crud-operation-create
         * @return void
         */
        protected function setupCreateOperation()
        {
            $this->crudResource->buildCreateForm();
        }
    
        /**
         * Define what happens when the Update operation is loaded.
         *
         * @see https://backpackforlaravel.com/docs/crud-operation-update
         * @return void
         */
        protected function setupUpdateOperation()
        {
            $this->crudResource->buildUpdateForm();
        }
    }
    

    What I see there is a lot of methods that don't really need to be there. At least not in the most common scenarios. So what if we make defining the setup methods optional too? What if the CrudController looked more like this:

    <?php
    
    namespace App\Http\Controllers\Admin;
    
    use App\Http\Requests\BookRequest;
    use App\CrudResources\BookCrudResource;
    use Backpack\CRUD\app\Http\Controllers\CrudController;
    use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
    
    /**
     * Class BookCrudController
     * @package App\Http\Controllers\Admin
     * @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
     */
    class BookCrudController extends CrudController
    {
        use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
    
        private BookCrudResource $crudResource;
    
        /**
         * Configure the CrudPanel object. Apply settings to all operations.
         *
         * @return void
         */
        public function setup()
        {
            $this->crudResource = new BookCrudResource();
            $this->crudResource->build(); // calls the correct builder for the current operation
        }
    }
    
    

    How I see it implemented

    See above.

    What I've already tried to fix it

    See above.

    Would I be able to work on this myself and submit a PR

    Sure, before the v6 launch when this is scheduled.

    opened by tabacitu 0
  • [Feature Request] Define the model, route and entity name strings inside the CrudResource, not the CrudController

    [Feature Request] Define the model, route and entity name strings inside the CrudResource, not the CrudController

    Feature Request

    What I am trying to achieve

    What if we could define EVERYTHING we need to define for a CRUD, inside the CrudResource? If you prefer to define a CrudResource, I don't really see a reason why you would split your definition across multiple files:

    • the CrudController
    • the CrudResource
    • the CrudRequest (see #3 )

    So what if... if you're using CrudRequest... the CrudController is kind of optional? Only there in case you need to do custom stuff, add things to the setup of a particular operation or override how an operation does its thing?

    How I see it implemented

    To achieve that, we need to move this from the CrudController:

    // BookCrudController.php
    
        public function setup()
        {
    -        CRUD::setModel(\App\Models\Book::class);
    -        CRUD::setRoute(config('backpack.base.route_prefix') . '/book');
    -        CRUD::setEntityNameStrings('book', 'books');
    -
            $this->crudResource = new BookCrudResource();
        }
    

    to the CrudResource:

    // BookCrudResource.php
    
    
    class BookCrudResource extends CrudResource
    {
        protected $model = \App\Models\Book::class;
        protected $route = config('backpack.base.route_prefix') . '/book';
        protected $entityNameSingular = 'book';
        protected $entityNamePlural = 'books';
    
        public function fields(): array
        {
            return [
                Text::make('Name')->size(9),
                Number::make('Year')->size(3),
                Textarea::make('Description')->onlyOnForms(),
                Text::make('ISBN'),
            ];
        }
    }
    

    But since some of the above will probably not work (see - calling the config πŸ˜…), we'll also need setters/getters for the above, so maybe:

    // BookCrudResource.php
    
    class BookCrudResource extends CrudResource
    {
        protected $model = 'App\Models\Book'; // mandatory
        protected $entityNameSingular = 'book'; // optional, can figure it out from the model name too
        protected $entityNamePlural = 'books'; // optional, can figure it out from the singular too
    
        // optional
        public function model() 
        {
            return \App\Models\Book::class;
        }
    
        // optional, would default to using the entity name as URL segment
        public function route() 
        {
            return config('backpack.base.route_prefix') . '/book';
        }
    
        // optional
        public function entityNameSingular() 
        {
            return 'book';
        }
    
        // optional
        public function entityNamePlural() 
        {
            return 'books';
        }
    
        public function fields(): array
        {
            return [
                Text::make('Name')->size(9),
                Number::make('Year')->size(3),
                Textarea::make('Description')->onlyOnForms(),
                Text::make('ISBN'),
            ];
        }
    }
    

    What I've already tried to fix it

    Nothing, just spitballing.

    Would I be able to work on this myself and submit a PR

    Sure, before we launch v6.

    opened by tabacitu 0
  • [Feature Request] Validation rules and messages inside CrudResource

    [Feature Request] Validation rules and messages inside CrudResource

    Feature Request

    What I am trying to achieve

    It feels a bit odd to me to define the validation rules in a different file, when everything else is defined in the CrudResource.

    How I see it implemented

    Starting with Backpack v5, we have three ways of adding validation rules, one way being directly on the fields. I see THAT as being the most useful if you're defining a CrudRequest. But I'd also expect to be able to define validationRules() and validationMessages() on the CrudResource... maybe... I don't know...

    The end result, to me, could look something like:

    
    class BookCrudResource extends CrudResource
    {
        public function fields(): array
        {
            return [
                Text::make('Name')->size(9)->validationRules('required'), // should already work, I think
                Number::make('Year')->size(3)->required(), // alias, todo maybe
                Textarea::make('Description')->onlyOnForms(),
                Text::make('ISBN'),
            ];
        }
    }
    

    or like this:

    
    class BookCrudResource extends CrudResource
    {
        public function fields(): array
        {
            return [
                Text::make('Name')->size(9)->validationRules('required'), // should already work, I think
                Number::make('Year')->size(3)->required(), // alias, todo maybe
                Textarea::make('Description')->onlyOnForms(),
                Text::make('ISBN'),
            ];
        }
    
        public function validationRules(): array
        {
            // devs could test the operation here, and do stuff depending on the operation name
            // eg: if ($this->crud->operation == 'update') { change_a_rule(); }
    
            return [
                'isbn' => 'required|string|unique:books,isbn',
                'name' => 'required|string',
                'description' => 'nullable|string',
                'year' => 'required|integer',
            ];
        }
    
        // public function validationMessages(): array { return []; }
    }
    

    This should clean up the CrudController a bit, so that... ideally, you don't have to do ANYTHING inside the setupXxxOperation() method (more on that in a separate issue).

    <?php
    
    namespace App\Http\Controllers\Admin;
    
    use App\Http\Requests\BookRequest;
    use App\CrudResources\BookCrudResource;
    use Backpack\CRUD\app\Http\Controllers\CrudController;
    use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
    
    /**
     * Class BookCrudController
     * @package App\Http\Controllers\Admin
     * @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
     */
    class BookCrudController extends CrudController
    {
        use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
    
        private BookCrudResource $crudResource;
    
        /**
         * Configure the CrudPanel object. Apply settings to all operations.
         *
         * @return void
         */
        public function setup()
        {
            CRUD::setModel(\App\Models\Book::class);
            CRUD::setRoute(config('backpack.base.route_prefix') . '/book');
            CRUD::setEntityNameStrings('book', 'books');
    
            $this->crudResource = new BookCrudResource($this->crud);
        }
    
        /**
         * Define what happens when the List operation is loaded.
         *
         * @see  https://backpackforlaravel.com/docs/crud-operation-list-entries
         * @return void
         */
        protected function setupListOperation()
        {
            $this->crudResource->buildList();
        }
    
        /**
         * Define what happens when the Create operation is loaded.
         *
         * @see https://backpackforlaravel.com/docs/crud-operation-create
         * @return void
         */
        protected function setupCreateOperation()
        {
    -        CRUD::setValidation(BookRequest::class);
    -
            $this->crudResource->buildCreateForm();
        }
    
        /**
         * Define what happens when the Update operation is loaded.
         *
         * @see https://backpackforlaravel.com/docs/crud-operation-update
         * @return void
         */
        protected function setupUpdateOperation()
        {
    -        CRUD::setValidation(BookRequest::class);
    -
            $this->crudResource->buildUpdateForm();
        }
    }
    
    
    enhancement 
    opened by tabacitu 0
  • [Potential Future Issue] Not all field types have a corresponding column type

    [Potential Future Issue] Not all field types have a corresponding column type

    I noticed this add-on is using fields to also define columns inside the ListOperation. This is probably inspired by Nova, for someone coming from there it should be pretty intuitive, but we should keep in mind that in Backpack fields and columns are separate things, and:

    • there might be inconsistencies in the definition, between a field and a column with the same name;
    • there will definitely be fields without a corresponding field type;

    I don't think this is something that package can fix... it's the inconsistency in Backpack that's the problem. But it's something we should be aware of, test and know.

    Let me make this clear, though: we do plan to fix this in Backpack: every inconsistency we can fix in a non-breaking way, we'll do in 5.x, everything else in v6. So... by Backpack v6, this should be a non-issue, we'll have fields and columns perfectly aligned. I'd love for @phpfour to be the one that tracks down and solves these inconsistencies. But there's quite a bit of work to be done there, see https://github.com/Laravel-Backpack/ideas/issues/196 for details.

    opened by tabacitu 0
Releases(1.0.6)
Owner
FigLab
We build software for the Muslim Ummah
FigLab
Backpack v3 used this Base package to offer admin authentication and a blank admin panel using AdminLTE

Until 2018, Backpack v3 used this Base package to offer admin authentication and a blank admin panel using AdminLTE. Backpack v4 no longer uses this package, they're now built-in - use Backpack/CRUD instead.

Backpack for Laravel 845 Nov 29, 2022
A script to help setup Laravel project with common packages and configurations

About Snap Snap allow developer to create scaffold Laravel project. Installation Clone this repository in your user home directory. cd ~ git clone htt

Nasrul Hazim Bin Mohamad 3 Jan 4, 2022
Registry manager for Laravel 5. An alternative for managing application configurations and settings.

Registry manager for Laravel 5. An alternative for managing application configurations and settings. Now with the magic of caching, so no more database calls to simply get site setting.

Daniel Stainback 22 Sep 28, 2020
Laravel CRUD Generator This Generator package provides various generators like CRUD, API, Controller, Model, Migration, View for your painless development of your applications.

Laravel CRUD Generator This Generator package provides various generators like CRUD, API, Controller, Model, Migration, View for your painless develop

AppzCoder 1.3k Jan 2, 2023
Laravel 8 boilerplate in docker-compose with Treafik and SSL setup and github workflow ready for CI/CD pipeline

Laravel8 boilerplate Laravel 8 boilerplate in docker-compose with Treafik and SSL setup with .github workflow ready To start the containers in prod en

Tej Dahal 5 Jul 9, 2022
Automatically Create professional ready to use Laravel REST API for MySQL Database With Postman Docs and JWT Authentication

Laravel Simple Rest API Generator An API Boilerplate to create a ready-to-use REST API in seconds with Laravel 8.x Install with Composer $ curl -s

null 5 Mar 12, 2022
A Laravel 5.8 API Boilerplate to create a ready-to-use REST API in seconds.

Laravel API Boilerplate (JWT Edition) for Laravel 5.8 Laravel API Boilerplate is a "starter kit" you can use to build your first API in seconds. As yo

Francesco Malatesta 1.2k Dec 18, 2022
Production Ready, Carefully Crafted, Extensive Vuejs Laravel Free Admin Template 🀩

Materio - Vuetify VueJS Laravel Free Admin Template Production ready carefully crafted most comprehensive admin template Introduction If you’re a deve

ThemeSelection 115 Dec 13, 2022
LaraAdmin is a Open source Laravel Admin Panel / CMS which can be used as Admin Backend, Data Management Tool or CRM boilerplate for Laravel with features like Advanced CRUD Generation, Module Manager, Backups and many more.

LaraAdmin 1.0 LaraAdmin is a Open source CRM for quick-start Admin based applications with features like Advanced CRUD Generation, Schema Manager and

Dwij IT Solutions 1.5k Dec 29, 2022
Get started with Laravel 5.3 and AngularJS (material)

Laravel 5.3 Angular Material Starter Demo An online demo is available. Angular (2+) update While this starter used to be an excellent starting point f

Jad Joubran 1.7k Dec 14, 2022
:elephant: A Laravel 6 SPA boilerplate with a users CRUD using Vue.js 2.6, GraphQL, Bootstrap 4, TypeScript, Sass, and Pug.

Laravel Vue Boilerplate A Laravel 6 Single Page Application boilerplate using Vue.js 2.6, GraphQL, Bootstrap 4, TypeScript, Sass and Pug with: A users

Alefe Souza 533 Jan 3, 2023
Laravel and Vue js CRUD

Laravel and Vue js PhoneBook app In this project I have done a simple CRUD using Laravel and Vue Js. Here I have used : Vue router Sweetalert2 Resourc

AR Shahin 4 Jun 11, 2022
Basic Crud Generator (With Code Files, like GII (YII2)) Using Laravel, Livewire and Tailwind CSS

LiveCrud Live Crud Generator. This package generates Basic Crud with Livewire. Features Generate Complete Crud With Livewire Component and Blade Files

Ritesh Singh 28 Oct 12, 2022
Dockerized Laravel project with authentication and car brand crud functionalities.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Legendary 4 Oct 16, 2021
Laravel CRUD Generator, Make a Web Application Just In Minutes, Even With Less Code and fewer Steps !

?? CRUDBOOSTER - Laravel CRUD Generator Laravel CRUD Generator, Make a Web Application Just In Minutes, Even With Less Code and fewer Steps ! About CR

Crocodic Studio 1.7k Jan 8, 2023
A CRUD app made with Laravel and VueJS 3 (API Composition)

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Ludovic GuΓ©net 2 Apr 1, 2022
Building Student Management CRUD with LARAVEL VUE and INERTIA

Building Student Management CRUD with LARAVEL VUE and INERTIA. the amazing thing about I got by combining these technologies is we ca build single page application or SPA .

Tauseed 3 Apr 4, 2022
A simple CRUD built in PHP, Bootstrap and MySQL

✨ Notes-CRUD ✨ A simple CRUD built in PHP, Bootstrap and MySQL ?? Table of Contents Usage Contribute Screenshots ?? Usage Add the project to your envi

Bonnie Fave 7 Dec 7, 2022
Create Migration, Seed, Request, Controller, Model and Views for your resource (CRUD)

Table of Contents Laravel Resourceful NOTE! Usage Install through composer Add Service Provider Run it! Example Generated Controller Generated Views I

Remo 62 Aug 15, 2021