使用查询字符串参数将Symfony2路由到控制器

5

我目前和一个客户一起生活在Bizzaro世界中。

因为我们正在编写的Symfony应用程序将响应注入到另一个应用程序中的页面中,我们被迫只能拥有一个应用程序的单个URL,但幸运的是我们可以完整地获取查询字符串。

因此,我需要做与Symfony相反的事情,一种老派的MVC方法。 我需要通过查询字符串参数进行路由,路由到正确的控制器并呈现正确的响应,而不是使用标准且合理的路径方法。

所以URL将是http://www.bizzaro.com/appname?route=%2fblog 而不是 http://www.bizzaro.com/appname/blog 等等。

在路由部分有很好的示例,可以确保将查询字符串作为参数传递给控制器操作,但没有针对这种比较保守的方法。

我该从哪里开始?

我实施了Corentin Dandoy提出的解决方案2,但稍微修改了一下,以防止查找根目录时出现循环。

namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class FrontControllerControllerController extends Controller
{
    /**
     * Forward the request to the appropriate controller
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function indexAction(Request $request)
    {
        // get the parameter that specifies the route to the 'real' homepage controller
        $homeroute = $this->container->getParameter('homeroute');
        $route = $request->query->get('route');

        // Convert the query-string route into a valid path route
        $path = '/'.$route;

        // if it is the route, then use the 'real' homepage controller, otherwise you end up in a routing loop!
        if ($path === '/')
        {
            $match = $this->get('router')->match('/' . $homeroute);
        } else {
            try {
                $match = $this->get('router')->match($path);
            } catch (ResourceNotFoundException $e) {

                throw $this->createNotFoundException('The route does not exist');
            }
        }

        $params = array(
            'request' => $request,
        );

        return $this->forward($match['_controller'], $params);
    }

}

插入自己的控制器解析器可能是最佳选择:http://api.symfony.com/2.7/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.html 不幸的是,关于这方面的文档不多。 - Cerad
我发现有一些关于如何使用自己的实现来装饰路由器的文档,但是需要编写的代码比Corentin的简单前端控制器解决方案要多得多。 对于表单提交,我编写了一个简单的Twig扩展,将操作从路径更改为查询字符串。前端控制器控制器也会按照同样的方式传递请求。 - graney
1个回答

4

解决方案1

一个简单的解决方案(虽然不可扩展)是这样的:

namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class MainController
{
    /**
     * @Route("/app", name="bizarro_app")
     */
    public function mainAction(Request $request)
    {
        $route = $request->query->get('route');

        switch ($route) {
            case 'blog':
                return $this->blogAction($request);
            default:
                throw $this->createNotFoundException('The route does not exist');
        }
    }

    protected function blogAction(Request $request)
    {
        // Your blog page here
        return new Response('...');
    }
}

解决方案二

如果您不介意同时拥有两种类型的路由,您可以尝试以下方法:

namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class MainController
{
    /**
     * @Route("/app", name="bizarro_app")
     */
    public function mainAction(Request $request)
    {
        $route = $request->query->get('route');

        // Convert the query-string route into a valid path
        $path = '/'.$route;

        try {
            $match = $this->get('router')->match($path);
        } catch (ResourceNotFoundException $e) {
            throw $this->createNotFoundException('The route does not exist');
        }

        $params = array(
            'request' => $request,
        );

        return $this->forward($match['_controller'], $params);
    }

    /**
    * @Route("/blog", name="bizarro_blog")
    */
    public function blogAction(Request $request)
    {
        // Your blog page here
        return new Response('...');
    }
}

这样,您就可以受益于Sf2路由组件。请注意,我自己没有测试过。


我使用了第二种方法,本质上是一个前端控制器到前端控制器的转发。目前为止它运行良好。 我将在此添加修改后的解决方案,因为在您的代码中,如果您请求主页,会出现一点循环。但这确实帮助了我。谢谢。 - graney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接