我有这个控制器:
/**
* {@inheritdoc}
*
* @Route("entity/{domain_host}")
* @ParamConverter("entity", class="AppBundle:Entity", options={
* "repository_method" = "findOneByDomainHost",
* "mapping": {"domain_host": "domainHost"},
* "map_method_signature" = true
* })
*/
class EntityController extends Controller
{
...
}
这样,诸如http://example.com/entity/another-example.com之类的URL与动作匹配,并且相应的another-example.com实体被水合并传递给控制器.
现在,这个实体也有一个ID.
我想拦截像http://example.com/entity/12345这样的网址,并将其重定向到http://example.com/entity/another-example.com.
为此,我在EntityController中创建了另一个方法:
/**
* {@inheritdoc}
*
* @Route("entity/{domain_host}")
* @ParamConverter("store", class="AppBundle:Entity", options={
* "repository_method" = "findOneByDomainHost",
* "mapping": {"domain_host": "domainHost"},
* "map_method_signature" = true
* })
*/
class EntityController extends Controller
{
public function redirectIdToDomainAction(Request $request)
{
die(dump($request));
// Following will be the redirect logic
}
}
在我的routing.yml中,在文件的顶部:
entity_id_to_domain:
path: /entity/{id}
defaults: { _controller: AppBundle:Entity:redirectIdToDomain }
requirements:
id: ^[^.]*$
methods: [GET]
实际上,如果占位符不包含点,则调用redirectIdToDomain操作(点是discrimen:如果占位符有点,则传递域,如果没有点,则占位符可能由uts表示实体ID和我必须重定向).
问题是,当控制器类EntityController使用@ParamConverter时,占位符被解释为域,结果是我得到了一个AppBundle:未找到实体对象.
那么,只有在占位符有点的情况下才有办法应用@ParamConverter吗?或者,我可以使用哪些其他方法使redirectToIdAction工作而不抛出未找到的异常?
最佳答案 自定义ParamConverter可能会起作用,但如果您不想制作一个,则必须使用不同的ID和域名路由.
解决方案1
由于您的路由是在整个类上完成而不是在操作本身上完成,我担心您必须将重定向操作移动到另一个控制器类.
之后,您可以使用要求有选择地匹配ID和域名
/**
*@Route(
"entity/{domain_host}",
name="entity_domain",
requirements={"domain_host": "^(?=.*[\w])(?=.*[.]).+$"}
*)
*@ParamConverter(...)
*/
someActionOnDomainAction()
{
//...
}
/**
*@Route(
"entity/{id}",
name="entity_domain",
requirements={"id": "^[\d]$"}
*)
*/
redirectIdToDomainAction()
{
//...
}
解决方案2
或者,您可以将存储库方法findOneByDomainHost()更改为findOneByDomainHostOrID(),并使其与域名和数字ID匹配.
通过这种方式,您可以获得Object Not Found错误,并始终可以获取实体的域名,并在同一控制器操作中执行重定向.
这是一个例子:
/**
* Class EntityController
*
* @Route("/entity/{domain_host}", name="domain_host")
* @ParamConverter("domain_host", class="AppBundle:Entity", options={
* "repository_method" = "findOneByHostOrID"
* })
*/
class EntityController extends Controller
{
/**
* @Route("/", name="show_domain_host")
* @param Entity $domain_host
*/
public function domain_hostAction(Entity $domain_host, Request $request)
{
$id = $domain_host->getId();
$host = $domain_host->getHost();
// Get the unconverted route parameter.
$parameter = $request->attributes->get('_route_params')['domain_host'];
if ($parameter == $domain_host->getId()){
// If the route parameter matches the ID,
// redirect to the same route using the domain host.
$url = $this->generateUrl('show_mail', ['mail' => $lib]);
return $this->redirect($url, 301);
}
return new Response("<html><body>$id $host</body></html>");
}
}
和存储库类:
class EntityRepository extends EntityRepository
{
public function findOneByHostOrID($domain_host)
{
if (preg_match("[\\d]",$domain_host)) {
return $this->findOneById($domain_host);
} else {
return $this->findOneByHost($domain_host);
}
}
}