handleRequest()在同一个请求中调用了两次,$ Action是不同的

时间:2017-02-02 10:34:43

标签: php silverstripe

我有自定义路线:

/create//$Action/$ID

行动:

public function Edit(SS_HTTPRequest $request) {
    $id = $this->getRequest()->params()['ID'];
    if($this->request->isPost()) return UploadForm::create($this, 'Edit/' . $id, 'SubmitImportedModule');;
    return $this->renderWith(array("Edit", "Page"));
}

自定义表单:

class UploadForm extends Form {
    public function __construct($controller, $name, $action) {
        $fields = FieldList::create(
            TextField::create('Title', 'Title'),
            $course = UploadField::create('Upload', 'Upload')
        );

        $actions = FieldList::create(
            FormAction::create($action, 'Add Resource')
        );
        $validator = RequiredFields::create('Name');

        parent::__construct($controller, $name, $fields, $actions, $validator);
    }
}

如果路径为/ create / Edit /,则上传字段工作正常。但是,如果路径为/ create / Edit / 1 /,则服务器响应:

  

行动' 1'在UploadImportedCourseForm类上没有。

深入研究handleRequest中的RequestHandler我发现这被调用两次,每次都到达第180行,在那里查看对象latestParam()。第一次它被称为动作是编辑,但是第二次它是第一次它是1,这实际上是ID。

如何在同一请求中更改操作以及如何解决问题?我认为我可以解决这个问题的唯一方法是使用带有ID的隐藏字段。

1 个答案:

答案 0 :(得分:1)

通常,创建表单的方法不应过于复杂。他们只需要退回表格。关于动态ID,您可以通过几种不同的方式执行此操作 - 您可以通过隐藏字段传入ID,并创建像getIDFromRequest()这样的方法来检查URL和请求正文。

private static $allowed_actions = ['EditForm'];

public function EditForm() {
    return UploadForm::create($this, __FUNCTION__, 'yourAction');
}

class UploadForm extends Form {
    protected function getIDFromRequest(SS_HTTPRequest $r)
    {
        return $r->param('ID') ?: $r->postVar('ID');
    }

    public function __construct($controller, $name, $action) {
        $fields = FieldList::create(
            TextField::create('Title', 'Title'),
            HiddenField::create('ID','', $this->getIDFromRequest($controller->getRequest())),
            $course = UploadField::create('Upload', 'Upload')
        );

        $actions = FieldList::create(
            FormAction::create($action, 'Add Resource')
        );
        $validator = RequiredFields::create('Name');

        parent::__construct($controller, $name, $fields, $actions, $validator);
    }
}

或者,基于我可以推断出您尝试做的事情,我认为子控制器在这里会更有意义。创建一个可识别ID的单独请求处理程序。如果您正在进行大量此类操作,这将使您可以更加干净地扩展。

private static $url_handlers [
    'yourpath/$ID' => 'handleEditForm'
];
private static $allowed_actions = ['handleEditForm'];

public function handleEditForm(SS_HTTPRequest $r)
{
    $obj = SomeObject::get()->byID($r->param('ID')) {
        if(!$obj) $this->httpError(404);
    }

    $handler = new MyController_EditRequest($this, $obj);
    return $handler->handleRequest($r, DataModel::inst());
}

class MyController_EditRequest extends RequestHandler
{
    protected $parent;

    protected $obj;

    private static $allowed_actions = ['edit', 'EditForm'];

    public function __construct(MyController $controller, SomeDataObject, $obj)
    {
        $this->parent = $controller;
        $this->obj = $obj;

        parent::__construct();
    }

    public function edit(SS_HTTPRequest $r) 
    {
        return $this->renderWith(['SomeTemplate_edit','Page']);
    }

    public function Link()
    {
        return $this->parent->Link('yourpath/'.$this->obj->ID);
    }

    public function EditForm()
    {
        return UploadForm::create($this, __FUNCTION__, 'yourAction', $obj->ID)
    }
}

class UploadForm extends Form {

    public function __construct($controller, $name, $action, $id) {
        $fields = FieldList::create(
            TextField::create('Title', 'Title'),
            HiddenField::create('ID','', $id),
            $course = UploadField::create('Upload', 'Upload')
        );

        $actions = FieldList::create(
            FormAction::create($action, 'Add Resource')
        );
        $validator = RequiredFields::create('Name');

        parent::__construct($controller, $name, $fields, $actions, $validator);
    }
}

您的子控制器是DataObject感知的,因此对于事物的来源绝不会产生任何混淆。您已经从中抽取了后变量和URL。