MVC:如何实现 ajax?
Posted
技术标签:
【中文标题】MVC:如何实现 ajax?【英文标题】:MVC: how to ajax? 【发布时间】:2010-12-02 17:29:10 【问题描述】:我将使用 Zend Framework MVC 实现开始一个项目。
如何使用 ajax?我的意思是,我应该将所有 ajax 代码放入控制器中吗?还是进入视野?
例如,我想将作者“ivan”的帖子显示在页面上。
通常,我创建一个指向“/posts/author/ivan”的链接或类似的链接,在 Posts 控制器(或者可能是用户控制器,任何地方)中创建一个新的 Action,如“byAuthorAction()”,查看它(并且所有从模型中获取帖子的代码都在那里)并创建一个新的路由。
如何添加功能以获取任何用户的 json、xml 格式的 ajax 和 API,保持 DRY 原则并尽可能智能地设计代码结构?
--
感谢您的回答! 我会很高兴看到 cmets 在像我这样的情况下设计 MVC。我在基本 MVC 原则方面有一些经验,但在更复杂的情况下没有。也许一些有用的链接?
【问题讨论】:
【参考方案1】:您可以利用相同的操作返回 XML、JSON 或其他内容,方法是检测 ajax 请求,从而能够将 ajax 请求与正常请求区分开来。例如:
public function fooAction()
if($this->getRequest->isXmlHttpRequest())
echo json_encode($someData);
else
echo 'This is the normal output';
【讨论】:
xml和json如何选择?我应该像 /posts/author/ivan 这样的 html 格式、/posts/author/ivan.xml、/posts/author/ivan.json、/posts/author/ivan.rss 等格式的 url 格式吗? 不,URL 是一样的。您可以使用 json_encode() 以 JSON 格式输出内容。 ar2.php.net/json_encode json 重量更轻,更易于与 IMO 一起使用。您可以创建一个 JSON 视图,或者您可以在不使用视图的情况下回显 json_encode() 您的数据数组,您可能必须关闭自动视图渲染。 我的意思是,为了 API,而不是为了我自己的请求【参考方案2】:您的视图可以是 HTML 以外的其他内容,并且管道可以对作为 ajax 发布的请求做出反应,或者您的控制器可以做出反应。无论哪种方式,它都应该像返回不同的视图一样简单。
【讨论】:
【参考方案3】:看看 AjaxContext Action-Helper(或它扩展的 ContextSwitch),它将允许您使用完全相同的控制器代码,切换到单独的视图脚本(foo.json.phtml , 或 foo.ajax.phtml 等 - 从 ?format 参数中自动获取),或使用 JSON Action-Helper 将返回一个包含您分配给视图的所有变量的对象 - 所以您不需要从您的控制器中回显(如果您拥有它们,这会弄乱单元测试)。
【讨论】:
哦,当然。我怎么没看到呢?【参考方案4】:我的语法可能较旧,但这是我的索引控制器中我的 REST 操作的草图:
/**
* 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;
【讨论】:
【参考方案5】:您确实应该阅读有关 ContextSwitch Action Helper 的手册章节。但这里有一个简短的大纲:
您的视图脚本 (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。
上下文开关的特殊版本是 AjaxContext,您还必须手动配置它。它不使用“格式”参数来确定它应该使用哪种格式进行输出,但它会检查请求中发送的标头并查找“X-Requested-With: XmlHttpRequest”标头,如果存在,则检查 AjaxContext。使用 AjaxContext 操作帮助程序,您可以指定在使用 AJAX 触发请求时应将哪个上下文用于特定操作。
【讨论】:
【参考方案6】:当我将 ajax 与 codeigniter 一起使用时,我直接从控制器中输出。
我还使用单独的控制器处理简单的 ajax 请求,如标记、收藏等。对于登录、联系人等 ajax 请求,我会在正常路径(例如 domain.com/contact)中添加逻辑来处理 ajax要求。然后我输出 json 并终止脚本执行。
【讨论】:
以上是关于MVC:如何实现 ajax?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Asp.Net MVC5 中使用 Ajax 将数据库更改保存到拖放列表
ajax异步请求获取后台数据,java mvc 后台应该如何封装各种实体类数据?