To leverage easy-api-bundle in a Laravel project, follow these steps:
Install Symfony Components (Required) Since the bundle relies on Symfony’s ecosystem, install core components via Composer:
composer require symfony/http-kernel symfony/serializer symfony/form symfony/validator
Create a Laravel Service Provider Register the bundle and bridge Symfony configurations:
// app/Providers/EasyApiServiceProvider.php
namespace App\Providers;
use Citizen63000\EasyApiBundle\EasyApiBundle;
use Illuminate\Support\ServiceProvider;
class EasyApiServiceProvider extends ServiceProvider
{
public function register()
{
// Override Symfony's container with Laravel's DI
$this->app->bind('easy_api.config', function () {
return [
'authentication' => true,
'user_class' => \App\Models\User::class,
'inheritance' => [
'entity' => \App\Models\AbstractEntity::class,
],
];
});
}
public function boot()
{
// Load the bundle (if using a wrapper)
if ($this->app->has('kernel')) {
$this->app['kernel']->registerBundle(new EasyApiBundle());
}
}
}
Register the provider in config/app.php:
'providers' => [
// ...
App\Providers\EasyApiServiceProvider::class,
],
Create a CRUD Controller
Extend AbstractApiController (Symfony) or create a Laravel-compatible wrapper:
// app/Http/Controllers/Api/UserCrudController.php
namespace App\Http\Controllers\Api;
use App\Models\User;
use Citizen63000\EasyApiBundle\Controller\AbstractApiController;
use Citizen63000\EasyApiBundle\Traits\CrudControllerTrait;
class UserCrudController extends AbstractApiController
{
public const entityClass = User::class;
public const entityCreateTypeClass = \App\Form\UserType::class;
public const serializationGroups = ['user:read'];
public const listSerializationGroups = ['user:list'];
use CrudControllerTrait;
}
Define Routes
Use Laravel’s routing system with annotations (via doctrine/annotations):
// routes/api.php
use Doctrine\Common\Annotations\AnnotationRegistry;
use Citizen63000\EasyApiBundle\Annotation\Route;
AnnotationRegistry::registerLoader('class_exists');
Route::get('/users', [UserCrudController::class, 'listAction']);
Route::post('/users', [UserCrudController::class, 'createAction']);
Configure Serialization
Set up Symfony’s serializer in config/services.php:
'serializer' => [
'groups' => [
'user:read' => ['id', 'name', 'email'],
'user:list' => ['id', 'name'],
],
],
First API Call Test the endpoint:
curl -X GET http://your-app.test/api/users
Entity Setup Define a Laravel Eloquent model with serialization groups:
// app/Models/User.php
namespace App\Models;
use Symfony\Component\Serializer\Annotation\Groups;
class User
{
/**
* @Groups({"user:read"})
*/
public $id;
/**
* @Groups({"user:read", "user:list"})
*/
public $name;
/**
* @Groups({"user:read"})
*/
public $email;
}
Form Type Configuration Create a Symfony form type for input validation:
// app/Form/UserType.php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class)
->add('email', TextType::class);
}
}
Controller Inheritance Extend the base controller for shared logic:
// app/Http/Controllers/Api/BaseCrudController.php
namespace App\Http\Controllers\Api;
use Citizen63000\EasyApiBundle\Controller\AbstractApiController;
use Citizen63000\EasyApiBundle\Traits\CrudControllerTrait;
abstract class BaseCrudController extends AbstractApiController
{
use CrudControllerTrait;
protected $inheritance = [
'entity' => \App\Models\AbstractEntity::class,
];
}
Custom Actions Override methods for bespoke logic:
// app/Http/Controllers/Api/UserCrudController.php
class UserCrudController extends BaseCrudController
{
public const entityClass = User::class;
public const entityCreateTypeClass = UserType::class;
public function customAction()
{
return response()->json(['custom' => 'data']);
}
}
Routing with Annotations Use NelmioApiDoc annotations for OpenAPI docs:
/**
* @Route("/users/custom", name="users_custom", methods={"GET"})
* @OA\Get(
* path="/users/custom",
* tags={"Users"},
* summary="Custom user endpoint",
* @OA\Response(response=200, description="Custom response")
* )
*/
public function customAction()
{
// ...
}
Filtering and Sorting Configure dynamic query parameters:
class UserCrudController extends BaseCrudController
{
public const filterFields = ['name', 'email'];
public const filterSortFields = ['name', 'created_at'];
}
Access filters in the controller:
public function listAction(Request $request)
{
$filters = $request->query->all();
$query = $this->getEntityRepository()->createQueryBuilder('u');
if (isset($filters['name'])) {
$query->andWhere('u.name LIKE :name')->setParameter('name', "%{$filters['name']}%");
}
return $this->handleList($query->getQuery()->getResult());
}
Hybrid Serialization
Combine Laravel’s API Resources with Symfony’s serializer:
// app/Http/Resources/UserResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use Symfony\Component\Serializer\Annotation\Groups;
class UserResource extends JsonResource
{
/**
* @Groups({"user:read"})
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
];
}
}
Authentication Bridge
Integrate Laravel’s auth with Symfony’s UserInterface:
// app/Models/User.php
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
public function getRoles()
{
return ['ROLE_USER'];
}
public function getPassword()
{
return $this->password;
}
}
Testing with Pest Extend Laravel’s testing tools:
// tests/Feature/UserCrudTest.php
namespace Tests\Feature;
use App\Models\User;
use Citizen63000\EasyApiBundle\Tests\AbstractApiTestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserCrudTest extends AbstractApiTestCase
{
use RefreshDatabase;
public function test_list_users()
{
User::factory()->create();
$response = $this->getJson('/api/users');
$response->assertStatus(200)
->assertJsonStructure(['data' => [[
'id', 'name', 'email'
]]]);
}
}
Performance Optimization Cache serialized data:
// app/Providers/AppServiceProvider.php
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(CacheableSupportsMethodInterface::class, function () {
return new class implements CacheableSupportsMethodInterface {
public function supportsCacheableNormalization($data, $format, array $context = [])
{
return true;
}
};
});
}
}
How can I help you explore Laravel packages today?