php – 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.

我想拦截像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);
        }
    }
}
点赞