symfony-cmf/content-bundle
Symfony CMF Content Bundle for integrating a content repository (PHPCR/Doctrine) into Symfony apps. Provides document mapping, content models, persistence and admin-friendly tools to build CMS features on top of CMF components.
Since symfony-cmf/content-bundle is Symfony-based, integration into Laravel requires Symfony Bridge or Laravel Symfony Components. Start by:
Install via Composer (if using Symfony Bridge):
composer require symfony-cmf/content-bundle
For Laravel-only projects, use symfony/cmf-bundle as a reference and manually port core concepts (e.g., Document, RouteProviderInterface).
Configure Routing:
The bundle relies on Symfony’s Routing component. In Laravel, mimic this with:
// routes/web.php
Route::get('/content/{slug}', [ContentController::class, 'show']);
Define a Basic Document Model:
Extend Symfony\CMF\Component\Routing\RouteObjectInterface:
namespace App\Models;
use Symfony\CMF\Component\Routing\RouteObjectInterface;
class Page implements RouteObjectInterface
{
public function getRoute(): array
{
return [
'_controller' => 'App\Http\Controllers\PageController::show',
'slug' => $this->slug,
];
}
}
First Use Case:
Create a PageController to render content:
namespace App\Http\Controllers;
use App\Models\Page;
use Illuminate\Http\Request;
class PageController extends Controller
{
public function show(Request $request, Page $page)
{
return view('pages.show', ['page' => $page]);
}
}
Hierarchical Content:
Use Symfony\CMF\Component\Routing\RouteObjectInterface for nested routes (e.g., blogs with categories).
class BlogPost extends Page
{
public function getRoute(): array
{
return [
'_controller' => 'App\Http\Controllers\BlogPostController::show',
'slug' => $this->slug,
'category' => $this->category->slug, // Nested route
];
}
}
Dynamic Routes:
Leverage RouteProviderInterface to generate routes dynamically:
namespace App\Providers;
use Symfony\CMF\Component\Routing\RouteProviderInterface;
class AppRouteProvider implements RouteProviderInterface
{
public function getRouteCollection()
{
$collection = new RouteCollection();
$collection->add('home', $this->createHomeRoute());
return $collection;
}
}
Eloquent + CMF: Combine with Laravel’s Eloquent for persistence:
use Illuminate\Database\Eloquent\Model;
use Symfony\CMF\Component\Routing\RouteObjectInterface;
class EloquentPage extends Model implements RouteObjectInterface
{
protected $fillable = ['title', 'slug', 'content'];
// ...
}
Blade Templates: Use Blade to render CMF-powered content:
@foreach($pages as $page)
<a href="{{ route('content.show', $page->slug) }}">
{{ $page->title }}
</a>
@endforeach
Page models with slug and content.RouteServiceProvider to load CMF routes:
public function boot()
{
parent::boot();
$this->router->getRouteCollection()->addCollection(
app(AppRouteProvider::class)->getRouteCollection()
);
}
Archived Package:
symfony/routing).Route Overrides:
Route::middleware(['cmf.routes'])->group(function () {
// CMF routes here
});
Database Migrations:
RouteObjectInterface to Eloquent:
// Migration for pages table
Schema::create('pages', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->text('content');
$table->timestamps();
});
Route Dumping:
Use Symfony’s RouteDebuggerBundle (if bridged) or dump Laravel routes:
php artisan route:list
Filter for CMF-generated routes (e.g., prefixed with content).
Route Matching Issues:
Ensure RouteObjectInterface::getRoute() returns a valid Laravel route array:
// Bad: Symfony-specific controller format
return ['_controller' => 'AppBundle:Page:show'];
// Good: Laravel-compatible
return ['uses' => 'App\Http\Controllers\PageController@show'];
Custom Route Loaders:
Extend RouteProviderInterface to add logic (e.g., cache routes):
class CachedRouteProvider implements RouteProviderInterface
{
public function getRouteCollection()
{
return Cache::remember('cmf.routes', now()->addHours(1), function () {
return parent::getRouteCollection();
});
}
}
Content Events:
Dispatch Laravel events for CMF actions (e.g., PageCreated):
event(new PageCreated($page));
Listen in EventServiceProvider:
protected $listen = [
PageCreated::class => [
UpdateSearchIndex::class,
],
];
API Integration: Use Laravel’s API resources to expose CMF content:
namespace App\Http\Resources;
use App\Models\Page;
use Illuminate\Http\Resources\Json\JsonResource;
class PageResource extends JsonResource
{
public function toArray($request)
{
return [
'slug' => $this->slug,
'content' => $this->content,
'route' => route('content.show', $this->slug),
];
}
}
How can I help you explore Laravel packages today?