freema / react-admin-api-bundle
Symfony bundle for React Admin API
Installs: 64
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 1
Open Issues: 0
Type:symfony-bundle
pkg:composer/freema/react-admin-api-bundle
Requires
- php: >=8.2
- doctrine/doctrine-bundle: ^2.10
- doctrine/orm: ^2.16 || ^3.0
- symfony/framework-bundle: ^6.4 || ^7.1
- symfony/http-kernel: ^6.4 || ^7.1
- symfony/routing: ^6.4 || ^7.1
- symfony/serializer: ^6.4 || ^7.1
- symfony/validator: ^6.4 || ^7.1
- symfony/yaml: ^6.4 || ^7.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.40
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.5
- symfony/browser-kit: ^6.4 || ^7.1
- symfony/debug-bundle: ^6.4 || ^7.1
- symfony/monolog-bundle: ^3.10
- symfony/test-pack: ^1.0
Conflicts
- symfony/framework-bundle: <6.4
README
Symfony bundle for automatically generating REST API endpoints compatible with React Admin. The bundle provides a complete infrastructure for creating CRUD APIs with minimal configuration - just create a DTO class and the bundle automatically provides all necessary endpoints.
Main Features
- ✅ Automatic endpoint registration - based only on resource → DTO configuration
- ✅ CRUD operations - GET, POST, PUT, DELETE with pagination, sorting, and filtering
- ✅ React Admin compatibility - standard response formats
- ✅ Doctrine integration - uses standard Symfony/Doctrine patterns
- ✅ Trait-based repository implementation - easy implementation of CRUD operations
- ✅ Type-safe DTO objects - clean architecture with separation of entity and API layer
- ✅ Flexible configuration - supports related resources
Architecture
The bundle is built on the principle of resource path → DTO class mapping. Everything else is derived automatically:
Resource path "users" → UserDto::class → User::class (from DTO) → UserRepository (from EntityManager)
Key Components:
- DTO (Data Transfer Object) - defines the API structure and maps to entities
- Repository traits - provide standard CRUD implementations
- Resource Configuration Service - manages resource to DTO mappings
- Controllers - automatically handle HTTP requests
Installation
composer require freema/react-admin-api-bundle
Register the bundle in config/bundles.php:
return [ // ... Freema\ReactAdminApiBundle\ReactAdminApiBundle::class => ['all' => true], ];
Configuration
Create configuration in config/packages/react_admin_api.yaml:
react_admin_api: resources: # Simple mapping: resource path => DTO class users: dto_class: 'App\Dto\UserDto' products: dto_class: 'App\Dto\ProductDto' related_resources: categories: dto_class: 'App\Dto\CategoryDto' relationship_method: 'getCategories'
Usage
1. Entity
The entity must implement AdminEntityInterface:
namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Freema\ReactAdminApiBundle\Interface\AdminEntityInterface; #[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Table(name: 'users')] class User implements AdminEntityInterface { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', length: 255)] private string $name = ''; #[ORM\Column(type: 'string', length: 255, unique: true)] private string $email = ''; // getters and setters... }
2. DTO (the most important part)
The DTO defines the API structure and is key to the bundle:
namespace App\Dto; use App\Entity\User; use Freema\ReactAdminApiBundle\Dto\AdminApiDto; use Freema\ReactAdminApiBundle\Interface\AdminEntityInterface; class UserDto extends AdminApiDto { public ?int $id = null; public string $name = ''; public string $email = ''; public array $roles = []; /** * Key method - tells the bundle which entity the DTO maps to */ public static function getMappedEntityClass(): string { return User::class; } /** * Create DTO from entity (for reading) */ public static function createFromEntity(AdminEntityInterface $entity): AdminApiDto { if (!$entity instanceof User) { throw new \InvalidArgumentException('Entity must be instance of User'); } $dto = new self(); $dto->id = $entity->getId(); $dto->name = $entity->getName(); $dto->email = $entity->getEmail(); return $dto; } /** * Convert DTO to array for API response */ public function toArray(): array { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'roles' => $this->roles, ]; } }
3. Repository
The repository implements CRUD operations using traits:
namespace App\Repository; use App\Dto\UserDto; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; use Freema\ReactAdminApiBundle\CreateTrait; use Freema\ReactAdminApiBundle\DeleteTrait; use Freema\ReactAdminApiBundle\Dto\AdminApiDto; use Freema\ReactAdminApiBundle\Interface\AdminEntityInterface; use Freema\ReactAdminApiBundle\Interface\DataRepositoryCreateInterface; use Freema\ReactAdminApiBundle\Interface\DataRepositoryDeleteInterface; use Freema\ReactAdminApiBundle\Interface\DataRepositoryFindInterface; use Freema\ReactAdminApiBundle\Interface\DataRepositoryListInterface; use Freema\ReactAdminApiBundle\Interface\DataRepositoryUpdateInterface; use Freema\ReactAdminApiBundle\ListTrait; use Freema\ReactAdminApiBundle\UpdateTrait; class UserRepository extends ServiceEntityRepository implements DataRepositoryListInterface, // for GET /api/users DataRepositoryFindInterface, // for GET /api/users/{id} DataRepositoryCreateInterface, // for POST /api/users DataRepositoryUpdateInterface, // for PUT /api/users/{id} DataRepositoryDeleteInterface // for DELETE /api/users/{id} { use ListTrait; // implements list() method with pagination, sorting, filtering use CreateTrait; // implements create() method use UpdateTrait; // implements update() method use DeleteTrait; // implements delete() and deleteMany() methods public function __construct(ManagerRegistry $registry) { parent::__construct($registry, User::class); } /** * Fields for full-text search */ public function getFullSearchFields(): array { return ['name', 'email']; } /** * Find entity and return as DTO */ public function findWithDto($id): ?AdminApiDto { $user = $this->find($id); return $user ? UserDto::createFromEntity($user) : null; } /** * Map entity to DTO (used by traits) */ public static function mapToDto(AdminEntityInterface $entity): AdminApiDto { return UserDto::createFromEntity($entity); } /** * Create entities from DTO (used by CreateTrait) */ public function createEntitiesFromDto(AdminApiDto $dto): array { if (!$dto instanceof UserDto) { throw new \InvalidArgumentException('DTO must be instance of UserDto'); } $user = new User(); $user->setName($dto->name); $user->setEmail($dto->email); $this->getEntityManager()->persist($user); return [$user]; } /** * Update entity from DTO (used by UpdateTrait) */ public function updateEntityFromDto(AdminEntityInterface $entity, AdminApiDto $dto): AdminEntityInterface { if (!$entity instanceof User) { throw new \InvalidArgumentException('Entity must be instance of User'); } if (!$dto instanceof UserDto) { throw new \InvalidArgumentException('DTO must be instance of UserDto'); } $entity->setName($dto->name); $entity->setEmail($dto->email); return $entity; } }
Generated Endpoints
After configuration, the bundle automatically creates these endpoints:
| Method | URL | Description |
|---|---|---|
| GET | /api/users |
List users with pagination, sorting, filtering |
| GET | /api/users/{id} |
User detail |
| POST | /api/users |
Create new user |
| PUT | /api/users/{id} |
Update user |
| DELETE | /api/users/{id} |
Delete user |
| DELETE | /api/users |
Bulk delete (with filter) |
Request/Response Examples
GET /api/users?page=1&perPage=10&sort=name&order=ASC
{
"data": [
{"id": 1, "name": "John Doe", "email": "john@example.com"},
{"id": 2, "name": "Jane Smith", "email": "jane@example.com"}
],
"total": 25
}
POST /api/users
Request:
{"name": "New User", "email": "new@example.com"}
Response:
{"id": 3, "name": "New User", "email": "new@example.com"}
Development Mode
A dev application is prepared for testing in the dev/ directory:
# Run via docker task dev:up # Or locally cd dev && php index.php
The dev application uses:
- In-memory SQLite (fast testing)
- Automatic database initialization with test data
- Minimal configuration
Advanced Features
Related Resources
react_admin_api: resources: users: dto_class: 'App\Dto\UserDto' related_resources: posts: dto_class: 'App\Dto\PostDto' relationship_method: 'getPosts'
Generates endpoint: GET /api/users/{id}/posts
Custom Repository
If you need custom repository logic, just implement the required interfaces:
class CustomUserRepository implements DataRepositoryListInterface { public function list(ListDataRequest $request): ListDataResult { // Your custom logic } }
Testing
The bundle contains a complete test suite in the tests/ directory:
composer test # PHPUnit tests composer test:php # PHP syntax check composer lint # Code style check
Supported Versions
- PHP 8.2+
- Symfony 6.4+ / 7.1+
- Doctrine ORM 2.14+
License
MIT License
Contributing
Contributions are welcome! Please create an issue or pull request on GitHub.