ctrl-f5/ctrl-rad-bundle
Symfony bundle to get apps running fast: SB Admin 2 layout with configurable sidebar/topbar/breadcrumbs, Twig extensions for Bootstrap UI, template overrides, configurable CRUD (index/edit) with grid, pagination and filters, plus an EntityService layer and TableView.
Since ctrl-rad-bundle is a Symfony bundle, Laravel developers must first bridge it using Symfony Bridge (symfony/console, symfony/http-kernel) or Laravel Symfony Integration (e.g., spatie/laravel-symfony-support). Install via Composer:
composer require ctrl-f5/ctrl-rad-bundle symfony/console symfony/http-kernel
Register the Bundle (in config/app.php for Laravel 5.x or config/bundles.php for Laravel 8+ with Symfony integration):
'providers' => [
// ...
CtrlRadBundle\CtrlRadBundle::class,
],
Publish Assets (Bower for SB Admin 2):
php artisan vendor:publish --provider="CtrlRadBundle\CtrlRadBundle\CtrlRadBundle" --tag=assets
npm install # Install Bower dependencies (if using Laravel Mix)
Generate a Basic CRUD Controller:
Use the EntityService layer to abstract Doctrine calls. Example:
// src/Service/PostService.php
namespace App\Service;
use CtrlRadBundle\Service\EntityService;
class PostService extends EntityService {
protected $entityClass = 'App\Entity\Post';
protected $repositoryMethod = 'findAll'; // Optional: Override default repo method
}
Create a Controller leveraging the TableView:
// src/Controller/PostController.php
use CtrlRadBundle\Controller\CrudController;
use App\Service\PostService;
class PostController extends CrudController {
protected $service;
public function __construct(PostService $service) {
$this->service = $service;
}
public function indexAction() {
$tableView = $this->service->createTableView();
$tableView->addColumn('title', 'Title');
$table->addRowAction('edit', 'Edit', ['route' => 'edit_post']);
return $this->render('CtrlRadBundle:Crud:index.html.twig', ['tableView' => $tableView]);
}
}
Route the Controller:
// routes/web.php
use App\Controller\PostController;
Route::resource('posts', PostController::class);
Override Layout Blocks (e.g., sidebar):
Create a custom template at resources/views/layouts/custom.html.twig:
{% extends 'CtrlRadBundle::layout.html.twig' %}
{% block sidebar %}
{{ parent() }}
<div class="sidebar-box">Custom Content</div>
{% endblock %}
topbar, sidebar, breadcrumbs) in your child template.{% set app_title = 'Posts Dashboard' %}
bower update after pulling SB Admin 2 updates.// src/Service/UserService.php
class UserService extends EntityService {
protected $entityClass = 'App\Entity\User';
protected $defaultSort = ['name' => 'ASC'];
public function getActiveUsers() {
return $this->findBy(['active' => true]);
}
}
$tableView = $this->service->createTableView();
$tableView->setItemsPerPage(20);
$tableView->addColumn('email', 'Email')
->addColumn('active', 'Status', 'label'); // Uses Twig `label` filter
$tableView->addRowAction('delete', 'Delete', ['route' => 'delete_user']);
{{ is_active|label }} {# Renders <span class="label label-success">Yes</span> #}
{{ pagination(tableView) }}
{{ button('Save', 'btn-primary', { onclick: 'saveForm()' }) }}
{{ buttonGroup([
button('Edit', 'btn-info'),
button('Delete', 'btn-danger')
]) }}
resources/views/FOSUserBundle/ (e.g., registration.html.twig).{% extends 'CtrlRadBundle::layout.html.twig' %}
{% block body %}
{{ parent() }}
{# FOSUser content #}
{% endblock %}
findAll is overridden in your entity repo, specify a custom method in EntityService:
protected $repositoryMethod = 'getPublishedPosts';
TableView columns reference loaded properties to avoid UndefinedPropertyException.call filter executes PHP callables. Use cautiously to avoid XSS:
{{ user.getFullName()|call }} {# Safe if `getFullName()` is trusted #}
is_type is case-sensitive:
{% if value is iterable %} {# Not `is_iterable` #}
webpack.mix.js:
mix.sass('resources/sass/app.scss', 'public/css')
.copy('vendor/bower_components/bootstrap/dist/css/bootstrap.css', 'public/css');
php artisan cache:clear
TableView object to inspect columns/actions:
dump($tableView->getColumns());
{{ dump(app.request.attributes) }} to debug block inheritance.EntityService to add domain logic:
class CustomEntityService extends EntityService {
public function getWithRelations() {
return $this->getEntityManager()
->getRepository($this->entityClass)
->findWithRelations();
}
}
config/packages/ctrl_rad.yaml:
twig:
globals:
app_version: "1.0.0"
$this->app->bind('ctrl_rad.entity_service', function ($app) {
return new EntityService($app['doctrine.orm.entity_manager']);
});
# config/routes.yaml (Symfony)
ctrl_rad_crud:
resource: "@CtrlRadBundle/Resources/config/routing/crud.xml"
prefix: /admin
How can I help you explore Laravel packages today?