如何使用cakephp中的前缀将post rest请求连接到add控制器操作

时间:2014-06-24 08:55:11

标签: angularjs rest cakephp cakephp-2.0 ionic-framework

我编写客户端/服务器应用程序。

  • 服务器端由CakePHP 2.4.7提供支持。
  • 客户端在移动设备上使用angularjs和cordova运行

我使用了几个带有'admin'和'mobile'的cakephp路由前缀。 (我使用$ resource和$ httpInterceptor angularjs工厂来设置我的REST请求。)

我想用json数据发布来调用/website/mobile/posts/add.json

所以我用POST ajax查询调用/website/mobile/posts.json

问题在于:被叫控制器动作是'索引',而不是'添加';

在我的PostsController上,我添加了这个:

echo $this->request->params['action'] . "\n";
echo ($this->request->isPost())? "post" . "\n" : "not post";
die;

并且响应总是:

mobile_index
post

所以ajax请求似乎是正确的但是cakephp没有将它映射到add动作,而是将其映射到索引1。 不过我的配置似乎也不错;这是我的routes.php的片段

Router::mapResources(array('users','posts'));
Router::parseExtensions('json');

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

前缀路由不适用于开箱即用的REST路由

REST路由的工作原理是为传递给Router::mapResources()的控制器自动创建路由。前缀路由几乎相同,它创建默认路由,包括Routing.prefixes中定义的前缀。

但是这两个功能彼此不了解,它们都创建了separte路由,因此Router::mapResources()将连接到没有前缀的URL(此方法的prefix选项使用实际的前缀路由,它只会将该选项的值添加到要连接的URL的开头!),因此您对/mobile/...的请求实际上并不使用REST路由,而只是前缀路由。

手动定义带前缀的REST路由

对于像使用选项或其他东西这样的问题没有简单的解决方法,相反,您必须手动定义REST路由,以便包含前缀选项,但这很简单。

请参阅Modifying the default REST routesCustom REST Routing

示例路线可能如下所示:

Router::connect(
    '/mobile/users',
    array(
        'prefix' => 'mobile',
        'mobile' => true,
        'controller' => 'users',
        'action' => 'add',
        '[method]' => 'POST'
    )
);

这会将POST请求与/mobile/users连接到UsersController::mobile_add()。类似地,您必须对GETPUT等所有其他方法执行此操作,无论是否传递id等等。

请注意,手动连接时,您可以放弃Routing.prefixes选项,当然也可以放弃Router::mapResources()

自动映射

手动定义所有这些路线有点令人筋疲力尽,相对于Router::resourceMap() configuration,你最好自动化它。

以下是有关如何执行此操作的示例,它有点类似于Router::mapResources(),但它接受实际使用前缀路由的prefix选项:

function mapResources(array $controllers) {
    $resourceMap = Router::resourceMap();

    foreach($controllers as $controller => $options) {
        if(!is_array($options)) {
            $controller = $options;
            $options = array();
        }
        $options += array(
            'prefix' => null,
            'plugin' => null,
            'id' => Router::ID . '|' . Router::UUID
        );

        foreach($resourceMap as $params) {
            $url = '';
            if($options['prefix']) {
                $url .= '/' . $options['prefix'];
            }
            if($options['plugin']) {
                $url .= '/' . $options['plugin'];
            }
            $url .= '/' . $controller;
            if($params['id']) {
                $url .= '/:id';
            }

            Router::connect(
                $url,
                array(
                    'prefix' => $options['prefix'],
                    $options['prefix'] => !!$options['prefix'],
                    'plugin' => $options['plugin'],
                    'controller' => $controller,
                    'action' => $params['action'],
                    '[method]' => $params['method']
                ),
                array(
                    'id' => $options['id'],
                    'pass' => array('id')
                )
            );
        }
    }
}

你会这样称呼:

mapResources(array(
    'books' => array(
        'prefix' => 'mobile'
    )
));

它将使用books前缀映射mobile控制器的所有REST路由。

相关问题