ecentria/ecentria-rest-bundle
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require ecentria/ecentria-rest-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Ecentria\RestBundle\EcentriaRestBundle::class => ['all' => true],
];
First Use Case:
Create a RESTful resource controller for a Post entity:
php bin/console generate:bundle --namespace=App/Bundle/PostBundle --format=yml --dir=src --bundle=PostBundle
Extend EcentriaRestBundle's RestController:
// src/PostBundle/Controller/PostController.php
namespace App\Bundle\PostBundle\Controller;
use Ecentria\RestBundle\Controller\RestController;
use App\Bundle\PostBundle\Entity\Post;
class PostController extends RestController
{
public function getEntityFQCN(): string
{
return Post::class;
}
}
Routing:
Configure routes in config/routes.yaml:
app_post:
resource: "@PostBundle/Resources/config/routing.yml"
prefix: /api/posts
Verify: Access endpoints like:
GET /api/posts (List)POST /api/posts (Create)GET /api/posts/{id} (Read)PUT/PATCH /api/posts/{id} (Update)DELETE /api/posts/{id} (Delete)RestController and implement getEntityFQCN() to define the managed entity.
class UserController extends RestController
{
public function getEntityFQCN(): string
{
return User::class;
}
}
getList(), getItem(), or postItem() for custom logic.
public function getList(): Response
{
$users = $this->getDoctrine()->getRepository(User::class)->findActiveUsers();
return $this->handleList($users);
}
_links.self, _links.collection) in responses.addLink() in controllers:
public function getItem(User $user): Response
{
$response = $this->handleItem($user);
$response->getData()->addLink('profile', '/api/users/'.$user->getId().'/profile');
return $response;
}
@Groups annotations to control serialization:
use Symfony\Component\Serializer\Annotation\Groups;
class User
{
#[Groups(['user:read'])]
private string $name;
}
public function getItem(User $user): Response
{
return $this->handleItem($user, ['groups' => ['user:read']]);
}
@Assert\NotBlank).validate() in controllers or use Symfony’s ValidatorInterface.knplabs/knp-paginator-bundle for pagination:
# config/packages/ecentria_rest.yaml
ecentria_rest:
pagination:
enabled: true
items_per_page: 20
Paginator object to handleList():
public function getList(): Response
{
$paginator = $this->get('knp_paginator');
$users = $paginator->paginate(
$this->getDoctrine()->getRepository(User::class)->findAll(),
$this->getRequest()->query->getInt('page', 1),
10
);
return $this->handleList($users);
}
prePersist, preUpdate, or postRemove:
// src/EventListener/UserListener.php
namespace App\EventListener;
use Ecentria\RestBundle\Event\RestEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class UserListener implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'ecentria_rest.pre_persist' => 'onPrePersist',
];
}
public function onPrePersist(RestEvent $event): void
{
$user = $event->getEntity();
$user->setCreatedAt(new \DateTime());
}
}
# config/packages/security.yaml
access_control:
- { path: ^/api/users, roles: ROLE_USER }
RestController to add authentication logic:
public function postItem(): Response
{
if (!$this->isGranted('ROLE_ADMIN')) {
throw $this->createAccessDeniedException();
}
return parent::postItem();
}
Client to test endpoints:
public function testGetPosts(): void
{
$client = static::createClient();
$client->request('GET', '/api/posts');
$this->assertResponseIsSuccessful();
$this->assertJsonContains([
'@context' => '/api/contexts/Post',
'@id' => '/api/posts',
]);
}
RestController in unit tests:
$controller = $this->getMockBuilder(RestController::class)
->setMethods(['getEntityFQCN'])
->getMock();
$controller->method('getEntityFQCN')->willReturn(Post::class);
Entity Not Found:
404 when accessing /api/resource/{id} even if the entity exists.getItem() in your controller is properly annotated or overridden. Verify the find() method in the repository returns the entity.getItem():
public function getItem($id): Response
{
$entity = $this->getDoctrine()->getRepository($this->getEntityFQCN())->find($id);
if (!$entity) {
throw $this->createNotFoundException('Entity not found');
}
return $this->handleItem($entity);
}
Serialization Errors:
500 Internal Server Error with "Unable to serialize object" in responses.@Ignore for non-serializable properties:
use Symfony\Component\Serializer\Annotation\Ignore;
class User
{
#[Ignore]
private $sensitiveData;
}
NormalizerInterface to customize serialization:
// src/Serializer/UserNormalizer.php
namespace App\Serializer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class UserNormalizer implements NormalizerInterface
{
public function normalize($object, $format = null, array $context = [])
{
return [
'id' => $object->getId(),
'name' => $object->getName(),
];
}
}
Register it in config/packages/ecentria_rest.yaml:
ecentria_rest:
normalizers:
- App\Serializer\UserNormalizer
HATEOAS Links Missing:
_links section is empty in responses.config/packages/ecentria_rest.yaml:
ecentria_rest:
hateoas:
enabled: true
RestResponse object is being returned correctly. Override handleItem() or handleList() to inspect the response:
public function getItem(User $user): Response
{
$response = $this->handleItem($user);
$data = $response->getData();
dump($data->getLinks()); // Debug links
return $response;
}
**Pagination Not Working
How can I help you explore Laravel packages today?