Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Hal Laravel Package

api-platform/hal

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require api-platform/hal
    

    Add the ApiPlatform\Hal\Serializer\ContextBuilder to your serializer context builders in config/services.php:

    'serializer' => [
        'context_builders' => [
            // ...
            ApiPlatform\Hal\Serializer\ContextBuilder::class,
        ],
    ],
    
  2. First Use Case Use the HAL serializer in a controller or API resource to return HAL-formatted responses:

    use ApiPlatform\Hal\Serializer\ContextBuilder;
    use Symfony\Component\Serializer\SerializerInterface;
    
    class PostController extends AbstractController
    {
        public function __invoke(SerializerInterface $serializer, ContextBuilder $contextBuilder)
        {
            $data = ['id' => 1, 'title' => 'Hello HAL'];
            $context = $contextBuilder->createSerializationContext([]);
    
            return new JsonResponse(
                $serializer->serialize($data, 'jsonhal', $context)
            );
        }
    }
    
  3. Where to Look First

    • HAL Specification for format understanding.
    • ApiPlatform\Hal\Serializer\ContextBuilder for context configuration.
    • ApiPlatform\Hal\Serializer\Normalizer\HalNormalizer for customization.

Implementation Patterns

Usage Patterns

  1. Embedding Resources Use the embedded key in the context to include related resources:

    $context = $contextBuilder->createSerializationContext([
        'groups' => ['post:read'],
        'embedded' => ['author', 'comments'],
    ]);
    
  2. Custom Links Add custom links via the links key in the context:

    $context = $contextBuilder->createSerializationContext([
        'links' => [
            'self' => ['href' => '/api/posts/1'],
            'custom' => ['href' => '/api/posts/1/related'],
        ],
    ]);
    
  3. Partial Serialization Leverage Symfony’s serializer groups for partial data:

    // In your entity
    #[Groups(['post:read'])]
    private $title;
    
    #[Groups(['post:write'])]
    private $content;
    
    // In the context
    $context = $contextBuilder->createSerializationContext(['groups' => ['post:read']]);
    
  4. Integration with API Platform If using API Platform, the HAL format is enabled by default for jsonhal format. Customize via:

    # config/api_platform/resources.yaml
    resources:
        App\Entity\Post:
            collectionOperations:
                get:
                    normalization_context:
                        groups: ['post:read']
                        embedded: ['author']
    

Workflows

  1. Request-Response Cycle

    • Use ContextBuilder to dynamically adjust serialization based on request attributes (e.g., Accept header).
    • Example middleware to set context:
      public function onKernelRequest(RequestEvent $event)
      {
          $request = $event->getRequest();
          $contextBuilder = $this->container->get(ContextBuilder::class);
          $context = $contextBuilder->createSerializationContext([
              'format' => $request->getRequestFormat(),
          ]);
          $request->attributes->set('serialization_context', $context);
      }
      
  2. Testing Mock the ContextBuilder and SerializerInterface in tests:

    $contextBuilder = $this->createMock(ContextBuilder::class);
    $contextBuilder->method('createSerializationContext')->willReturn([]);
    
    $serializer = $this->createMock(SerializerInterface::class);
    $serializer->expects($this->once())
        ->method('serialize')
        ->with($data, 'jsonhal', $context);
    

Gotchas and Tips

Pitfalls

  1. Context Overrides

    • The ContextBuilder merges contexts. Ensure explicit overrides in your code don’t conflict with defaults:
      // Bad: Overrides all links
      $context = $contextBuilder->createSerializationContext(['links' => []]);
      
      // Good: Preserves defaults while adding custom links
      $context = $contextBuilder->createSerializationContext([
          'links' => ['custom' => ['href' => '/custom']],
      ]);
      
  2. Circular References

    • HAL normalizer may fail on circular references (e.g., PostAuthor). Use ignore_circular_references:
      $context = $contextBuilder->createSerializationContext([
          'ignore_circular_references' => true,
      ]);
      
  3. Performance

    • Avoid deep embedding in high-traffic APIs. Use lazy-loading or pagination for related resources.

Debugging

  1. Inspect Context Dump the context to debug serialization issues:

    $context = $contextBuilder->createSerializationContext([]);
    dump($context); // Inspect keys like 'groups', 'embedded', etc.
    
  2. Normalizer Order If HAL output is unexpected, check the normalizer order in config/packages/api_platform.yaml:

    api_platform:
        formats:
            jsonhal:
                mime_types: ['application/hal+json']
                serializer_normalizer: 'api_platform.hal_serializer.normalizer.hal'
    
  3. Custom Normalizers Extend HalNormalizer for custom logic:

    use ApiPlatform\Hal\Serializer\Normalizer\HalNormalizer;
    
    class CustomHalNormalizer extends HalNormalizer
    {
        public function normalize($object, $format, array $context = [])
        {
            $data = parent::normalize($object, $format, $context);
            $data['_custom'] = 'value'; // Add custom key
            return $data;
        }
    }
    

    Register it in config/services.yaml:

    services:
        App\Serializer\Normalizer\CustomHalNormalizer:
            tags: [serializer.normalizer]
            arguments:
                - 'jsonhal'
            decorates: 'api_platform.hal_serializer.normalizer.hal'
    

Extension Points

  1. Dynamic Links Create a custom context builder to inject dynamic links:

    use ApiPlatform\Hal\Serializer\ContextBuilder as BaseContextBuilder;
    
    class DynamicContextBuilder extends BaseContextBuilder
    {
        public function createSerializationContext(array $context = [])
        {
            $context['links']['dynamic'] = [
                'href' => route('dynamic.route', ['id' => 123]),
            ];
            return parent::createSerializationContext($context);
        }
    }
    
  2. Custom HAL Metadata Extend the HAL structure by overriding the normalizer’s normalize method (as shown above) or by using a custom metadata factory.

  3. Integration with API Platform Override the default HAL format in API Platform’s configuration to add custom logic:

    api_platform:
        formats:
            jsonhal:
                mime_types: ['application/hal+json']
                serializer_normalizer: 'App\Serializer\Normalizer\CustomHalNormalizer'
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver