gl3n/serialization-group-bundle
A Symfony bundle that simplifies serialization groups, letting you control which object properties are exposed in different contexts. Define groups once and reuse them across API responses and other serialized output.
gl3n/serialization-group-bundle predates Symfony Flex, so setup follows the classic Symfony 2/3 bundle workflow. Treat the README and the bundle's DependencyInjection/Configuration.php as your source of truth for exact config keys before writing YAML — the package has a single small surface area, and the config tree is the fastest way to see what it actually accepts.
composer require gl3n/serialization-group-bundle:^1.0
app/AppKernel.php (there is no Flex recipe):
new Gl3n\SerializationGroupBundle\SerializationGroupBundle(),
php app/console debug:container | grep -i serialization
Read Configuration.php to confirm the root key name and whether groups are defined as flat lists, nested sets, or per-class mappings.api.list, api.detail) once in config, then resolve those groups into your serialization context instead of scattering group strings across controllers. This is the core value proposition — one config-defined vocabulary of groups shared by every endpoint.A minimal conceptual flow:
# config.yml — verify keys against the bundle's Configuration.php
gl3n_serialization_group:
groups:
api_list:
- user_summary
- post_summary
api_detail:
- user_details
- post_details
- comment_details
Then in a controller or service, ask the bundle for the resolved groups and hand them to your serializer.
Centralise group vocabulary, resolve at the edge. The bundle is most useful when group composition lives in config and controllers only reference a logical name. Keep the translation from logical name → serializer group array in one place (the bundle service) so a change to "what api_detail means" is a single config edit.
Wire into JMS Serializer explicitly. Most real-world use in 2016 was JMS Serializer contexts:
$groups = $this->get('gl3n_serialization_group.resolver')->getGroups('api_detail');
return $this->get('jms_serializer')->serialize(
$entity,
'json',
SerializationContext::create()->setGroups($groups)
);
Same pattern works with Symfony's Serializer (for AbstractNormalizer::GROUPS), which is the safer choice today given that JMS Serializer has moved on considerably since 2016:
$json = $this->get('serializer')->serialize($entity, 'json', [
AbstractNormalizer::GROUPS => $groups,
]);
Build a thin wrapper service. Rather than injecting the bundle's resolver everywhere, wrap it:
class GroupProvider
{
public function __construct(private $resolver) {}
public function forContext(string $context): array
{
return $this->resolver->getGroups($context);
}
}
This gives you one seam to swap in your own logic if the bundle stops working on a newer Symfony.
Per-action selection. A common workflow is mapping controller actions or route names to a logical group set, then resolving once in a listener or base controller. Keep the mapping explicit — config-driven magic here gets hard to trace.
Compose base + specific. If the package supports merging group lists, define a base set and layer endpoint-specific sets on top; otherwise merge the arrays yourself before calling the resolver.
Test the resolved groups, not the bundle. Write a unit test asserting GroupProvider::forContext('api_detail') returns ['user_details', 'post_details', 'comment_details']. This is the piece of behaviour you actually depend on, and it protects you when/if you replace the bundle.
AppKernel.php (or bundles.php on Symfony 4+, where the class may still work but the service definitions may not load cleanly).cache:clear after every config change. Container-compiled bundles often bake group definitions into the compiled container; stale YAML edits are a frequent "why isn't my change applying" cause. debug:container --parameter on the bundle's parameters can confirm what was actually compiled.user_details group can expose emails or hashes. Review the resolved groups in tests rather than trusting config intent.max_depth / circular reference handlers. Expect surprises when a group pulls in a relation that itself references back.DependencyInjection/Gl3nSerializationGroupExtension.php) and the Configuration class — you can override the service definition or decorate the resolver in your own bundle. There is no plugin/event system worth relying on.debug:container gl3n (or grep for serialization_group) to find the actual service IDs, then dump getGroups() output in a small command before wiring it into controllers. If the service isn't there, the bundle didn't register — check bundle registration and that the extension alias matches the config root key.#[Groups] attributes, or a maintained alternative is a contained change rather than a codebase-wide refactor.How can I help you explore Laravel packages today?