MVC: как аякс?

Я собираюсь запустить проект с использованием реализации Zend Framework MVC.

Как работать с ajax? Я имею в виду, должен ли я помещать весь код ajax в контроллер? Или посмотреть?

Например, я хочу получить сообщения от автора «ivan» для показа на странице.

Обычно я создаю ссылку на «/ posts / author / ivan» или smth, как это, создаю новое действие вроде «byAuthorAction ()» в контроллере Posts (или, возможно, контроллер пользователя, где бы вы ни находились), просмотр для него (и весь код что получает сообщения от модели) и создать для него новый маршрут.

Как добавить функциональность, чтобы получать сообщения любого пользователя в json, xml-форматах для ajax и, возможно, API, сохраняя принцип DRY и разрабатывая структуру кода как можно более умную?

Спасибо за ответы! Я буду очень рад видеть комментарии о проектировании MVC в таких ситуациях, как мой. У меня есть некоторый опыт в основных принципах MVC, но не в более сложных случаях. Может быть, некоторые полезные ссылки?

Вы действительно должны прочитать главу руководства о помощнике Action ContextSwitch. Но вот краткий обзор:

  • ваши сценарии просмотра (action-name.phtml) используются для обычного вывода HTML
  • вы можете инициализировать контекстный переключатель для некоторых действий в контроллере, чтобы их можно было выводить, например, XML-xml-контекст поддерживается по умолчанию, и вы бы поместили свой сценарий вида для контекста xml в (action-name.xml.phtml); контекст xml также отключает рендеринг макета
  • json также поддерживается встроенным контекстным переключателем, а опция по умолчанию – отключать как макет, так и представление и выводить все переменные, назначенные представлению из действия контроллера в формате JSON, этот параметр можно переключать с помощью setAutoJsonSerialization ( false) метода контекстного переключателя; но если вы его переключите, вам нужно создать сценарий вида action-name.json.phtml и вручную вывести переменные в формате JSON

Чтобы переключаться между этими двумя контекстами, вы должны добавить параметр формата в свой URL, например / posts / author / ivan / format / json или / posts / author / ivan / format / xml. Если вы не укажете формат, в котором ваше приложение выведет простой html.

Специальная версия коммутатора Context – это AjaxContext, и вам также нужно настроить это вручную. Он не использует параметр «format», чтобы определить, какой формат он должен использовать для вывода, но он проверяет заголовок, отправленный в вашем запросе, и ищет заголовок «X-Requested-With: XmlHttpRequest», и если он присутствует, рассматривается AjaxContext. Используя помощник действий AjaxContext, вы можете указать, какой контекст должен использоваться для определенных действий, если запрос запущен с использованием AJAX.

Вы можете использовать те же действия для возврата XML, JSON или что-то еще, путем обнаружения запросов ajax и, таким образом, возможность различать запросы ajax от обычных. Например:

public function fooAction() { if($this->getRequest->isXmlHttpRequest()) { echo json_encode($someData); } else { echo 'This is the normal output'; } } 

Ваш вид может быть чем-то иным, чем HTML, и либо конвейер может реагировать на запрос, являющийся сообщением ajax, либо ваш контроллер может реагировать. В любом случае, это должно быть так же просто, как вернуть другой вид.

Взгляните на AjaxContext Action-Helper (или ContextSwitch, который он расширяет), и он позволит вам использовать точно такой же код контроллера, переключаясь либо на отдельный сценарий вида (foo.json.phtml, либо на foo .ajax.phtml и т. д. – автоматически выбирается из параметра формата?) или использовать JSON Action-Helper, который возвращает объект, содержащий все переменные, которые вы назначаете для представления, – поэтому вам не нужно эхо от вашего контроллера (который испортит модульные тесты, если они у вас есть).

Мой синтаксис может быть старше, но это эскиз моего действия REST от моего Index Controller:

 /** * REST Action for this application. * * @return void */ public function restAction() { $this->_helper->viewRenderer->setNoRender(true); $parameters = (func_num_args() > 0) ? array($key => func_get_arg(0)) : $this->getRequest()->getParams(); $key = 'restCommand'; if(!array_key_exists($key, $parameters)) throw new Exception('Request for “' . $key . '” not found.'); $restCommand = $parameters[$key]; $xmlString = IndexModel::getEmptyXmlSet($restCommand); $xslFile = IndexModel::getModelFilePath('index'); //Handle OPML-driven REST commands: if(stripos($restCommand, 'opml-') === 0) { $opmlCall = explode('-', $restCommand); if(count($opmlCall) != 3) { $xmlString = Songhay_SimpleXml::getXmlMessage('OPML Call Not Recognized', array('The number of parameters are incorrect.')); } else { $opmlSet = $opmlCall[1]; $opmlId = $opmlCall[2]; $xmlString = IndexModel::getRssFragmentWithOpml($opmlSet, $opmlId); } } //Handle general REST commands: switch($restCommand) { case 'deeplink': $key = 'id'; if(!array_key_exists($key, $parameters)) throw new Exception('Request for “' . $key . '” not found.'); $url = $parameters[$key]; $xmlString = IndexModel::getRssFragment($url); $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); break; case 'index': $opmlFile = IndexModel::getModelFilePath('index', '.xml'); $xmlString = Songhay_SimpleXml::loadXmlAndStripNamespaces($opmlFile); $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); break; default: $xmlString = Songhay_SimpleXml::loadXslString($restCommand, $xmlString, $xslFile); } $response = $this->getResponse(); $response->setHeader('Content-Type', 'text/xml'); $response->setBody($xmlString); return; } 

Когда я использую ajax с выражением codeigniter i, выхожу прямо из контроллера.

Я также использую отдельный контроллер для простых запросов ajax, таких как маркировка, избранное и т. Д. Для запросов ajax, таких как логин, контакт и т. Д., Я бы добавил логику к нормальному пути (например, domain.com/contact), имея дело с запросом ajax. Затем я запускаю выполнение json и kill.