Passing parameters through form to Controller (CakePHP)

16,086

Solution 1

Nik's answer will fail if the website isn't in the server public_html root.

This answer is more solid:

<?php echo $form->create('Reservation',array('url'=>'/reservation/add/'.$data['id']));?>

Solution 2

Following the strictest convention for just a moment, reading a URL like /reservations/add/3 would be, well, confusing. You're calling on the ReservationsController to act on the Reservation model, but passing it an event ID. Calling /reservations/edit/3 is far less confusing, but just as wrong for your situation since the id value, "3", would be assumed to be a reservation identifier.

Essentially, you're making an ambiguous request at best. This is a simple form to create a reservation and that reservation has to be associated with an event. In a "traditional" scenario, the form would allow the user to select an event from some kind of list. After all, the foreign key, probably event_id in this case, is really just another property of a reservation. The list would have to be populated in the controller; this is usually done via a find( 'list' ) call.

If you already know the event that you want to create the reservation against (which you apparently do), then I'd probably select the analogous method of using a hidden field in the form. You still have to set the value in the controller just as you're doing, but the end result is a bit more Cake-y. The hidden field would be named data[Reservation][event_id] (again, I'm assuming the name of your foreign key field).

Solution 3

$form->create('Reservation',array('action' => 'add',$eventId);

and in the controller:

    function add($eventId = null)
    {

            if($eventId == null)
            {
                // error state
                throw new NotFoundException('Invalid id');
            }

    ...

    }

I do it all the time.

Solution 4

You can do following:

$form->create('Reservation',array('url' => $this->Html->url()));

this way all your variables from the url will be added in the form action :)

Solution 5

As Rob Wilkerson suggests, the issue is your URL route doesn't accurately describe the operation being performed. It becomes further confusing when you want to edit the reservation: /reservations/edit/6. Now the number in the URL means something different.

The URL convention I use for situations like these (adapted to your particular case) is /events/3/reservations/add. It takes a bit more up-front to configure your routes, but I've found it's superior for clarity down the road.

Sample routes.php:

Router::connect(
    '/events/:event_id/reservations/:action', 
    array('controller'=>'reservations','action'=>'index'),
    array(
        'pass' => array('event_id'), // pass the event_id as a param to the action
        'event_id' => '[0-9]+',
        'actions'=>'add|index' // only reverse-routes with 'action'=>'add' or 
                               // 'action'=>'index' will match this route
    )
)
// Usage: array('controller'=>'reservations','action'=>'add','event_id'=>3)

Router::connect(
    '/events/:event_id/reservations/:id/:action', 
    array('controller'=>'reservations'),
    array(
        'pass' => array('id'), // pass the reservation id as a param to the action
        'id' => '[0-9]+',
        'event_id' => '[0-9]+',
        'actions'=>'edit|delete' // only reverse-routes with 'action'=>'edit' or 
                                 // 'action'=>'delete' will match this route
    )
)
// Usage: array('controller'=>'reservations','action'=>'edit','event_id'=>3,'id'=>6)

In your FormHelper::create call, you'd have to specify most of the reverse-route you want to follow, but again, the up-front cost will pay dividends in the future. It's usually better to be explicit with Cake than to hope its automagic always works correctly, especially as the complexity of your application increases.

Share:
16,086
Jeroen Baert
Author by

Jeroen Baert

Computer Sciences engineer, technology enthousiast, improv player and aspiring game developer. I also talked to a girl once. :)

Updated on June 04, 2022

Comments

  • Jeroen Baert
    Jeroen Baert almost 2 years

    Okay, so I'm fairly new to CakePHP. This is the setup:

    I've got a Model (Reservation), and a controller, (ReservationController).

    I'm trying to provide a simple add() functionality.

    The request url is: www.example.com/reservations/add/3

    Where 3 is the ID of the event this reservation is for. So far, so good. The problem is, the form is constructed like this:

     <h2>Add reservation</h2>
    <?php echo $form->create('Reservation');
    echo $form->input('first_name');
    echo $form->input('last_name');
    echo $form->input('email');
    echo $form->input('tickets_student'); echo $form->input('tickets_nstudent');
    echo $form->end('Add');?>
    

    When I hit the send button, the request URL becomes simply www.example.com/reservations/add/, and the event id is lost.

    I've solved it now by grabbing the id in the controller, and make it available to the form:

    // make it available for the form
    $this->set('event_id', $eventid);
    

    And then, in the form:

    $form->create('Reservation',array('url' => array($event_id)));
    

    It works, but it strikes me as a bit ugly. Isn't there an easier way to make sure the form POST action gets made to the current url, instead of the url without the id?

  • Nik Chankov
    Nik Chankov over 13 years
    I agree with you, because I am using the same form for add and edit in my projects and it will be confusing, but if @Forceflow uses two separate actions, I believe it will be ok, because he will pass this variable only in add action. then in the edit one he will know the event and it wont be needed to be passed in the url. But there are too many if's in the our assumptions. :)
  • Daniel Wright
    Daniel Wright over 13 years
    You should correct the evaluation vs assignment bug in your conditional. =)
  • Leo
    Leo over 13 years
    thanks - I've just got in from work and have no real excuse ;) +1