0

This issue came up while maintaining an application written in CakePHP 1.3. Please bear in mind that while I can and do read the docs, my experience with Cake is quite limited.

The application has a Widget model and a WidgetController. When editing a Widget, one option the user has is to massively import data into the Widget in one of three modes: add to, remove from, or replace the widget data with what is imported.

The current implementation is a total mess (there is an "edit" action which performs all the 10 or so different mutation functions a Widget supports; it decides what to do exactly by sniffing the parameters from the submitted form), so I broke the "massive stuff" into a new action:

function batch($id)
{
    // massively apply data to Widget $id; either add, remove or replace
}

This action is triggered by a form in the "edit" view:

// Only relevant elements shown
echo $form->create('Widget', array('enctype'=>'multipart/form-data', 'action' => 'batch')); ?>
echo $form->input('id');
echo $form->input('action', array('type'=>'select',
    'options'=>array(
        'append'=>__('Append', true), 
        'replace'=>__('Replace existing', true), 
        'delete'=>__('Delete specified', true)
    ));
echo $form->end(); ?>

As it stands, this form bundles the action parameter into the Widget array and the only way I can get hold of that from the controller is with $this->data['Widget']['action'].

This is ugly and semantically wrong, so I hope there's a better way to do it.

Ideally I 'd want to submit to the URL /widget/batch/X/append, but that's not possible because the append part is not fixed. So I 'd settle with any of these:

  • somehow pass the action as a controller parameter like $id
  • somehow pass the action as a named parameter, allowing $this->params['named']['action']
  • some other way that does not require installing a custom route and does not require JavaScript

Can Cake 1.3 do this?

Jon
  • 428,835
  • 81
  • 738
  • 806
  • @Ross: Multiple forms won't work because there are fields valid across all three modes. Multiple actions would require updating the form action with JS when the user selects an update mode. – Jon Dec 27 '12 at 14:33

1 Answers1

0

No

no you cannot route a request to a different action based on a post parameter, nor with php alone change the action of a form. This is likely to be the same with any framework.

Ideally I'd want to submit to the URL /widget/batch/X/append, but that's not possible because the append part is not fixed.

The only way to do that is with javascript - of course it's not hard to write some appropriate js to do that.

However

If you don't want to use javascript to manipulate the form action when the user changes their selection, or just want the simplest solution - you can use setAction to internally redirect the request to more appropriate, dedicated, controller actions:

function batch() {
    if (!empty($this->data['Widget']['action'])) {
        $this->setAction($this->data['Widget']['action']);
    }
}

function append() {
    if ($this->data) {
        if ($this->Widget->append($this->data)) {
            $this->Session->setFlash('Widget appended successfully');
        } else {
            $this->Session->setFlash('Error: Unable to append widget');
        }
    }
}

In this way you can likely refactor the existing code into more manageable and logical methods.

Community
  • 1
  • 1
AD7six
  • 63,116
  • 12
  • 91
  • 123