## Getting Started
### Minimal Setup for Laravel Integration
Since this bundle is Symfony2-based, Laravel developers must adapt it via **Symfony Bridge** or **standalone usage**. Start by:
1. **Install Dependencies**
```bash
composer require symfony/framework-bundle nelmio/api-doc-bundle jms/serializer-bundle
composer require doctrine/orm doctrine/doctrine-bundle # If using Doctrine
Configure Kernel (Laravel Equivalent: bootstrap/app.php)
Replace Laravel’s service provider registration with Symfony’s kernel setup:
$kernel = new Symfony\Component\HttpKernel\Kernel(
'dev', // Environment
false // Debug mode
);
$kernel->boot();
$request = Symfony\Component\HttpFoundation\Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Define API Resources in config/config.yml (Laravel: config/api-resources.php)
tch_api_resource:
resources:
user:
entity: App\Models\User
actions: [C, R, U, D, S] # CRUD + Search
post:
entity: App\Models\Post
actions: [R, S]
Route Configuration (Laravel: routes/api.php)
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\RouteCollection;
$loader = new YamlFileLoader();
$collection = $loader->load(__DIR__.'/config/routing.yml');
$router = new Symfony\Component\Routing\Router($collection, $kernel->getEnvironment());
First Use Case: Generate API Docs
Access /api/doc to see auto-generated Swagger/OpenAPI docs for configured resources.
Use TraitTCHRepository to extend Doctrine repositories with API-specific methods:
// app/Repositories/UserRepository.php
namespace App\Repositories;
use TCH\ApiResourceBundle\Util\TraitTCHRepository;
class UserRepository extends \Doctrine\ORM\EntityRepository
{
use TraitTCHRepository;
// Auto-implemented: find(), findAll(), search(), create(), update(), delete()
}
Workflow:
create()) in controllers.search() with query params (e.g., ?q=email:test@example.com).Create controllers to handle API logic:
// app/Http/Controllers/API/UserController.php
namespace App\Http\Controllers\API;
use App\Repositories\UserRepository;
use Symfony\Component\HttpFoundation\Request;
class UserController extends AbstractController
{
private $repository;
public function __construct(UserRepository $repository)
{
$this->repository = $repository;
}
public function index(Request $request)
{
return $this->repository->findAll($request->query->all());
}
public function store(Request $request)
{
return $this->repository->create($request->request->all());
}
}
Patterns:
UserRepository (or any entity repository).$request->query or $request->request to trait methods.config/packages/jms_serializer.yaml).Extend beyond CRUD by adding custom methods to repositories:
// app/Repositories/UserRepository.php
public function getActiveUsers()
{
return $this->createQueryBuilder('u')
->where('u.isActive = :active')
->setParameter('active', true)
->getQuery()
->getResult();
}
Route it in config/routing.yml:
tch_api_resource_user_active:
path: /api/v1/users/active
defaults: { _controller: App\Controller\API\UserController::activeUsers }
methods: GET
Use Symfony’s Validator component for request validation:
# config/validator/validation.yml
App\Models\User:
properties:
email:
- Email: ~
password:
- NotBlank: ~
- Length: { min: 8 }
Controller Usage:
public function store(Request $request)
{
$validator = $this->get('validator');
$errors = $validator->validate($request->request->all());
if (count($errors) > 0) {
return new JsonResponse(['errors' => (string) $errors], 400);
}
return $this->repository->create($request->request->all());
}
Kernel must be booted before handling requests. Avoid mixing Laravel’s service container with Symfony’s directly./api/v1/) to avoid clashes with Laravel’s default routes.$this->get('service_id')) or bridge it with Laravel’s via SymfonyBridge.NelmioApiDocBundle is properly configured in config/packages/nelmio_api_doc.yaml:
nelmio_api_doc:
routes:
prefix: /api/doc
areas: # to filter documented controllers
default:
path_patterns:
- ^/api/v1
config/packages/jms_serializer.yaml:
jms_serializer:
metadata:
directories:
- %kernel.project_dir%/config/serializer
Create custom metadata files (e.g., config/serializer/App.Models.User.yml) for complex types.findAll() with limit and offset params:
$users = $this->repository->findAll([
'limit' => 10,
'offset' => 0,
'sort' => ['id' => 'DESC']
]);
public function search(array $params)
{
// Custom search logic
return $this->createQueryBuilder('u')
->where('u.name LIKE :name')
->setParameter('name', '%'.$params['q'].'%')
->getQuery()
->getResult();
}
// src/EventListener/UserListener.php
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class UserListener
{
public function onKernelController(FilterControllerEvent $event)
{
$request = $event->getRequest();
if ($request->getPathInfo() === '/api/v1/users') {
// Modify request/response here
}
}
}
Register in config/services.yaml:
services:
App\EventListener\UserListener:
tags:
- { name: kernel.event_listener, event: kernel.controller }
entity in config.yml matches the fully qualified namespace (e.g., App\Models\User).security:
access_control:
- { path: ^/api/v1, roles: IS_AUTHENTICATED_ANONYMOUSLY }
WebTestCase:
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class UserAPITest extends WebTestCase
{
public function testCreateUser()
{
$client = static::createClient();
$client->request('POST', '/api/v1/users', [
'json' => ['name' => 'John', 'email' => 'john@example.com']
]);
$this->assertEquals(201, $client->getResponse()->getStatusCode());
}
}
use PHPUnit\Framework\TestCase;
class UserRepositoryTest extends TestCase
{
public function testSearch()
{
$repo = $this->getMockBuilder(UserRepository::class)
->onlyMethods(['createQueryBuilder'])
->getMock();
$repo->expects($this->once())
->method('createQueryBuilder')
->with('u')
->willReturn
How can I help you explore Laravel packages today?