2016-11-28 85 views
4

我有这样的控制器:Symfony的@ParamConverter:排除使用,如果占位符不包含点

/** 
* {@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。

我想拦截的URL像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:Entity object not found.

那么,有没有申请只有占位符有一个点的@ParamConverter的方法吗?或者,我可以使用其他哪些方法使redirectToIdAction工作,而不会抛出Not found异常?

+0

更好地实现对重定向的东西和/或paramconverter – Matteo

+1

定制的监听器为什么不把paramconverter上一个动作需要它而不是课程,还是将重定向操作移出课程? – Gerry

+1

更多操作(约7)需要'paramconverter'。我曾考虑过将重定向操作移出课程的可能性,但我希望有另外的选择,所以在这里提出...不是创建一个自定义参数转换器,而是创建另一个控制器,然后在其中放入重定向动作... – Aerendir

回答

1

定制ParamConverter可能做的伎俩,但如果你不想做一个,你将不得不使用的ID和域名不同的路线。

解决方案1 ​​

因为你的路由是对整个类,而不是对自己的行为做,恐怕你必须将重定向动作移动到另一个控制器类。

之后,你可以搭配选择性地使用要求

/** 
*@Route(
    "entity/{domain_host}", 
    name="entity_domain", 
    requirements={"domain_host": "^(?=.*[\w])(?=.*[.]).+$"} 
*) 
*@ParamConverter(...) 
*/ 
someActionOnDomainAction() 
{ 
//... 
} 


/** 
*@Route(
    "entity/{id}", 
    name="entity_domain", 
    requirements={"id": "^[\d]$"} 
*) 
*/ 
redirectIdToDomainAction() 
{ 
//... 
} 

解决方案2

或者ID和域名,你可以储存库的方法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); 
     } 
    } 
}