-
Notifications
You must be signed in to change notification settings - Fork 919
Description
Right now we're configuring the entire CrudPanel object inside the EntityCrudController::setup()
method. That's basically all we're doing inside setup()
, because all calls start with $this->crud
.
I think this makes Backpack easy to understand. Since it happens inside the EntityCrudController, even a first-timer with medium OOP knowledge should understand what's happening.
BUT.
For big (huge) CRUDs, the setup()
method becomes so bloated. Just take a look at the MonsterCrudController in the demo. It's very very rare that you'll need a CRUD this complicated, but when you do, it's a drag to organize the code inside the CrudController. There are a few options, but none of them good, in my opinion. You can further split your configuration using:
- comments inside the
setup()
method (not really an organization method imho) - methods like
addFieldsToCrud()
,addFiltersToCrud()
or something likeaddMetaFakeFields()
that you could even isolate into a trait, that you can then reuse across multiple EntityCrudControllers;
Out of the above, I definitely like no 2 better, but even that one has got problems:
- I'm used to my controllers having all methods
public
and accessible through routes. - When creating new methods, you really have to make sure you're not overwriting some CrudPanel or CrudTrait methods;
- The CrudPanel configuration is in the same object as its representation;
A solution to this problem (or maybe it isn't a real problem, you tell me) could be to configure the CrudPanel separately - not in the CrudPanel at all, but in a Builder. So that your MonsterCrudController
could look something like:
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\MonsterRequest as StoreRequest;
// VALIDATION: change the requests to match your own file names if you need form validation
use App\Http\Requests\MonsterRequest as UpdateRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use App\CrudPanel\MonsterCrudPanelConfiguration;
class MonsterCrudController extends CrudController
{
public function setup()
{
$this->crud = $this->crud->makeFrom(MonsterCrudPanelConfiguration::class);
}
public function store(StoreRequest $request)
{
$redirect_location = parent::storeCrud($request);
return $redirect_location;
}
public function update(UpdateRequest $request)
{
$redirect_location = parent::updateCrud($request);
return $redirect_location;
}
public function show($id)
{
$content = parent::show($id);
// so we want to change something only for the Show operation
// ok, sure, we can do it here
$this->crud->addColumn([
'name' => 'table',
'label' => 'Table',
'type' => 'table',
'columns' => [
'name' => 'Name',
'desc' => 'Description',
'price' => 'Price',
]
]);
$this->crud->addColumn([
'name' => 'fake_table',
'label' => 'Fake Table',
'type' => 'table',
'columns' => [
'name' => 'Name',
'desc' => 'Description',
'price' => 'Price',
],
]);
$this->crud->addColumn([
'name' => 'upload_multiple',
'label' => 'Upload multiple',
'type' => 'upload_multiple',
// 'disk' => 'uploads',
]);
$this->crud->addColumn('text');
$this->crud->removeColumn('date');
$this->crud->removeColumn('extras');
return $content;
}
}
With a separate file containing the actual configuration (pseudo-code here):
<?php
namespace App\CrudPanels;
class MonsterCrudControllerConfiguration extends CrudPanelConfiguration
{
public function fields() {
return [];
}
public function columns()
{
return [];
}
public function filters()
{
return [];
}
public function buttons()
{
return [];
}
}
What I like about this:
- would make it easier for someone to see all configuration options, since the methods are generated in the builder;
- would probably make it easier to generate configurations;
- it would separate CrudPanel configuration from the actual representation; we need to do that anyway, at some point - it's just good OOP for big objects like this one;
- it would allow us to create CRUDs inside CRUDs (aka "matrix field type", aka “add related item in a pop-up”) - we could just have a
related_crud
field type that points to this configuration file; - it would make it easier for us to generate 100% complete CRUD panels - we just generate this configuration file;
- it would make it easier to share configurations between admin panels, or create multiple admin panels for the same entity (just extend the configuration file and modify a few things);
What I don't like about this solution:
- configuration is still not split up into Operations (Create, Update, Delete, ListEntries), and I think it should be;
- how would you go about enabling/disabling some nitch features of an operation? say
disableResponsiveTable()
?
Food for thought...