Say Geese!

CakePHP is in many ways an awesome framework. It does lots of things for you automagically, and makes development quite pleasant on most days. However, there are a few places where the framework displays irritating glitches.

One of those unlucky places is when you want to use an image as the submit button for your forms.

The official $form helper documentation lists the various methods available for creating HTML forms in CakePHP. In there, it mentions that you can make $form->end() use an image, by coding the image as the first parameter of the method:

//in your ctp file

<?php
    echo $form->create('Person', array('target'=> '_parent','action' => 'save', 'name' =>'saveForm') );
    echo $form->input('name');  
    echo $form->input('surname');
    echo $form->input('nickname');
    echo $form->end('Save.png'); //Note that the image must reside in your webroot/img folder.
?>

When you do that, the $form->end() method creates the following for you (where baseurl is your Dispatcher::baseUrl() value) :

<input type="image" src="/baseurl/img/save.png">

This may sometimes be exactly what you want. But there’s a caveat here – consider the following:

//in your ctp file

<?php
    $options = array('div'=>false,'name' => 'save','onclick' => "foo();");
    echo $form->create('Person', array('target'=> '_parent','action' => 'save', 'name' =>'saveForm') );
    echo $form->input('name');  
    echo $form->input('surname');
    echo $form->input('nickname');
    echo $form->end('Save.png',$options);
    .
    .
    <script type="text/javascript">
        function foo() {
            //do anything
        }
    </script>
?>

In the code snippet above, I add some options to the $form->end() method. Most importantly – I try and add an onclick= attribute to the image. I want something to happen just before the form is submitted.
But Cake is not happy to oblige. In fact, the resulting xhtml for both of the previous snippets is the same:

<input type="image" src="/baseurl/img/save.png">

Cake, apparently, disregards the $options array if it receives an image name as $form->end() ‘s first parameter.
Frustration ensues.

Luckily though, we don’t have to use $form->end() to create a submit element for the form. Cake also has the $form->submit() method, which allows us to play a bit with the options and come up with a solution:

//in your ctp file

<?php
    $options = array('div'=>false,'name' => 'save','onclick' => "foo();");
    echo $form->create('Person', array('target'=> '_parent','action' => 'save', 'name' =>'saveForm') );
    echo $form->input('name');  
    echo $form->input('surname');
    echo $form->input('nickname');
    echo $form->submit('Save.png',$options);
    .
    .
    <script type="text/javascript">
        function foo() {
            //do anything
        }
    </script>
?>

The $form->submit method honors the $options array. We don’t even have to tell it that the type of the submit element is an image – the method works it out all by itself, resulting in:

<input type="image" name="save" onclick="foo();" src="/baseurl/img/save.png">

and all is well on this front.

And just one Security.php note

While the code in the last snippet above works, it will fail you if you use the Security component.
With the Security component, Cake adds tokens to each form it creates.
When the user submits the form back to the server, Cake can check that the token submitted matches the token created, and know that it did in fact generate the form. This (and other methods) provide some protection against CSRF attacks.

However, these tokens are only generated for forms created and closed with the $form->create() .. $form->end() methods. The snippet above does not use $form->end() – so while it works, the form is going to be useless if you use the Security component.

This is easy to fix – just add $form->end() to ensure that the token generation is called correctly:

//in your ctp file

<?php
    $options = array('div'=>false,'name' => 'save','onclick' => "foo();");
    echo $form->create('Person', array('target'=> '_parent','action' => 'save', 'name' =>'saveForm') );
    echo $form->input('name');  
    echo $form->input('surname');
    echo $form->input('nickname');
    echo $form->submit('Save.png',$options);
    echo $form->end();
    .
    .
    <script type="text/javascript">
        function foo() {
            //do anything
        }
    </script>
?>

and ther you have it- Submitting a CakePHP form with an image, with an onclick= attribute configured, and as a bonus – with the Security token generated (if you’re using the Security component).

Popularity: 61% [?]

Tagged with:
 

2 Responses to How to submit a form with an image in CakePHP

  1. Ayo Akinyemi says:

    Thanks.
    Used this;
    submit(‘submit’, array(‘type’ => ‘image’, ‘src’ =>
    $this->webroot . ‘img/myimage.jpg’, ‘height’ => ’15′, ‘width’ => ’13′)); ?>

    But yours is more cleaner.

  2. christian cscc says:

    Thanks.
    I was searching the solution for that problem. And you have helped me.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Set your Twitter account name in your settings to use the TwitterBar Section.