darvinstudio/darvin-content-bundle
Installation
composer require darvinstudio/darvin-content-bundle
Register the bundle in config/bundles.php:
return [
// ...
DarvinStudio\ContentBundle\DarvinContentBundle::class => ['all' => true],
];
Database Migration Run migrations to set up the core tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Use Case: Basic Content Widget Create a widget via CLI:
php bin/console darvin:content:widget:create --name="Header" --type="text"
Render it in a Twig template:
{{ render(controller('DarvinContentBundle:Widget:render', {'id': widget.id})) }}
Key Documentation
Widget Management
darvin:content:widget:create for predefined types (text, html, image, etc.).DarvinStudio\ContentBundle\Entity\Widget or use the admin interface (if provided).WidgetManager service to fetch and render widgets dynamically:
$widget = $widgetManager->find($widgetId);
return $this->renderView('DarvinContentBundle:Widget:render.html.twig', ['widget' => $widget]);
Content Controllers
# config/routes.yaml
darvin_content_section:
path: /content/{slug}
controller: DarvinStudio\ContentBundle\Controller\ContentController::sectionAction
templates/DarvinContentBundle/ to customize layouts.Metadata Handling
# config/packages/darvin_content.yaml
darvin_content:
metadata:
widget.header:
title: "Header Widget"
description: "Displays a promotional header"
$metadata = $this->get('darvin_content.metadata_reader')->getMetadata('widget.header');
Translations
translations/messages.en.yaml:
widget:
header:
title: "Welcome"
{{ 'widget.header.title'|trans }}
$form = $this->createForm(WidgetType::class, $widget);
#[ApiResource]
class Widget extends BaseWidget {}
WidgetPreSaveEvent):
$eventDispatcher->addListener(WidgetEvents::PRE_SAVE, function (WidgetEvent $event) {
$event->setWidgetContent(strtoupper($event->getWidgetContent()));
});
Database Schema
widget, widget_type, metadata) exist.php bin/console doctrine:schema:update --force if migrations fail.Widget Caching
php bin/console cache:clear
# config/packages/darvin_content.yaml
darvin_content:
cache: false
Translation Overrides
# translations/messages.custom.yaml
widget.header.title: "Custom Title"
trans with domain:
{{ 'widget.header.title'|trans({'%domain%': 'custom'}) }}
Security
render() may expose sensitive data. Validate input:
$widget = $widgetManager->find($id);
if (!$widget->isPublished()) {
throw $this->createAccessDeniedException();
}
Widget Not Rendering?
widget_type table.templates/DarvinContentBundle/Widget/{type}.html.twig).php bin/console debug:config darvin_content
Metadata Not Loading?
config/packages/darvin_content.yaml.Custom Widget Types
DarvinStudio\ContentBundle\Entity\BaseWidget and register the type:
$widgetType = new WidgetType();
$widgetType->setName('custom');
$widgetType->setClass('App\Entity\CustomWidget');
$entityManager->persist($widgetType);
Admin Panel
// Example for EasyAdmin
$builder
->setEntity(Widget::class)
->add('content', TextType::class);
Event Subscribers
WidgetPostSave) for analytics or notifications:
public static function getSubscribedEvents()
{
return [
WidgetEvents::POST_SAVE => 'onWidgetSave',
];
}
Custom Metadata Drivers
MetadataReaderInterface for non-YAML sources (e.g., database):
class DatabaseMetadataReader implements MetadataReaderInterface
{
public function getMetadata(string $key): array
{
// Fetch from DB
}
}
How can I help you explore Laravel packages today?