2017-02-02 2 views
2

Ich habe eine benutzerdefinierte Route:

/create//$Action/$ID

Mit einer Aktion:

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")); 
} 

und eine eigene Form:

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); 
    } 
} 

Wenn der Pfad/create/Edit/das Upload-Feld funktioniert gut. Wenn der Pfad jedoch/create/Edit/1/lautet, antwortet der Server mit:

Die Aktion '1' ist in der Klasse UploadImportedCourseForm nicht verfügbar.

Eintauchen in die handleRequest in RequestHandler habe ich festgestellt das zweimal aufgerufen wird, wird jedes Mal 180 Zeile, wo es am Objekt sieht latestParam(). Das erste Mal, dass es die Aktion heißt, ist Edit, zu erwarten, aber beim zweiten Mal ist es 1, das ist eigentlich die ID.

Wie hat sich die Aktion in derselben Anfrage geändert und wie gehe ich vor, um mein Problem zu beheben? Die einzige Möglichkeit, wie ich dieses Problem umgehen kann, ist ein verstecktes Feld mit der ID.

+2

Sie haben 2 Handler mit dem gleichen Namen: Anforderungshandler (registriert mit benutzerdefinierten Route) und Form Action Handler (registriert von Formularobjekt) –

+1

Ich würde ein verstecktes Feld verwenden, wie Sie erwähnt haben. Das habe ich in der Vergangenheit an Projekten gemacht. –

+0

@GregSmirnov Also der Formularaktionshandler ist derjenige, der bricht? Wenn ich url_handlers in dieser Klasse mit der gleichen von meiner benutzerdefinierten Route überschreiben, glaubst du, dass das funktioniert? – Rudiger

Antwort

1

Im Allgemeinen sollten Methoden zum Erstellen von Formularen nicht übermäßig komplex sein. Sie müssen nur ein Formular zurückgeben. In Bezug auf die dynamische ID könnten Sie dies auf verschiedene Arten tun - Sie könnten die ID über ein verstecktes Feld eingeben und eine Methode wie getIDFromRequest() erstellen, die sowohl die URL als auch den Anfragetext überprüft.

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); 
    } 
} 

Alternativ auf dem, was ich ableiten kann, dass Sie zu tun versuchen, denke ich, ein Subzentrale hier viel mehr Sinn machen würde. Erstellen Sie einen separaten Anforderungshandler, der ID-fähig ist. Dadurch können Sie viel sauberer skalieren, wenn Sie viele dieser Arten von Operationen ausführen.

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); 
    } 
} 

Ihre Subzentrale ist Datenobjekt-aware, so dass es nie eine Verwirrung darüber, wo die Dinge herkommen. Sie haben die Abstraktion von Post-Vars und URLs daraus gezogen.

+0

Während ich sehe, wie Ihre Subcontroller-Lösung funktionieren würde, denke ich, dass ich nur das versteckte Feld mache, weil ich das nur gelegentlich tun werde. Ich werde die Subcontroller-Lösung wieder besuchen, wenn ich mehr Zeit habe. – Rudiger

Verwandte Themen