rtmatt / abstractresource
Abstract Resource Manager for Laravel
Requires
- php: >=5.3.0
- illuminate/support: ~5.1
- intervention/image: ^2.3
- laravelcollective/html: ^5.1
Requires (Dev)
- phpunit/phpunit: 4.*
- scrutinizer/ocular: ~1.1
README
Abstract Resource Management in Laravel.
Speed up basic CRUD functionality by configuring resources, rather than repeating the same code over and over and over...
This package currently generates a horizontal form with Bootstrap 3 markup.
Prerequisites
In an ideal world, this would be a fully self-contained package. This isn't an ideal world.
Laravel
You will need an existing install of laravel 5.1. You'll need a database set up and hooked into the application.
Admin Layout
You will need a file in /resources/views/layouts
called admin.blade.php
At the very least, this file will need a @yield('content)
in it.
Install
Via Composer
$ composer require rtmatt/abstractresource
Add to service provider list in config/app.php
RTMatt\AbstractResource\AbstractResourceServiceProvider::class,
This package has a couple dependencies you will need to register with you app if they haven't been already. In your file's config/app.php
file, make sure the following is under your 'providers' list:
'Intervention\Image\ImageServiceProvider', 'Collective\Html\HtmlServiceProvider',
In the same file, the following needs to be in your 'aliases' list:
'Form' => 'Collective\Html\FormFacade', 'Image' => 'Intervention\Image\Facades\Image',
For file uploads to work, you will need a folder uploads
inside your public
directory that is writable by the web server.
If you don't already have one, create a folder Admin
in app/Http/Controllers
Usage
Create Model and Migration
$ php artisan make:model [ResourceName] -m
Within the migration file, define your schema. Make sure to define all nullable inputs. Inputs with no values will be set to null on the back end. Run the migration when you're done.
Make Resource Controller
When you make your controller, make sure its name is your Resource Name (pluralized and StudlyCased) + 'Controller'
$ php artisan make:controller Admin/[ResourceNames]Controller --plain
The contents should reflect the following:
<?php namespace App\Http\Controllers\Admin; use App\Http\Requests; use RTMatt\AbstractResource\AbstractResourceController; class [ResourceNames]Controller extends AbstractResourceController { protected $model = '\App\[ResourceName]'; }
It's important the controller is named just the same as your resource, only pluralized and that it lives in the Admin
subdirectory of the controllers directory.
It should extend from RTMatt\AbstractResource\AbstractResourceController
and have a namespace of App\Http\Controllers\Admin
.
This is all you need for default functionality.
Create Route
Within your routes.php
file:
Route::resource('/admin/[resource-names]','Admin\[ResourceNames]Controller');
The URI needs to be a subroute of /admin
. The route needs to be a resource route.
Define Model
Define your model as normal. Add your fillable array and any accessors or mutators you will need.
Add the following method:
public static function getResourceControllerConfigs() { return [ 'resourceName' => 'resource-names', 'creatable' => true, 'deletable' => true, 'indexFields' => [ 'field_1', 'field_2' ], 'editableFields' => [ // ... ] ]; }
This method is where the power lies. We'll discuss it later. Just kidding. We'll discuss it NOW.
Configure Model
Configure your model by changing the array returned by the getResourceControllerConfigs
method.
[ 'resourceName' => 'resource-names', //this is the lower-case, hyphenated resource name 'creatable' => true, //whether the resource should be creatable in the admin 'deletable' => true, //whether the resource should be deletable in the admin 'indexFields' => [ 'field__name_1', 'field_name_2' ], //fields to display on the index view of the resource manager 'editableFields' => [ // all the fields that appear on the create and edit forms 'field_name' => 'field_type' // field definition. make sure each field is fillable ] ]
On the generated form, labels will automatically be generated from field names by replacing underscores with spaces and capitalizing the result. Additionally, if the field name ends in "_id," it will be removed.
'hide_flag' => "Hide Flag:", 'property_type_id' => "Property Type:"
Standard Options for field_type
'field_name' => 'text', // <input type="text" name="field_name"> 'field_name' => 'tel', // <input type="tel" name="field_name"> 'field_name' => 'email', // <input type="email" name="field_name"> 'field_name' => 'textarea', // <textarea name="field_name"></textarea> 'field_name' => 'image', // <input type="file" name="field_name"> - configured for image uploads 'field_name' => 'file', // <input type="file" name="field_name"> - configured for file uploads 'field_name' => 'checkbox', // single checkbox
Array-based field_type options
Some field types are more complex and defined as arrays :
'field_name' => [ // Array Field Type 'type' => 'radioGroup', //creates a radio group 'options' => [ //options are defined as value:key pairs 'value_1' => 'Display Text for value_1', 'value_2' => 'Display Text for value_2', ] ], 'field_name' => [ // Array Field Type 'type' => 'select', //creates a select input 'options' => [ //options are defined as value:key pairs 'value_1' => 'Display Text for value_1', 'value_2' => 'Display Text for value_2', ] ], 'field_name' => [ // Array Field Type 'type' => 'checkGroup', //creates a checkbox group 'options' => [ //options are defined as value:key pairs 'value_1' => 'Display Text for value_1', 'value_2' => 'Display Text for value_2', ] ],
Note: checkgroup field types require you create accessors and mutators on your model to json_encode the field when storing values and json_decode the field when retrieving them.
Special field_type Options
WYSIWIG
'field_name' => 'wysi', //creates a wysi input. requires additional scripts
This simply creates a textarea input and adds a class of "wysi" to it. You can attach any wysiwig plugin you like to this class.
Date/Datetime
'field_name' => 'date', //creates an input primed for a datepicker. requires additional scripts 'field_name' => 'datetime', //creates an input primed for a datepicker. requires additional scripts
The above create inputs of type="text" with the classes "date-picker" and "date-time-picker" respectively. You can use these classes to attach any date/datetime picker plugins you wish.
#####Image with Size Variants This is for images that require automatic saving of various sizes (standard - 320x240, thumbnail - 32x24,etc)
'field_name' => 'varied_image', //creates a image input field
For the system to create the image variants, you need to add a new index to the array returned by getResourceControllerConfigs()
:
'field_name_versions' => [ // make sure `field_name` corresponds to the name you used to create the input 'name_columns' => [ 'name_field' ], // field used to generate file names. this must be a field from the model 'versions' => // different varients of image to create. It's important these are in order of descending size [ 'field_name' => [ height, width ], // arrays are integers 'field_name_2' => [ height, width ], //... ] ]
If you would like to see all size variants of the image after it has been saved, add the following to you site's .env file:
DEMO=true
Complete Model Configuration Example
<?php namespace App; use Illuminate\Database\Eloquent\Model; class ResourceName extends Model { protected $fillable = [ 'name', 'phone_number', 'email_address', 'biography', 'hide_flag', 'featured_image', 'resume_file', 'color', 'affiliation', 'skills', 'custom_content', 'birthday', 'hide_until', 'profile_picture', 'profile_picture_2x', 'profile_picture_tile', 'profile_picture_tile_2x', ]; public static function getResourceControllerConfigs() { return [ 'resourceName' => 'resource-names', 'creatable' => true, 'deletable' => true, 'indexFields' => [ 'name', 'phone_number', 'email_address' ], 'editableFields' => [ 'name' => 'text', 'phone_number' => 'tel', 'email_address' => 'email', 'biography' => 'textarea', 'hide_flag' => 'checkbox', 'featured_image' => 'image', 'resume_file' => 'file', 'color' => [ 'type' => 'radioGroup', 'options' => [ 'red' => 'Favorite Color - Red', 'blue' => 'Favorite Color - Blue', ] ], 'affiliation' => [ 'type' => 'select', 'options' => [ 'rep' => 'Republican', 'dem' => 'Democrat', 'ind' => 'Independent', 'oth' => 'Other', ] ], 'skills' => [ 'type' => 'checkGroup', 'options' => [ 'typing' => 'Typing', 'reading' => 'Readiing', 'knitting' => 'Knitting' ] ], 'custom_content' => 'wysi', 'birthday' => 'date', 'hide_until' => 'datetime', 'profile_picture' => 'varied_image', ], 'profile_picture_versions' => [ 'name_columns' => [ 'name' ], 'versions' => [ 'profile_picture_tile_2x' => [ 80, 80 ], 'profile_picture_2x' => [ 60, 60 ], 'profile_picture_tile' => [ 40, 40 ], 'profile_picture' => [ 30, 30 ], ] ] ]; } public function setSkillsAttribute($value) { $this->attributes['skills'] = json_encode($value); } public function getSkillsAttribute($value) { return json_decode($value, true); //include true arguent to create array instead of std class } }
Overrides
For more complex resources, you will need to override default functionality.
Index Ordering
If you want to change the order of display on the index page, simply give your model a query scope called defaultOrder:
public function scopeDefaultOrder($query){ return $query->orderBy('name','asc'); }
View Overrides
Overriding the default view for any resource manager screens is easy. All you need to do is create the overridden view, and it will be loaded. If you don't already have one, you will need a resources/views/admin
folder.
Within this folder, create a folder for your resource and whichever of the following files you want to override:
resources/views/admin/
[resource-names]/ //this folder needs to be the pluralized, hyphenated name of your resource
resource/ //this folder holds all the necessary resource views
index.blade.php
edit.blade.php
create.blade.php
show.blade.php
partials/
form.blade.php //the form for creating/editing your resource.
It's recommended to start with the default views in this package as a starting point when creating an override.
Functionality Overrides
There are some extra functionions outside of typical REST that you can use to add functionality without overriding the REST functions.
Validation
// define the rules for laravel controller validation for the store request protected function getValidationRulesStore() { return [ ]; } // define custom validation messages for laravel controller validation for the store request protected function getValidationMessagesStore() { return [ ]; }
Additional Manipulation of Data
//Allows you do manipulate form input before creting the new resource instance. if errors are be produced, return $args['errors'] with the error message protected function uniqueStoreArgs($args) { return $args; }
All these methods have versions for update requests. Simply replace 'Store' with 'Update' in the function names.
Pre-Destroy Functionality
If you need to do anything prior to deleting a model instance, you can override the following function:
protected function pre_destroy($id){ return true; }
Change log
Please see CHANGELOG for more information what has changed recently.
License
Exclusive. Please see License File for more information.