Как подключить запрос post rest к действию add controller, используя префиксы в cakephp

#angularjs #rest #cakephp #cakephp-2.0 #ionic-framework

#angularjs #rest #cakephp #cakephp-2.0 #ionic-framework

Вопрос:

Я кодирую клиент-серверное приложение.

  • Серверная часть работает на CakePHP 2.4.7.
  • Запуск на стороне клиента с angularjs и cordova на мобильных устройствах

Я использую несколько префиксов маршрута cakephp, у которых ‘admin’ и ‘mobile’. (И я использую фабрики angularjs $resource и $ HttpInterceptor для настройки своих запросов REST.)

Я хочу вызвать /website/mobile/posts/add.json с помощью отправки данных в формате json.

Итак, я вызываю /website/mobile/posts.json запрос POST ajax:

Проблема здесь: вызываемое действие контроллера — это «индекс», а не «добавить»;

Поверх моего PostsController я добавил это:

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

и ответ всегда:

 mobile_index
post
  

Таким образом, запрос ajax кажется правильным, но cakephp не сопоставляет его с действием add, а индексирует его.
Однако моя конфигурация тоже кажется хорошей; вот фрагмент моего routes.php

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

Есть идеи?

Комментарии:

1. Используете ли вы фактическую префиксную маршрутизацию ( Configure::write('Routing.prefixes', /*...*/) ), т. Е. Вы хотите в конечном итоге вызывать префиксные действия контроллера, например mobile_add() , или ваши «префиксы» просто красивые URL-адреса?

2. Да, я действительно использую префиксную маршрутизацию

Ответ №1:

Префиксная маршрутизация не работает с REST-маршрутизацией из коробки

Маршрутизация REST работает путем автоматического создания маршрутов для переданных контроллеров Router::mapResources() . Префиксная маршрутизация в значительной степени делает то же самое, она создает маршруты по умолчанию, включая префиксы, определенные в Routing.prefixes .

Однако обе функции не знают друг о друге, они оба создают отдельные маршруты, поэтому Router::mapResources() будут подключаться к URL-адресам без префиксов ( prefix опция для этого метода не использует фактическую маршрутизацию префиксов, она просто добавит значение этой опции в начало URL-адреса для подключения!), И, следовательно, вашзапрос на /mobile/... самом деле не использует маршрутизацию REST, а только маршрутизацию с префиксом.

Определение маршрутов REST с префиксами вручную

Для этой проблемы нет простого решения, такого как использование опции или чего-то еще, вместо этого вам придется определять маршруты REST вручную, чтобы включить опцию prefix, хотя это достаточно просто.

См. Изменение маршрутов REST по умолчанию и Пользовательская маршрутизация REST.

Примерный маршрут может выглядеть следующим образом:

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

Это будет подключать запросы POST к /mobile/users to UsersController::mobile_add() . Аналогично, вам нужно будет сделать это для всех других методов, таких как GET and PUT , с передачей и без передачи id и т. Д.

Обратите внимание, что при подключении вручную вы можете отказаться от Routing.prefixes опции и, конечно, вызова Router::mapResources() .

Автоматическое сопоставление

Определение всех этих маршрутов вручную довольно утомительно, вам лучше автоматизировать его в зависимости от Router::resourceMap() конфигурации.

Вот пример того, как это сделать, он чем-то похож на 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'
    )
));
  

и это сопоставило бы все маршруты REST для вашего books контроллера с использованием mobile префикса.