Installation
composer require ekyna/blog-bundle
Add to config/app.php under providers:
Ekyna\BlogBundle\BlogBundle::class,
Publish the config:
php artisan vendor:publish --provider="Ekyna\BlogBundle\BlogBundle" --tag=config
First Use Case Create a blog post via Trait:
use Ekyna\BlogBundle\Entity\BlogPostTrait;
class MyPost
{
use BlogPostTrait;
}
Configure config/blog.php with basic settings (title, default author, etc.).
Database Migration Run:
php artisan migrate
Check database/migrations/ for generated tables (blog_posts, blog_categories, etc.).
Post Management
$post = new \Ekyna\BlogBundle\Entity\BlogPost();
$post->setTitle('First Post');
$post->setContent('Hello, world!');
$post->setSlug('hello-world');
$post->setPublishedAt(new \DateTime());
$entityManager->persist($post);
BlogPostRepository (auto-registered) for queries:
$posts = $blogPostRepo->findBy(['published' => true]);
Category Integration
$category = new \Ekyna\BlogBundle\Entity\BlogCategory();
$category->setName('Tutorials');
$post->addCategory($category);
Routing & Controllers
blog.post.show route (auto-generated) or extend:
# config/routes.yaml
blog_post:
resource: '@EkynaBlogBundle/Resources/config/routing/posts.yaml'
prefix: /blog
Twig Integration
{% for post in blog_posts %}
<h2>{{ post.title }}</h2>
<p>{{ post.content|raw }}</p>
{% endfor %}
Event Listeners
// src/EventListener/BlogPostListener.php
class BlogPostListener
{
public function onPrePersist(BlogPost $post)
{
if (empty($post->getSlug())) {
$post->setSlug(Str::slug($post->getTitle()));
}
}
}
Register in services.yaml:
services:
App\EventListener\BlogPostListener:
tags:
- { name: kernel.event_listener, event: blog.post.pre_persist, method: onPrePersist }
Missing Configuration
config/blog.php may lack required keys (e.g., default_author).php artisan vendor:publish --tag=config and verify defaults.Slug Conflicts
$post->setSlug(Uuid::v4()->toString());
Entity Inheritance
BlogPostTrait may cause conflicts with existing traits.Route Overrides
blog_custom:
path: /custom-blog
controller: App\Controller\CustomBlogController::index
Translation Support
{{ 'blog.post.published_at'|trans }}
Check Events
Use dd() in event listeners to inspect payloads:
public function onPostPublish(BlogPostEvent $event)
{
dd($event->getPost()->getData());
}
Doctrine Events Enable SQL logging for migrations:
// config/packages/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Bundle Assets Clear cache after publishing assets:
php artisan cache:clear
php artisan config:clear
Custom Fields
Extend BlogPost entity with additional fields:
/**
* @ORM\Column(type="string", nullable=true)
*/
private $customField;
Validation
Add constraints to BlogPost:
use Symfony\Component\Validator\Constraints as Assert;
/**
* @Assert\Length(min=10)
*/
private $content;
API Integration Use Symfony Serializer for JSON responses:
use Symfony\Component\Serializer\Annotation\Groups;
class BlogPost
{
/**
* @Groups({"blog:read"})
*/
public function getTitle(): string
{
return $this->title;
}
}
Testing Mock the repository in tests:
$blogPostRepo = $this->createMock(BlogPostRepository::class);
$blogPostRepo->method('findBy')->willReturn([$mockPost]);
$container->set(BlogPostRepository::class, $blogPostRepo);
How can I help you explore Laravel packages today?