Installation Run the composer command in your project root:
composer require dovstone/symfony-blog-admin
Ensure Dovstone\BlogAdminBundle\DovstoneBlogAdminBundle is enabled in config/bundles.php.
Database Migration Execute the bundle’s migrations:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Use Case
Access /admin/blog to see the default admin interface. The bundle provides CRUD for:
Post entity)Category entity)User entity)Post Management
/admin/blog/post route.Post entity (src/Entity/Post.php) to extend fields (e.g., slug, meta_title).// src/Entity/Post.php
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $customField;
Category Hierarchy
Category entity (src/Entity/Category.php) to add custom logic:
// Add a method to fetch child categories
public function getChildren(): Collection
{
return $this->children->matching(new Expression('parent = :parent'), [':parent' => $this]);
}
Frontend Integration
PostRepository:
// src/Controller/BlogController.php
public function index(PostRepository $repo): Response
{
$posts = $repo->findBy([], ['createdAt' => 'DESC']);
return $this->render('blog/index.html.twig', ['posts' => $posts]);
}
{% for post in posts %}
<h2>{{ post.title }}</h2>
<p>{{ post.content|truncate(200) }}</p>
{% endfor %}
Custom Controllers/Forms
# config/routes.yaml
dovstone_blog_admin_post:
resource: "@DovstoneBlogAdminBundle/Resources/config/routing/post.yaml"
type: annotation
prefix: /admin/blog
// src/Form/PostType.php
class PostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('customField', TextType::class);
}
}
Outdated Doctrine Migrations
doctrine/orm and doctrine/doctrine-bundle versions are compatible.src/Resources/migrations/ for schema changes if extending entities.Hardcoded Routes
/admin/blog. Override them in config/routes.yaml to avoid conflicts:
dovstone_blog_admin:
resource: "@DovstoneBlogAdminBundle/Resources/config/routing/admin.yaml"
prefix: /custom-prefix
Lack of Documentation
Translation Issues
Resources/translations/messages.en.xlf. Extend them by copying the file to translations/messages.en.xlf in your project.Entity Extensions
Post or Category, clear the cache after changes:
php bin/console cache:clear
Form Validation
// src/Entity/Post.php
public function getCustomField(): ?string
{
return $this->customField;
}
public function setCustomField(?string $customField): self
{
$this->customField = $customField;
return $this;
}
// Add constraints in the form type
$builder->add('customField', TextType::class, [
'constraints' => [new Length(['max' => 100])],
]);
Query Performance
PostRepository methods to optimize queries:
// Avoid N+1 queries
$posts = $repo->findBy([], ['createdAt' => 'DESC'], null, 10);
Custom Admin Layout
{# templates/blog_admin/base.html.twig #}
{% extends 'DovstoneBlogAdminBundle:layout.html.twig' %}
{% block stylesheets %}
{{ parent() }}
{{ encore_entry_link_tags('admin-blog') }}
{% endblock %}
Event Listeners
PostEvents::POST_PERSIST):
// src/EventListener/PostListener.php
class PostListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
PostEvents::POST_PERSIST => 'onPostPersist',
];
}
public function onPostPersist(PostEvent $event)
{
$post = $event->getPost();
// Add logic (e.g., generate slug)
$post->setSlug(Str::slug($post->getTitle()));
}
}
API Integration
Serializer:
// src/Controller/ApiPostController.php
#[Route('/api/posts', methods: ['GET'])]
public function index(PostRepository $repo, SerializerInterface $serializer): JsonResponse
{
$posts = $repo->findAll();
return new JsonResponse($serializer->serialize($posts, 'json', ['groups' => 'api']));
}
How can I help you explore Laravel packages today?