blackboxcode/pando-content-bundle
Installation Add the bundle to your Laravel project via Composer:
composer require blackboxcode/pando-content-bundle
Register the bundle in config/app.php under providers:
BlackBoxCode\PandoContentBundle\PandoContentBundle::class,
Publish Configuration Publish the default config file:
php artisan vendor:publish --provider="BlackBoxCode\PandoContentBundle\PandoContentBundle" --tag="config"
Locate the config at config/pando_content.php.
First Use Case: Basic Content Management
Define a content type in a migration (e.g., pages):
use BlackBoxCode\PandoContentBundle\Migrations\CreateContentTypeTable;
Schema::create('content_types', function (Blueprint $table) {
CreateContentTypeTable::create($table, 'pages');
});
Create a model extending PandoContentModel:
use BlackBoxCode\PandoContentBundle\Models\PandoContentModel;
class Page extends PandoContentModel { protected $contentType = 'pages'; }
Insert content via Tinker or a controller:
$page = new Page();
$page->title = 'Home';
$page->content = '<h1>Welcome</h1>';
$page->save();
Content Type Definition
articles, products).CreateContentTypeTable for reusable schema logic.Schema::create('articles', function (Blueprint $table) {
CreateContentTypeTable::create($table, 'articles');
$table->string('slug')->unique();
$table->text('excerpt');
});
Model Integration
PandoContentModel for each content type.getContentType() if needed:
class Article extends PandoContentModel {
protected $contentType = 'articles';
public function getContentType() { return $this->contentType; }
}
Content Retrieval
$articles = Article::where('published', true)->orderBy('created_at', 'desc')->get();
$content = app(\BlackBoxCode\PandoContentBundle\Repositories\ContentRepository::class)
->findByType('pages', 1);
Frontend Integration
Route::get('/content/{type}/{id}', function ($type, $id) {
return app(\BlackBoxCode\PandoContentBundle\Repositories\ContentRepository::class)
->findByType($type, $id);
});
@foreach($pages as $page)
<h2>{{ $page->title }}</h2>
{!! $page->content !!}
@endforeach
Content Versioning
config/pando_content.php:
'versioning' => [
'enabled' => true,
'table' => 'content_versions',
],
$versions = $page->versions()->orderBy('created_at', 'desc')->get();
Content Type Naming
'pages') match the table names exactly.ContentNotFoundException.Model Binding
id column exists in the content table.getRouteKeyName() if needed:
public function getRouteKeyName() { return 'slug'; }
JSON Fields
content fields. Use dedicated columns for structured data.Caching
Cache::forget("pando_content_{$contentType}_{$id}");
Query Logs Enable Laravel’s query logging to debug content retrieval:
DB::enableQueryLog();
$content = Article::find(1);
dd(DB::getQueryLog());
Content Type Existence
Verify content types exist in the content_types table before querying.
Versioning Conflicts
If versioning is enabled, ensure the content_versions table exists and has the correct schema.
Custom Fields
Extend the PandoContentModel to add custom accessors/mutators:
public function getFormattedContentAttribute() {
return nl2br(e($this->content));
}
Events
Listen for content events (e.g., ContentSaved):
Event::listen(\BlackBoxCode\PandoContentBundle\Events\ContentSaved::class, function ($event) {
// Log or notify on content changes
});
API Resources Create custom API resources for content:
class PageResource extends JsonResource {
public function toArray($request) {
return [
'title' => $this->title,
'content' => $this->content,
'slug' => $this->slug,
];
}
}
Middleware Protect content routes with middleware:
Route::get('/admin/content', function () {
// ...
})->middleware('can:manage-content');
config/pando_content.php for fields like published_at.use SoftDeletes;
class Page extends PandoContentModel {
use SoftDeletes;
protected $dates = ['deleted_at'];
}
How can I help you explore Laravel packages today?