Installation:
composer require bu/json-response-bundle dev-master
Add to AppKernel.php:
new Bu\JsonResponseBundle\BuJsonResponseBundle(),
Enable PHP Templating:
Update config.yml:
framework:
templating:
engines: ['twig', 'php']
First Use Case:
Create a PHP template (e.g., src/Application/MyBundle/Resources/views/Product/list.json.php):
<?php
return [
'products' => $products,
'count' => count($products),
'meta' => ['timestamp' => time()]
];
Annotate your controller:
use Bu\JsonResponseBundle\Configuration\JsonResponseTemplate;
class ProductController extends Controller
{
/**
* @JsonResponseTemplate("Product/list")
*/
public function listAction()
{
$products = $this->getDoctrine()->getRepository('ApplicationMyBundle:Product')->findAll();
return $products; // Data passed to template
}
}
Template Inheritance: Use PHP templates to modularize JSON responses. Example:
// Base template (src/Application/MyBundle/Resources/views/Base/base.json.php)
<?php return ['@base' => $data]; ?>
// Child template (src/Application/MyBundle/Resources/views/Product/list.json.php)
<?php
$baseData = include __DIR__.'/../../Base/base.json.php';
return array_merge($baseData, [
'products' => $products
]);
Dynamic Template Selection: Pass template names dynamically via annotation:
/**
* @JsonResponseTemplate("%template%", options={"template": $templateName})
*/
public function dynamicAction($templateName)
{
return ['data' => 'example'];
}
Integration with SensioFrameworkExtraBundle:
Combine with @Template for mixed HTML/JSON responses:
/**
* @Route("/product/{id}", name="product_show")
* @Template("@ApplicationMyBundle/Product/show.html.twig")
* @JsonResponseTemplate("@ApplicationMyBundle/Product/show.json", options={"format": "json"})
*/
public function showAction($id)
{
return ['product' => $this->findProduct($id)];
}
Data Transformation: Use templates to transform data before JSON serialization:
// src/Application/MyBundle/Resources/views/Product/transform.json.php
<?php
return array_map(function($product) {
return [
'id' => $product->getId(),
'name' => $product->getName(),
'price' => (float) $product->getPrice()
];
}, $products);
API Development:
src/Application/MyBundle/Resources/views/API/Error/error.json.php for standardized error responses.Legacy System Integration:
Testing:
JsonResponseTemplate annotation processor.Template Caching:
PHP templates are not cached by default. Use php engine configuration:
twig:
debug: false # Disable Twig debug to avoid caching issues
Annotation Conflicts:
@JsonResponseTemplate and @Template cannot coexist on the same method. Use separate actions or middleware to route based on Accept header.
Data Serialization:
PHP templates return raw arrays. Ensure all data is JSON-serializable (e.g., avoid DateTime objects without conversion):
// Fix: Convert DateTime to string
<?php return ['date' => $product->getCreatedAt()->format('Y-m-d')]; ?>
Performance: Avoid complex logic in templates. Offload heavy processing to controllers or services.
Template Not Found:
Verify the template path follows Symfony’s naming conventions:
Bundle/Controller/Action/template.json.php → Bundle/Resources/views/Controller/Action/template.json.php.
Annotation Ignored:
Ensure SensioFrameworkExtraBundle is installed and registered before BuJsonResponseBundle.
Circular References:
Use json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) in templates to handle circular references gracefully.
Reuse Logic:
Create helper templates (e.g., src/Application/MyBundle/Resources/views/Helpers/pagination.json.php) for common patterns like pagination.
Validation: Validate template output with JSON Schema in a post-response event listener:
$this->get('validator')->validate($jsonResponse, new \Symfony\Component\Validator\Constraints\Json());
Extending the Bundle:
Override the JsonResponseTemplateListener to add custom logic:
// src/Application/MyBundle/EventListener/CustomJsonListener.php
use Bu\JsonResponseBundle\EventListener\JsonResponseTemplateListener;
class CustomJsonListener extends JsonResponseTemplateListener
{
protected function getTemplate($template, array $options)
{
// Custom logic here
return parent::getTemplate($template, $options);
}
}
Register in services.yml:
services:
application.my_bundle.json_listener:
class: Application\MyBundle\EventListener\CustomJsonListener
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
Documentation: Add PHPDoc comments to templates for IDE autocompletion:
/**
* @param array $products List of Product entities
* @return array JSON-serializable product data
*/
<?php return array_map([$this, 'transformProduct'], $products); ?>
How can I help you explore Laravel packages today?