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

Templated Uri Bundle Laravel Package

ibexa/templated-uri-bundle

Symfony bundle providing an RFC-6570 (URI Template) compatible router and URL generator via hautelook/TemplatedUriRouter. Exposes a templated router service to generate links like /demo?{&page}{&sort*}{&filter*} from route params.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ibexa/templated-uri-bundle
    

    For Symfony Flex, the bundle auto-registers in config/bundles.php. For older Symfony versions, add to AppKernel.php:

    new Hautelook\TemplatedUriBundle\HautelookTemplatedUriBundle(),
    
  2. First Use Case: Generate a templated URI for a route named app_homepage with dynamic query parameters:

    $router = $this->get('hautelook.router.template');
    $uri = $router->generate('app_homepage', [
        'page' => '{page}',
        'sort' => ['{sort}'],
        'filter' => ['{filter}']
    ]);
    // Outputs: `/homepage?{&page}{&sort*}{&filter*}`
    
  3. Where to Look First:

    • Service Name: hautelook.router.template (injected via autowiring or container).
    • Route Configuration: Ensure routes are defined in config/routes.yaml with _templated_uri: true if custom behavior is needed.
    • Documentation: TemplatedUriRouter for RFC-6570 syntax (e.g., {&page}, {+path}).

Implementation Patterns

Usage Patterns

  1. Basic URI Generation:

    // In a controller or service
    $uri = $this->router->generate('route_name', [
        'query' => '{query}',
        'page'  => ['{page}']
    ]);
    // Output: `/route?{&query}{&page}`
    
  2. Dynamic Query Parameters:

    • Use arrays for multiple values (expands to ?key=val1&key=val2):
      $uri = $this->router->generate('products', [
          'filter' => ['category={category}', 'price={price}']
      ]);
      // Output: `/products?filter=category={category}&filter=price={price}`
      
    • Use RFC-6570 modifiers:
      • {&param}: Preserves existing params (e.g., /search?{&query}).
      • {+param}: Appends to path (e.g., /base/{+id}/base/123).
      • *: Repeats for arrays (e.g., {sort*}?sort=asc&sort=desc).
  3. Integration with Symfony Router:

    • Named Routes: Works with Symfony’s named routes (e.g., app_product_show).
    • Route Collections: Combine with Symfony’s RouterInterface for hybrid routing:
      $symfonyUri = $this->router->generate('symfony_route');
      $templatedUri = $this->templatedRouter->generate('templated_route');
      
  4. HATEOAS Integration:

    • Use with BazingaHateoasBundle to generate templated links in API responses:
      use Bazinga\Hateoas\Generator\UrlGenerator;
      $link = $this->hateoasUrlGenerator->generate('route_name', [
          'page' => '{page}'
      ]);
      
  5. Twig Integration:

    • Pass the router to Twig templates:
      {% set uri = app.service('hautelook.router.template').generate('route_name', {'page': '{page}'}) %}
      <a href="{{ uri }}">Link</a>
      

Workflows

  1. API Pagination:

    • Generate templated URIs for pagination controls:
      $nextPageUri = $this->router->generate('api_products', [
          'page' => '{page=2}' // Defaults to 2 if not provided
      ]);
      
  2. Filterable Lists:

    • Create URIs for dynamic filtering:
      $filteredUri = $this->router->generate('api_users', [
          'filter' => ['role={role}', 'status={status}']
      ]);
      
  3. Legacy URL Migration:

    • Replace hardcoded URLs in templates/services with templated versions:
      // Before
      $oldUrl = '/products?page=' . $page;
      
      // After
      $newUrl = $this->router->generate('api_products', ['page' => '{page}']);
      
  4. Conditional Templating:

    • Use ternary logic to switch between static and templated URIs:
      $uri = $useTemplate
          ? $this->router->generate('route_name', ['param' => '{param}'])
          : $this->router->generate('route_name', ['param' => $value]);
      

Integration Tips

  1. Route Configuration:

    • Define routes in config/routes.yaml with _templated_uri: true for custom behavior:
      api_products:
          path: /products
          defaults: { _controller: 'App\Controller\ProductController::index', _templated_uri: true }
      
  2. Dependency Injection:

    • Autowire the router in services/controllers:
      use Hautelook\TemplatedUriRouter\Router\RouterInterface;
      
      public function __construct(private RouterInterface $templatedRouter) {}
      
  3. Testing:

    • Test URI generation with PHPUnit:
      public function testUriGeneration()
      {
          $router = $this->get('hautelook.router.template');
          $uri = $router->generate('route_name', ['page' => '{page}']);
          $this->assertEquals('/route?{&page}', $uri);
      }
      
  4. Performance:

    • Cache generated URIs if used frequently (e.g., in loops):
      $cacheKey = 'uri_' . md5(serialize($params));
      $uri = $this->cache->get($cacheKey, function() use ($params) {
          return $this->router->generate('route_name', $params);
      });
      
  5. Validation:

    • Validate templates against RFC-6570 before use:
      use Hautelook\TemplatedUriRouter\Validator\Validator;
      
      $validator = new Validator();
      $isValid = $validator->validate($template);
      

Gotchas and Tips

Pitfalls

  1. Unclosed Braces:

    • Issue: Forgetting to close braces (e.g., {param) causes malformed URIs.
    • Fix: Use a linter or validator (e.g., Hautelook\TemplatedUriRouter\Validator).
  2. Reserved Characters:

    • Issue: Templates with &, =, or + may break if not escaped.
    • Fix: URL-encode dynamic values before templating:
      $encodedValue = urlencode($value);
      $uri = $this->router->generate('route', ['param' => '{' . $encodedValue . '}']);
      
  3. Symfony Router Conflict:

    • Issue: Mixing templated and static routes with the same name.
    • Fix: Ensure route names are unique and use _templated_uri only when needed.
  4. Array Expansion:

    • Issue: Arrays with non-string keys may not expand as expected.
    • Fix: Flatten arrays or use string keys:
      // Bad: ['{key}' => $value] (key may not be expanded)
      // Good: ['key' => '{value}']
      
  5. PHP Version:

    • Issue: The bundle may not support PHP 8.x features (e.g., named arguments).
    • Fix: Test with your PHP version or pin dependencies.
  6. Missing Dependencies:

    • Issue: preg functions are required but may be disabled in php.ini.
    • Fix: Ensure extension=php_pcre is enabled.

Debugging

  1. Invalid Templates:

    • Symptom: Blank or malformed URIs.
    • Debug:
      • Check for unclosed braces or invalid syntax.
      • Use var_dump($router->generate('route', $params)) to inspect output.
  2. Route Not Found:

    • Symptom: RouteNotFoundException.
    • Debug:
      • Verify the route name exists in config/routes.yaml.
      • Ensure the route is loaded (e.g., not in a skipped file).
  3. Parameter Expansion:

    • Symptom: Arrays not expanding correctly (e.g., {sort*} ignores values).
    • Debug:
      • Ensure parameters are passed as arrays:
        $uri = $router->generate('route', ['sort' => ['{asc}', '{desc}']]);
        
  4. Caching Issues:

    • Symptom: Stale URIs in production.
    • Debug:
      • Clear cache after deploying changes:
        php bin/console cache:clear
        
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor