ac/web-services-bundle
Symfony bundle providing generic REST API workflow tools: request lifecycle events, JMS-based deserialization into existing objects, validation error handling, configurable response formats (JSON/XML/JSONP/YML), and per-path settings for exceptions, response data, JSONP, and headers.
Installation:
composer require ac/web-services-bundle:~0.2.0
Enable the bundle in AppKernel.php:
new AC\WebServicesBundle\ACWebServicesBundle(),
Basic Configuration (app/config/config.yml):
ac_web_services:
default_format: json # or xml, jsonp, yml
include_response_data: true
First Use Case: Create a controller to handle a simple API endpoint:
use AC\WebServicesBundle\Event\ApiEvent;
use Symfony\Component\HttpFoundation\Request;
class ApiController extends Controller
{
public function indexAction(Request $request)
{
$event = new ApiEvent($request, $this->get('request_stack'));
$this->get('event_dispatcher')->dispatch('api.request', $event);
// Your logic here
return $this->get('ac_web_services.response_factory')->createResponse(
['data' => 'Hello, API!'],
200
);
}
}
Leverage the request lifecycle events to centralize API logic:
// In a service or controller
$event = new ApiEvent($request, $this->get('request_stack'));
$this->get('event_dispatcher')->dispatch('api.request', $event);
// Listen to events in a service
public function onApiRequest(ApiEvent $event)
{
$event->setData(['preprocessed' => true]);
}
Register listeners in services.yml:
services:
app.api_listener:
class: AppBundle\EventListener\ApiListener
tags:
- { name: kernel.event_listener, event: api.request, method: onApiRequest }
Use the object deserializer to map incoming JSON/XML to entities:
use AC\WebServicesBundle\Serializer\ObjectDeserializer;
// In a controller or service
$deserializer = $this->get('ac_web_services.object_deserializer');
$entity = $deserializer->deserialize($request->getContent(), 'AppBundle\Entity\User', 'json');
Configure JMS Serializer (config.yml):
jms_serializer:
metadata:
directories:
AppBundle: %kernel.root_dir%/Resources/config/serializer
Convert Symfony validator errors into API-friendly responses:
use AC\WebServicesBundle\Validator\ErrorMapper;
$validator = $this->get('validator');
$errors = $validator->validate($entity);
$errorMapper = $this->get('ac_web_services.error_mapper');
$response = $errorMapper->mapErrors($errors);
Extend the response factory for consistent API responses:
// Override the default response factory (e.g., in a compiler pass)
public function createResponse($data, $status = 200, array $headers = [])
{
$response = parent::createResponse($data, $status, $headers);
$response->headers->set('X-API-Version', '1.0');
return $response;
}
Deprecated Bundle:
JMS Serializer Dependency:
jms/serializer-bundle (not included by default). Add it manually:
composer require jms/serializer-bundle
Event Dispatching:
api.request are not standard Symfony events. Document them in your codebase to avoid confusion.Response Formats:
default_format config is case-sensitive (json, not JSON).Event Debugging:
public function onApiRequest(ApiEvent $event)
{
var_dump($event->getData());
}
Deserialization Issues:
.yml/.xml) for typos or missing properties.jms_serializer:
debug: %kernel.debug%
Response Headers:
Accept header:
$response->setPublic();
$response->setMaxAge(3600);
Custom Response Formats:
AC\WebServicesBundle\Response\ResponseFactory class to add support for new formats (e.g., GraphQL).Event Subscribers:
class GlobalApiSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return ['api.request' => 'onRequest'];
}
public function onRequest(ApiEvent $event)
{
$event->addData(['timestamp' => time()]);
}
}
Validation Groups:
@Groups to control deserialization:
# config/serializer/User.yml
AppBundle\Entity\User:
properties:
email:
groups: [registration]
$entity = $deserializer->deserialize($data, 'AppBundle\Entity\User', 'json', ['groups' => ['registration']]);
How can I help you explore Laravel packages today?