我编写客户端/服务器应用程序。
我使用了几个带有'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');
有什么想法吗?
答案 0 :(得分:1)
REST路由的工作原理是为传递给Router::mapResources()
的控制器自动创建路由。前缀路由几乎相同,它创建默认路由,包括Routing.prefixes
中定义的前缀。
但是这两个功能彼此不了解,它们都创建了separte路由,因此Router::mapResources()
将连接到没有前缀的URL(此方法的prefix
选项不使用实际的前缀路由,它只会将该选项的值添加到要连接的URL的开头!),因此您对/mobile/...
的请求实际上并不使用REST路由,而只是前缀路由。
对于像使用选项或其他东西这样的问题没有简单的解决方法,相反,您必须手动定义REST路由,以便包含前缀选项,但这很简单。
请参阅Modifying the default REST routes和Custom REST Routing。
示例路线可能如下所示:
Router::connect(
'/mobile/users',
array(
'prefix' => 'mobile',
'mobile' => true,
'controller' => 'users',
'action' => 'add',
'[method]' => 'POST'
)
);
这会将POST请求与/mobile/users
连接到UsersController::mobile_add()
。类似地,您必须对GET
和PUT
等所有其他方法执行此操作,无论是否传递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路由。