我仍然是Symfony2的新手,无法解决以下问题。
我在Controller中有一个主要的浏览操作,并定义了以下路径(在控制器中):
/**
* @Route("/browse")
* @Route("/browse/{page}")
* @Route("/browse/c/{category}/{categoryName}")
* @Route("/browse/c/{category}/{categoryName}/{page}")
* @Route("/browse/c/{category}/b/{brand}/{page}")
* @Route("/browse/b/{brand}")
* @Route("/browse/b/{brand}/{page}")
* @Template()
*/
public function browseAction($category = 0, $page = 1, $brand = 0) {
上述路由没有问题。
问题是从树枝视图生成网址或查看帮助程序。
我希望能够在视图助手中执行以下操作:
{{ url('browse', {'brand': '123'}) }}
这适用于routing.yml中的以下内容:
browse:
pattern: /browse/b/{brand}
defaults: { _controller: MyCoreBundle:Browse:browse }
然后我尝试了:
browse:
pattern: /browse/b/{brand}
pattern: /browse/c/{category}/b/{brand}
defaults: { _controller: MyCoreBundle:Browse:browse }
但只有最后一个模式似乎适用并尝试使用以下内容会引发错误:
{{ url('browse', {'brand': '123'}) }}
我意识到我可以在routing.yml中创建多个单独的路由,这些路由是唯一命名的。但这意味着根据将要使用的变量,我需要指定一个不同的路由名称,这将很快变得非常混乱。
我也尝试过:
browse:
pattern: /browse/c/{category}/b/{brand}/{page}
defaults: { _controller: MyCoreBundle:Browse:browse }
使用:
{{ url('browse', {'brand': '123', 'category':'', 'page': '1'}) }}
但是这引发了一个错误,说类别的格式不正确..
我在这里遗漏了什么吗?有人能指出我正确的方向吗?我是否可能需要创建一个枝条扩展,可以获取所有变量并根据输入构建URL?
答案 0 :(得分:3)
我最终创建了一个枝条延伸。它很长,并涉及传递route_params和query_params,但它可以工作。
所以在我的控制器中我需要获取路由和查询参数:
$routeParams = $this->get('request')->attributes->get('_route_params');
$queryParams = $this->get('request')->query->all();
然后转到查看:
return array('products' => $products, 'mfdFacets' => $mfdFacets, 'routeParams' => $routeParams, 'queryParams' => $queryParams);
然后在我的browse.html.twig中,我调用一个视图助手并传递路由和查询参数:
{% render controller("MyCoreBundle:Helper:menumfd", {'mfdFacets': mfdFacets, 'routeParams': routeParams, 'queryParams': queryParams }) %}
然后在辅助控制器中:
/**
* @Route("/helper/menu/module/mfd")
* @Template()
*/
public function menumfdAction($mfdFacets, $routeParams, $queryParams) {
$manufacturers = $this->get("my.manufacturers")->makeNamedArray($mfdFacets);
return array('manufacturers' => $manufacturers, 'routeParams' => $routeParams, 'queryParams' => $queryParams);
}
然后在帮助者视图中:
<ul>
{% for mfd in manufacturers %}
<li><a href="{{ mybrowseroute("brand", mfd.id, "brandName", mfd.name, routeParams, queryParams) }}">{{ mfd.name | raw }} ({{ mfd.count }})</a></li>
{% endfor %}
</ul>
然后是Twig Extension(服务?)类:
<?
namespace My\Bundle\ServiceBundle\Twig\Extension;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpFoundation\Request;
class MyRouterExtension extends \Twig_Extension {
protected $container;
public function __construct(Container $container) {
$this->container = $container;
}
public function getFunctions() {
return array(
'mybrowseroute' => new \Twig_Function_Method($this, 'myBrowseRoute')
);
}
public function myBrowseRoute($label, $value, $label2, $value2, $routeParams, $queryParams) {
#print_r($routeParams);
$route_array = array("category", "categoryName", "brand", "brandName");
## Value 1
if (array_key_exists($label, $routeParams)) {
$routeParams["$label"] = $value;
} else {
if (in_array($label, $route_array)) {
$routeParams["$label"] = $value;
}
}
if (array_key_exists($label, $queryParams)) {
$queryParams["$label"] = $value;
} else {
if (!array_key_exists($label, $route_array) && !array_key_exists($label, $routeParams)) {
$queryParams["$label"] = $value;
}
}
## Value 2
if (array_key_exists($label, $routeParams)) {
$routeParams["$label2"] = $value2;
} else {
if (in_array($label, $route_array)) {
$routeParams["$label2"] = $value2;
}
}
if (array_key_exists($label2, $queryParams)) {
$queryParams["$label2"] = $value2;
} else {
if (!array_key_exists($label2, $route_array) && !array_key_exists($label2, $routeParams)) {
$queryParams["$label2"] = $value2;
}
}
## Generate URL string
$base_route = $this->container->get('router')->generate("browse");
$routeString = $base_route;
if (array_key_exists("category", $routeParams)) {
$routeString .= "/c/" . $routeParams["category"];
}
if (array_key_exists("categoryName", $routeParams)) {
$routeString .= "/" . urlencode($routeParams["categoryName"]);
}
if (array_key_exists("brand", $routeParams)) {
$routeString .= "/b/" . $routeParams["brand"];
}
if (array_key_exists("brandName", $routeParams)) {
$routeString .= "/" . urlencode($routeParams["brandName"]);
}
# Page
$routeString .= '/1';
$i = 1;
foreach($queryParams as $qLabel => $qValue){
if($i == 1){
$routeString .= "?$qLabel=$qValue";
} else {
$routeString .= "&$qLabel=$qValue";
}
$i++;
}
return $routeString;
}
public function getName() {
return 'my_router';
}
}
在routing.yml中需要以下内容:
browse:
pattern: /browse
defaults: { _controller: MyCoreBundle:Browse:browse }
在services.yml:
services:
my.router:
class: My\Bundle\ServiceBundle\Twig\Extension\MyRouterExtension
arguments: ['@service_container']
tags:
- { name: twig.extension }
如果您只想在视图助手中使用传递1键值对,则可以使用:
<li><a href="{{ mybrowseroute("brand", mfd.id, '', '', routeParams, queryParams) }}">{{ mfd.name | raw }} ({{ mfd.count }})</a></li>
答案 1 :(得分:1)
调试路由,您将看到每个路径注释都获得唯一名称
php app/console router:debug
您可以在注释中使用name参数设置单个名称。看看documentation。
@Route("/browse/{page}", name="browse_with_page")
为您的案例创建专用的枝条扩展可能是另一种解决方案。或许这个blog post提到的可能很有趣。
编辑:您可以最小化路线,因为页面参数可以是可选的。
@Route("/browse/c/{category}/{categoryName}")
@Route("/browse/c/{category}/{categoryName}/{page}")
与两种方式相同,可以同时调用。
@Route("/browse/c/{category}/{categoryName}/{page}", defaults={"page" = 1})
在控制台上测试它,相同的路线应匹配。
php app:console router:match /browse/c/1/foobar
php app:console router:match /browse/c/1/foobar/2
答案 2 :(得分:-2)
首先,这不是动态路由。这是具有多种模式的静态路由。有明显的区别。
其次,您需要为每个模式创建一个特定定义的路由,每个模式都有唯一的名称。但是,您可以将页面参数默认为1以使其可选,从而减少定义的模式数量。
第三,当您需要在树枝中生成这些链接时,只需使用上面定义的唯一名称和所需参数。
最后,在上一个示例中,category是必需参数,并且您将空白值传递给它。这将创建“/ browse / c // b / 123/1”,这是Symfony2无法处理的路径。