Installation
composer require becklyn/javascript-routing
Add to config/bundles.php:
return [
// ...
Becklyn\JavaScriptRoutingBundle\BecklynJavaScriptRoutingBundle::class => ['all' => true],
];
Enable Routing Endpoint
Import the routes in config/routes.yaml:
_import.becklyn_javascript_routing:
resource: '@BecklynJavaScriptRoutingBundle/Resources/config/routes.yaml'
prefix: /_v/routing
(Default prefix: /_v/routing)
First Use Case Fetch routes in JavaScript:
fetch('/_v/routing')
.then(response => response.json())
.then(routes => console.log(routes));
Outputs a structured array of Symfony routes with metadata (e.g., paths, methods, requirements).
Frontend Routing Integration
const route = routes.find(r => r.path === '/dashboard');
document.getElementById('dashboard-link').href = route.path;
Conditional Route Loading
requirements or defaults):
const activeRoutes = routes.filter(r =>
r.requirements.user_role === 'admin' ||
r.path === window.location.pathname
);
Route-Based Feature Flags
if (routes.some(r => r.path === '/admin')) {
document.getElementById('admin-panel').style.display = 'block';
}
Cache the Response
Cache the /_v/routing endpoint (e.g., with Symfony’s HTTP cache) to avoid repeated requests:
# config/packages/framework.yaml
framework:
http_cache:
cache_control:
rules:
- path: ^/_v/routing
max_age: 3600 # Cache for 1 hour
Extend Route Data
Add custom metadata to routes via Symfony’s Route object:
# config/routes.yaml
app_home:
path: /
controller: App\Controller\HomeController::index
becklyn_js_routing:
data:
priority: high # Custom field for JS logic
Versioning
Use the _v prefix to version routes (e.g., /_v/2/routing) and update incrementally.
Route Name vs. Path Conflicts
// Avoid: routes.find(r => r.name === 'app_home') // ❌ Uses names (not exposed)
// Use: routes.find(r => r.path === '/') // ✅ Uses paths
Sensitive Route Exposure
requirements:
app_admin:
path: /admin
requirements:
_js_access: 'true' # Filter in JS: r.requirements._js_access === 'true'
Dynamic Routes
{id}) are preserved but may break JS parsing. Sanitize paths if needed:
const safePath = route.path.replace(/\{.*?\}/g, '[dynamic]');
Verify Endpoint Check the endpoint returns expected data:
curl http://localhost/_v/routing | jq
Should output:
[
{"path": "/", "methods": ["GET"], "requirements": {...}},
{"path": "/dashboard", "methods": ["GET"], ...}
]
Symfony Router Issues If routes are missing, ensure:
config/bundles.php._import YAML path.Customize Output Format
Override the RouteCollection serializer via a compiler pass or event listener:
// src/EventListener/RouteSerializerListener.php
public function onKernelRequest(GetResponseEvent $event) {
$routes = $event->getRequest()->attributes->get('routes');
// Transform $routes before JSON encoding
}
Add Route Groups
Use Symfony’s route_groups to batch routes with shared JS metadata:
_js_group:
path: /
becklyn_js_routing:
data:
group: 'public'
children:
app_home: ~
app_contact: ~
Security Protect the endpoint with Symfony’s access control:
_v_routing:
path: /_v/routing
controller: Becklyn\JavaScriptRoutingBundle\Controller\RoutingController::index
methods: [GET]
requirements:
_method: GET
defaults:
_controller: 'Becklyn\JavaScriptRoutingBundle\Controller\RoutingController::index'
access_control: 'public' # Or restrict to specific roles
How can I help you explore Laravel packages today?