SilverStripe:控制器索引被调用两次

时间:2016-05-25 18:42:28

标签: silverstripe

我在使用Dutch psp Mollie进行结帐的测试实施时遇到问题。问题不在于Mollie的相关问题。发生的事情是下面的索引函数有时被调用两次,导致我的sales表中有两条记录。我有点不知道为什么会发生这种情况。下面我粘贴了我的测试代码,导致了奇怪的行为。我已经尝试改变路线,但无济于事。即使我将代码移到路由/test/send,或者将/test存根链接到另一个函数,例如'' => 'send',也会发生同样的情况。

数据对象"销售"除了默认的$ db和$ has_something等之外没有额外的代码。

更新:我删除了所有与Mollie相关的代码,应用程序仍在执行相同的操作。我认为重定向与它有关,因为当我删除它时,问题不会浮出水面(它只会在我删除之后首次重新加载,之后,重新加载只会导致数据库中的一行)。当重新加载到位时,它会更频繁地发生(但我仍然无法预测何时或为什么)。

Update2:我尝试了全新安装,但问题仍然存在。由于站点托管在LEMP堆栈上,我还尝试在LAMP堆栈上进行全新安装。还是同样的问题......

Update3:我做了一个仍然显示相同行为的代码的最小示例,并相应地更新了以下代码

class TestController extends Controller {

    public function index() {
        $sale = Sale::create();
        $sale->TicketName = "test ".date("Y-m-d H:i:s");
        $sale->write();
        return $this->redirect("http://other.site");
    }
}

销售数据对象

class Sale extends DataObject {
        private static $db = array(
                "TicketName"            => "Varchar(255)",
        );
}

class SaleAdmin extends ModelAdmin {
        private static $managed_models  = array('Sale');
        private static $url_segment     = 'Sales';
        private static $menu_title      = 'Sales';
}

这就是route.yml

---
Name: myroutes
After: framework/routes#coreroutes
---
Director:
  rules:
    'test' : 'TestController'

3 个答案:

答案 0 :(得分:3)

我认为您不需要index静态中的url_handlers引用。如果请求在index没有条目的情况下到达控制器,则会自动调用allowed_actions

另一个提示是,您可能会在访问当前SS_HTTPRequest实例的问题时遇到问题。而不是$this->request->getVar('foo')$request添加index() arg。 SS会自动将SS_HTTPRequest的当前实例作为第一个arg传递给所有控制器方法。

无论如何,取决于转储payment->getPaymentUrl()实际 URL的结果,我也怀疑它。您是否已将网络服务器的访问日志保留在第二次/双重请求发生时查看URL的样子?

答案 1 :(得分:3)

我发现了问题所在。它与Silverstripe无关,但我注意到我的Chrome浏览器正在调用我在按Enter键之前在位置栏中输入的网站。当我切换标签时也会这样做。所以,是的,这将导致多个调用,以及数据库中的多个行...

这是谷歌浏览器的预取功能的结果,它试图在导航到页面之前缓存页面。我认为这是一个愚蠢的功能,导致了大量不必要的流量,但我确实需要考虑它。

奇怪的是,当没有重定向时问题不会发生,因此这表明在这些情况下,chrome正在显示缓存页面而不执行新请求。重定向可能会使该缓存无效,从而强制对该URL进行两次点击...

此外,它可能不是生产环境中的问题,因为重定向只会在表单发布后调用,而不会在导航栏中输入。但还是......

谢谢大家的帮助!值得赞赏的是:)

答案 2 :(得分:2)

我认为您的主要问题是您从Page_Controller继承了子类。如果您的控制器不是页面控制器(例如,链接到SiteTree实例的控制器),则应该从Controller继承。

这样的东西对我有用,并且不会产生任何重复的条目:

class TestController extends Controller
{
    private static $allowed_actions = array(
        'result',
    );

    private static $url_handlers = array(
        'result/$Code' => 'result',
    );

    public function index() {
        // process request and write DataObject
    }

    public function result() {
        $code = $this->request->param('Code');
        // do soemthing with the result code
    }
}