【问题标题】:Error redirects for OpenCart with UserFrosting使用 UserFrosting 重定向 OpenCart 的错误
【发布时间】:2016-06-21 04:59:15
【问题描述】:

所以我一直致力于将 OpenCart 集成到 UserFrosting (http://www.userfrosting.com/)。基本上,我通过使用.load 将页面注入到我自己的html 页面上的div 来使所有管理仪表板页面加载到UserFrosting 仪表板中。我几乎完成了,但还有最后一个工作没有留在 UF 仪表板中。

我将以目录/类别页面为例来说明我在做什么:

这是我的类别 html 文件,名为 cata-categories.html

<!DOCTYPE html>
        <html lang="en">
        {% include 'components/head.html' %}
        <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
        <body>
            <div id="wrapper">
                {% include 'components/nav-account.html' %}
                <div id="page-wrapper">
                    {% include 'components/alerts.html' %}

                    <ol id="categories"></ol>

                <script>
                    $( "#categories" ).load( "../solutions/admin/index.php?route=catalog/category" );
                </script>



                    <br>
                    {% include 'components/footer.html' %}    
                </div>
            </div></div>
        </body>
        </html>

这是通过 UserFrosting 的侧边栏访问的,在 sidebar.html 中使用以下代码:

{% if checkAccess('uri_manage_groups') %}
                <li>
                    <a href="{{site.uri.public}}/cata-categories/"><i class="fa fa-tags fa-fw"></i>Categories</a>
                </li>
                {% endif %}

页面是通过 public/index.php 中的以下代码为 UserFrosting 呈现的:

 $app->get('/cata-categories/?', function () use ($app) {   
           $app->render('cata-categories.html', [
               'page' => [
                   'author' =>         $app->site->author,
                   'title' =>          "Catagories",
                   'description' =>    "Catalogue Catagories.",
                   'alerts' =>         $app->alerts->getAndClearMessages()
               ]
           ]);  
        });

为了保持 OpenCart 页面上的所有链接都被点击,我将以下脚本放在每个主要 .tpl 的底部(例如 category_list.tpl):

<script>
$("#categories").on("click", "a", function (e) {
    $("#categories").load($(this).attr("href"));
    e.preventDefault();
});
</script>

然后,为了在提交表单时将内容保持在同一页面上,我将控制器中的重定向(例如 category.php)更改为以下内容:

$this->response->redirect('../../portal/cata-categories');

一切都很好,现在唯一的问题是表单提交或过滤结果中的错误。例如,如果有人尝试添加新类别但未填写任何信息并单击保存,它将重定向到 /admin/index.php?route=catalog/category/add,但不在 UserFrosting 仪表板内。

我希望它保留在我的仪表板中,并且需要朝着正确的方向推动在控制器中修改的内容以使其执行此操作,我假设某种 AJAX 强制它不重新加载页面并只显示错误。与过滤器按钮相同,它显然需要向 URL 添加过滤器,因此不会在仪表板中加载 - 需要一种无需刷新即可过滤的方法。

非常感谢有修改 OpenCart 经验的人提供的任何帮助,如果您需要有关我正在做什么的更多信息,请随时询问。

【问题讨论】:

  • 我已经召见皇上来协助你。
  • @r3wt 我感觉到源中有干扰。
  • @WintersWolf 是 /admin/index.php?route=catalog/category/add OpenCart 的路线之一吗? OpenCart 有自己的内部路由器吗?

标签: php jquery ajax opencart userfrosting


【解决方案1】:

OpenCart 的路由不是为 AJAX 请求构建的

UserFrosting 和 OpenCart 处理 POST 请求的方式似乎根本不一致。如果您查看catalog/category/add route 的代码(或者至少,我认为是这样,但该代码似乎没有任何代码内文档,因此很难确定),您会看到这个:

public function add() {
    $this->language->load('catalog/category');

    $this->document->setTitle($this->language->get('heading_title'));

    $this->load->model('catalog/category');

    if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validateForm()) {
        $this->model_catalog_category->addCategory($this->request->post);

        $this->session->data['success'] = $this->language->get('text_success');

        $url = '';

        if (isset($this->request->get['sort'])) {
            $url .= '&sort=' . $this->request->get['sort'];
        }

        if (isset($this->request->get['order'])) {
            $url .= '&order=' . $this->request->get['order'];
        }

        if (isset($this->request->get['page'])) {
            $url .= '&page=' . $this->request->get['page'];
        }

        $this->response->redirect($this->url->link('catalog/category', 'token=' . $this->session->data['token'] . $url, 'SSL'));
    }

    $this->getForm();
}

