Background Image

Architecture

LaraAdmin is inspired by the data management philosophy of the open source project SugarCRM, which has a module manager, workflows and many other features, but is large and hard to customize. At Dwij IT Solutions we needed rapid development of web applications, so we built LaraAdmin: an admin backend that can grow into a CRM.

LaraAdmin is schema driven. Modules and their fields are rows in the database. The admin panel reads those rows at run time to build forms, listings, validation and access checks, and the code generator reads them to write controllers, models and views. Since 1.1 it is a Laravel application template: all of this code is in your application, not in a package.

PathContents
app/Models/LAModule.phpThe core: creating modules and columns, saving records, validation, access checks, module deletion
app/Models/LAModuleField, LAModuleFieldType, LAMenu, LAConfig, LALog, Upload, Role, Permission, User and the module models
app/Helpers/LAFormMaker.phpForm inputs and displayed values for each field type
app/Helpers/CodeGenerator.phpWrites migrations and CRUD files from the stubs
app/Helpers/LAHelper.phpMenus, thumbnails, names, access cache and other helpers
app/Stubs/Templates of the generated controller, model, observer, views, routes, migration and language file
app/Http/Controllers/LA/Admin controllers: Module Manager, menus, settings, and one per module
app/Observers/One observer per module
app/Console/Commands/la:migration and la:crud
app/Providers/LAProvider.phpRegisters packages, facade aliases, Blade directives, commands and observers
config/laraadmin.phpAdmin URL, blog URL, uploads and log types
routes/admin.phpAll admin routes (loaded at the end of routes/web.php)
resources/views/la/Admin views: layouts and <module>/index|edit|show.blade.php
resources/less/, public/la-assets/AdminLTE / Bootstrap 3 theme in LESS, and its compiled CSS and JS
database/migrations/, database/seeders/LaraAdminSeeder.phpModule migrations and the seed data (roles, menus, settings, access)
storage/uploads/Uploaded files

Metadata tables

TableStores
la_modulesOne row per module: name, label, table, model, controller, view column, icon, whether the CRUD is generated
la_module_fieldsOne row per field: column, label, type, unique, default, min, max, required, listing, values, sort order
la_module_field_typesThe 31 field types
role_la_module, role_la_module_fieldsModule and field access per role
roles, permissions, role_user, permission_roleEntrust roles and permissions
la_menus, role_la_menuSidebar menu and its access
la_configsSettings of the Configure page
la_logsActivity log

LAModule

  • LAModule::generate($name, $table, $viewCol, $icon, $fields) is called from migrations. It creates the table and the module's rows.
  • LAModule::create_field_schema() maps each field type to Laravel schema builder columns. When a field is edited, it restates the whole column with ->change(). Since 1.13 this is Laravel's native column change: Doctrine DBAL is no longer used, and columns are read with Schema::getColumns() / Schema::getForeignKeys().
  • At run time, controllers call LAModule::validateRules(), insert() and updateRow(), which turn a request into a row field by field, skipping fields the user may not write.
  • LAModule::get('Courses') returns the module with its fields. hasAccess() and hasFieldAccess() check access (see Roles & Access Control).
  • LAModule::deleteModule() removes a module, its table and its generated code.

Form maker

LAFormMaker renders each field type's input and display value on top of laraadmin/html (Form::). Views use it through Blade directives:

@la_form($module)                         {{-- every field the user may write --}}
@la_form($module, ['name', 'fees'])       {{-- only these fields --}}
@la_input($module, 'fees')                {{-- one input with its label --}}
@la_display($module, 'fees')              {{-- one value, with its label --}}
@la_config_input('sitename')              {{-- input of a setting --}}
@la_access('Courses', 'edit') ... @endla_access
@la_field_access('Courses', 'fees') ... @endla_field_access

Because generated views call these directives instead of listing the fields, fields added later in Module Manager appear in the forms without regenerating the views.

CodeGenerator fills the templates in app/Stubs/*.stub, replacing tokens like __module_name__, __model_class_name__ and __db_table_name__, and writes the results into your application.

It also edits three existing files, by finding a marker and inserting before it. If a marker is changed or removed, generation silently stops updating that file:

FileMarkerWhat is added
app/Providers/LAProvider.php// End of Boot - Please do not edit this line.The module's observer registration
config/laraadmin.php// More LALogs Configurations - Do not edit this line (with its leading spaces)The module's log types
routes/admin.phpThe last }); of the fileThe module's routes (from routes.stub), inside the admin group

Module deletion finds the routes to remove by the controller names in them ('CoursesController' and 'CoursesController@dtajax'), so keep that form when editing generated routes.

routes/web.php ends with require __DIR__.'/admin.php'. routes/admin.php has two route groups with the App\Http\Controllers\LA namespace and the config('laraadmin.adminRoute') prefix:

  1. Super Admin only (role:SUPER_ADMIN): Module Manager, fields, menus, settings, the code editor.
  2. Admin panel (permission:ADMIN_PANEL): the dashboard and every module's resource route plus its *_dt_ajax DataTables endpoint. Controllers check module access.

Public routes in routes/web.php: the home page, the blog, registration, and /files/{hash}/{name} for uploads.

LAProvider registers the facade aliases Form, HTML, LAModule, LAConfig, LAHelper, CodeGenerator and Entrust, the Blade directives above, the la:* commands, and the observers. If the optional laraadmin/editor package is installed, it loads it too (see Code Editor).

PackageUsed for
laraadmin/entrust 7Roles, permissions, role / permission / ability middleware
laraadmin/html 7Form:: and HTML:: builders (fork of laravelcollective/html)
yajra/laravel-datatables-oracle 13Server-side listing tables
spatie/laravel-backup 10Backups
laravel/ui 4, laravel/sanctum 4Login and registration screens, API tokens

The application keeps the Laravel 8 structure (app/Http/Kernel.php, app/Console/Kernel.php, app/Exceptions/Handler.php and the classic bootstrap/app.php), which Laravel 13 still supports.


What's Next ?