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

SilverStripe: Controller index is called twice

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

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

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

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

更新 3:我制作了一个仍然显示相同行为的最小代码示例,并相应地更新了下面的代码

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'

我认为您不需要 url_handlers 静态中的 index 引用。如果请求到达控制器而没有在 allowed_actions 中输入,index 会自动调用。

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

无论如何,根据 actual URL 转储 payment->getPaymentUrl() 时的结果,我也怀疑这一点。您是否跟踪了您的网络服务器的访问日志以查看每当发生第二个/双重请求时 URL 是什么样子?

我认为您的主要问题是您从 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
    }
}

我找到问题所在了。它与 Silverstripe 无关,但我注意到我的 Chrome 浏览器正在调用我在按回车键之前在地址栏中输入的站点。当我切换标签时它也会这样做。所以是的,这将导致不止一次调用,并且数据库中不止一行......

这是 google chrome 的预取功能的结果,它会在您导航到页面之前尝试缓存页面。我认为这是一个愚蠢的功能,会导致大量不必要的流量,但我确实需要考虑到这一点。

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

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

谢谢大家的帮助!不胜感激:)