【问题标题】:MVC: how to ajax?MVC:如何实现 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 原则方面有一些经验,但在更复杂的情况下没有。也许一些有用的链接?

【问题讨论】:

    标签: php ajax model-view-controller zend-framework


    【解决方案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 并终止脚本执行。

          【讨论】:

            猜你喜欢
            • 2016-03-12
            • 2011-11-19
            • 1970-01-01
            • 1970-01-01
            • 2020-08-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多