-
-
Notifications
You must be signed in to change notification settings - Fork 381
Closed
Labels
BugBug FixBug FixLiveComponentStatus: Waiting feedbackNeeds feedback from the authorNeeds feedback from the author
Description
after upgrading to ux-live-component > 2.27.0 I'm getting this error. "Please provide a path
parameters". It happens when I'm doing $this->redirect('/'); on a live component that extends AbstractController that is on SonataPageBundle front page. It works on 2.27.0
I asked GTP-5 and it gave me this. It explains what is happening and It said that "If you need dynamic slug root and want URL mapping future-proof you should use this"
<?php
declare(strict_types=1);
namespace App\LiveComponent;
use Symfony\UX\LiveComponent\Util\UrlFactory;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
/**
* Decorator that preserves original matched route parameters (e.g. Sonata PageBundle's
* required "path" parameter for the dynamic CMS route) when LiveComponents rewrites URLs.
*
* The stock UrlFactory matches the previous URL path, extracts only the route name and
* regenerates with JUST the path-mapped LiveProps. If the underlying route has *required*
* parameters that were not mapped (like Sonata's page_slug "path"), generation fails.
*
* This subclass re-matches the previous path, captures the original parameters, merges
* them back in (letting path-mapped LiveProps override), then proceeds with query merging.
*/
class PreservingUrlFactory extends UrlFactory
{
public function __construct(private readonly RouterInterface $router)
{
parent::__construct($router);
}
/**
* @param string $previousUrl The full previous URL (path + optional query)
* @param array<string,mixed> $pathMappedProps LiveProps mapped to the path (mapPath = true)
* @param array<string,mixed> $queryMappedProps LiveProps mapped to the query (default)
*/
public function createFromPreviousAndProps(
string $previousUrl,
array $pathMappedProps,
array $queryMappedProps,
): ?string {
$parsed = parse_url($previousUrl);
if ($parsed === false) {
return null;
}
$previousPath = $parsed["path"] ?? "";
$previousQueryRaw = $parsed["query"] ?? "";
// Re-match to extract original parameters (needed for routes like Sonata's page_slug).
[$routeName, $originalParams] = $this->matchRouteAndExtractParams(
$previousPath,
);
if ($routeName === "") {
return null;
}
// Merge original params with new path-mapped props (LiveProps override originals).
$routeParams = array_merge($originalParams, $pathMappedProps);
try {
$newPath = $this->router->generate($routeName, $routeParams);
} catch (ResourceNotFoundException | MethodNotAllowedException | MissingMandatoryParametersException) {
return null;
} catch (\Throwable) {
return null;
}
// Previous query parameters
$previousQueryParams = $this->parseQueryString($previousQueryRaw);
// Remnant parameters the router injected into the query string
$remnantQueryParams = $this->extractQueryParamsFromUrl($newPath);
// Final query params (later sources override earlier)
$finalQueryParams = array_merge(
$previousQueryParams,
$remnantQueryParams,
$queryMappedProps,
);
return $this->replaceQueryString($newPath, $finalQueryParams);
}
/**
* Match the path and return [routeName, paramsWithoutInternalKeys].
*
* @return array{0:string,1:array<string,mixed>}
*/
private function matchRouteAndExtractParams(string $path): array
{
$context = $this->router->getContext();
$tmpContext = clone $context;
$tmpContext->setMethod("GET");
$this->router->setContext($tmpContext);
try {
$match = $this->router->match($path);
} catch (\Throwable) {
$this->router->setContext($context);
return ["", []];
} finally {
$this->router->setContext($context);
}
$routeName = $match["_route"] ?? "";
unset($match["_route"], $match["_controller"]);
return [$routeName, $match];
}
/**
* Extract query params from a URL (ignores path & fragment).
*
* @return array<string,mixed>
*/
private function extractQueryParamsFromUrl(string $url): array
{
$query = parse_url($url, PHP_URL_QUERY) ?? "";
return $this->parseQueryString($query);
}
/**
* @return array<string,mixed>
*/
private function parseQueryString(string $query): array
{
if ($query === "") {
return [];
}
$params = [];
parse_str($query, $params);
return $params;
}
/**
* Replaces (or appends) the query string on a URL path.
*
* @param array<string,mixed> $params
*/
private function replaceQueryString(string $url, array $params): string
{
$base = preg_replace("/[?#].*/", "", $url) ?? $url;
if (empty($params)) {
return $base;
}
$qs = http_build_query($params);
return $base . ("" !== $qs ? "?" . $qs : "");
}
}
Metadata
Metadata
Assignees
Labels
BugBug FixBug FixLiveComponentStatus: Waiting feedbackNeeds feedback from the authorNeeds feedback from the author