Inspired by the ruby gem InheritResource
I bring you quick minimalist resource controllers in laravel
Simply place resource trait in your controller
namespace App\Http\Controllers;
use Dgoring\Laravel\InheritResource\Resource;
class UsersController extends Controller
{
use Resource;
}
with the resource route in your routes file
Route::resource('users', 'UsersController');
And all the resource functions are placed and run against the class as well as loading the views
all settings are assumed by the name of the controller so UsersController
is assumed to use
App\User
for the model classuser
the route parameter- these views are assumed for there respective resource functions
--
users.index
with$users
passed into it as a paginator collection --users.show
with$user
passed into it as the instance of the record --users.create
with$user
a fresh new instance of the model --users.edit
with$user
passed into it as the instance of the record
To override the query used for say filtering the index page
you can override the collection
function
class UsersController extends Controller
{
use Resource { collection as query; }
protected function collection()
{
$query = $this->query();
if($search = request()->query('search'))
{
$query->where('name', 'like', "%{$search}%");
}
return $query;
}
}
The collection
function is also used for all resource functions to give the base query
So can be used to filter content across the controller
protected function collection()
{
$query = $this->query();
$query->where('active', 1);
return $query;
}
By default all the actions are put through the authorize function, so you can control access to this resource
index
->authorize(viewAny
, class)create
->authorize(create
, new instance)store
->authorize(create
, new instance)edit
->authorize(update
, instance)update
->authorize(update
, instance)destroy
->authorize(delete
, instance)
You can specify validation rules for the store
and update
functions but defining validationRules
function
class UsersController extends Controller
{
use Resource;
protected function validationRules()
{
if($this->resource()->exists)
{
return [
'name' => 'string',
];
}
else
{
return [
'name' => 'string|required',
];
}
}
}
Nested resources are just as easy
Simply setup your route
Route::resource('teams.users', 'UsersController');
And return the relationship in the collection function
use App\Team;
class UsersController extends Controller
{
use Resource { collection as query; }
protected function collection()
{
$team = Team::findOrFail(request()->route('team'));
$query = $team->users();
if($search = request()->query('search'))
{
$query->where('name', 'like', "%{$search}%");
}
return $query;
}
}
as the collection function is used for the create
and store
functions
as long as your return the relationship from the parent model the relationship should be saved to the new record
and it should also already be in the model in the create
view variable
this resource is also ready to respond to json requests
note that the index will return a total count in the response headers as Count
also if defined in a appropriate place a JsonCollection or JsonResource formatter will be used for the model i.e.
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
}
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UsersCollection extends ResourceCollection
{
}
And you can also allow only JSON responses
namespace App\Http\Controllers;
use Dgoring\Laravel\InheritResource\JsonResource;
class UsersController extends Controller
{
use JsonResource;
}
or only HTML
namespace App\Http\Controllers;
use Dgoring\Laravel\InheritResource\HtmlResource;
class UsersController extends Controller
{
use HtmlResource;
}
By default models are assumed to be under the App
namespace but you can change that by adding the file config/inherit_resource.php
below shows the config file for App\Models
and also the namespaces for the json resources and collections
<?php
return [
'namespace' => 'App\\Models\\',
'json_resources' => 'App\\Http\\Resources\\',
'json_collections' => 'App\\Http\\Collections\\',
];
class UsersController extends Controller
{
use Resource;
public function __construct()
{
$this->class_name = CustomUser::class; // Model Class
$this->instance_name = 'custom_user'; // Route parameter and name of variable passed to single record views
$this->collection_name = 'customer_users'; // Name of variable passed to index view
$this->authorize = false; // Switch to turn off authorize checks (default is on)
$this->saveTransaction = true; // while enabled model save and delete function are performed within a database transaction
$this->distinctFix = true; // if the query builder returns a distinct query, a fix will be applied to get the distinct count used for pagination
$this->fillOnlyValidated = true; // while enabled only the validated fields will be allowed to be mass assigned to the model
//Only for Resource and HtmlResource
$this->view_ns = 'customer_users'; // dot notation path to views folder
$this->views = [ // name of view used for each function
'index' => 'index',
'create' => 'form',
'show' => 'show',
'edit' => 'form',
];
}
}
these response functions can be overridden to allow you to have completely custom responses to certain actions without having to override the entire route function
class UsersController extends Controller
{
use Resource;
protected function htmlIndex();
protected function htmlShow();
protected function htmlCreate();
protected function htmlStoreSuccess();
protected function htmlStoreFailure();
protected function htmlEdit();
protected function htmlUpdateSuccess();
protected function htmlUpdateFailure();
protected function htmlDestroySuccess();
protected function htmlDestroyFailure();
protected function jsonIndex();
protected function jsonShow();
protected function jsonStoreSuccess();
protected function jsonStoreFailure();
protected function jsonUpdateSuccess();
protected function jsonUpdateFailure();
protected function jsonDestroySuccess();
protected function jsonDestroyFailure();
}