那么这里会发生什么?似乎当您 POST 到 catalog/category/add 时,它开始生成一个文档(我猜这就是前三行正在做的事情),然后它处理您的 POST 请求(我相信$this-&gt;model_catalog_category-&gt;addCategory($this-&gt;request-&gt;post);实际上添加了类别)。

然后,它重建 URL 以列出所有类别(我假设),并实际将响应重定向到该页面(请注意,仍在处理 POST 请求的服务器端代码中)。这一切都很好,实际上是大多数老式(AJAX 之前)应用程序的工作方式,但 UF 的做法略有不同。

UserFrosting 的路由(大部分)是 RESTful

在UF中,一个POST请求是RESTful,这意味着一个POST请求的唯一任务是修改一个资源。因此,当您在 UserFrosting 表单中单击“提交”时,POST 请求由 AJAX 在幕后分派,并在其中进行处理(成功更新资源并返回 HTTP 200 成功代码,或者由于某种原因失败并且返回错误代码)。如果在此请求之后需要刷新或重定向页面,由客户端 (Javascript) 代码负责执行此操作

推荐

我的建议是完全放弃 OpenCart 的控制器,并以 RESTful 模式重新实现它。因此,与其使用 OpenCart 的 add() 方法,不如使用以下方法:

  1. formCategoryAdd:生成添加类别的表单。这可能就像 OpenCart 的 getForm 方法的包装器一样简单。这与 UserFrosting 的 formUserCreate 所做的基本相同。
  2. addCategory:这实际上处理了添加类别的 POST 请求。同样,您可能需要在这里调用 OpenCart 的 addCategoryvalidateForm 方法。唯一的区别是您不会在完成后重定向请求。相反,您将向消息流添加一条成功消息(如果它成功添加了类别),或者您将添加一条错误消息,然后返回适当的错误代码(如果它由于某种原因而失败)。请参阅 UserFrosting 的 createUser 方法以了解其工作原理的示例。

然后,回到客户端,您需要一些 Javascript 来处理表单提交。您基本上可以从任何 UF 页面中窃取它。假设您的表单名为 add-category:

<script>
    $(document).ready(function() {            
      // Process form 
      $("form[name='add-category']").formValidation({
        framework: 'bootstrap',
        // Feedback icons
        icon: {
            valid: 'fa fa-check',
            invalid: 'fa fa-times',
            validating: 'fa fa-refresh'
        },
        fields: { "" : ""}
      }).on('success.form.fv', function(e) {
        // Prevent double form submission
        e.preventDefault();
        // Get the form instance
        var form = $(e.target);
        // Serialize and post to the backend script in ajax mode
        var serializedData = form.serialize();            
        var url = form.attr('action');
        $.ajax({  
          type: "POST",  
          url: url,  
          data: serializedData       
        }).done(function(data, statusText, jqXHR) {
            // Forward to account home page on success
            window.location.replace(site.uri.public);
        }).fail(function(jqXHR) {
            if ((typeof site !== "undefined") && site['debug'] == true) {
                document.body.innerHTML = jqXHR.responseText;
            } else {
                console.log("Error (" + jqXHR.status + "): " + jqXHR.responseText );
                // Display errors on failure
                $('#userfrosting-alerts').flashAlerts().done(function() {
                    // Re-enable submit button
                    form.data('formValidation').disableSubmitButtons(false);
                });
            }
        });
      });
    });        
</script>

如果您想减少客户端代码重复,我已将此 Javascript 放入 dev 分支中的单独函数中:https://github.com/alexweissman/UserFrosting/blob/dev/public/js/userfrosting.js#L58-L113

【讨论】:

  • 谢谢亚历克斯,没想到这个人自己会做出回应 :) 顺便说一句,爱用友。这绝对看起来像我将要做的事情,将需要一些时间来处理它 - 我的 PHP 非常生锈,所以我必须花一些时间来解决这个问题并弄清楚它。它会用一块石头杀死两只鸟,因为我也遇到了同样的问题,需要通过 ajax 加载报告过滤。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
相关资源
最近更新 更多