PHP5 Forms with AJAX submit – best practices
Forms are the foundation of interactive web and what we call Web 2.0. In this article I will walk through the possible problems web developers encounter when creating web forms and solutions to those problems.
This article will be useful to people who are starting web development or who are experienced at it.
This article refers to Form implementation in Agile Toolkit. For documentation and demonstrations of forms in Agile Toolkit see http://agiletoolkit.org/doc/form
Basics of the form is that it may contain multiple input fields allowing web visitor to input some information in them. Form also may have one or several buttons and by clicking them data is being sent over to the server. Server can process the data and prepare the new page in return.
If you are using Agile Toolkit – it implements all the best form practices for you. Toolkit-related notes are listed in italic.
Agile Toolkit is Open-Source UI framework which can be used on it’s own or with other frameworks.
1. Submitting forms – POST, GET or $.ajax?
If you are going to save form data or email – then definitely POST. On other hand, GET is useful on search forms and in few other cases. For the framework use the POST dominates. In many cases forms require to send data to the server without changing page, that’s where “submit” event for the form can be re-defined and used to send AJAX request to the server.
My suggestion is to build forms which work through POST, however are enhanced with jQuery UI widget to enable submission through AJAX.
2. Handling form data and security considerations.
When you show the form, you might be doing some security checks. Such as – will your user have permission to post comments? When form is being submitted, it’s very important to perform the same checks before you will actually put data into the database. If you have 2 pages – one to show the form and other to handle it’s submitted data – this design is prone to human-errors where certain validation will not be performed on submissions allowing skilled hackers to bypass validation. The best approach is to have exactly same code to initialize the form and handle form submission.
There are many ways to approach input sanitization, however since PHP5.2 it includes a native way of doing input filtering and sanitization. http://www.php.net/manual/en/function.filter-input.php
In Agile Toolkit form class has function “isSubmitted()” which returns true only if form was successfully submitted and validated. All the initialization and validation you perform before adding form on the page will still be executed for submission. Also form is always submitted to the same page where it was created. This promotes proper behavior which is secure and consistent.
Agile Toolkit does not implement sanitization on it’s own, however it suggest to use built-in PHP filter. However even without filter, internal approach of handling data is secure:
When dealing with POST forms (without using AJAX), it is a good practice to issue “Redirect” on form submission. If you do not do that, web user might click refresh and send data to your form again. Many web software has this problem. So if you wish to display a success message to your user after form is submitted successfully – perform a redirect and forward user to a new page. If you pass message as GET argument, do not forget about threat of JS injection, htmlspecialchars($message) – should do the trick.
Agile Toolkit approaches double-posts by introducing a form submission verification. If user happens to click submit twice, it will ignore second click if first is still being processing.
In most cases today – form implementation in frameworks and web applications require developer to write the HTML code for all the forms independently. This design requires developer to either know HTML very well or sit in the same room with designer.
My suggestion is to categorize your forms into generic templates. Inside that template you would define header and footer of the form, button area and give generic template for the field.
If forms you create already have a generic template, they provide a number of benefits for development:
- Forms are consistent. Developer might pick from several looks depending on the situation, however a good designer will be able to prepare a nice and universal templates which will work in most cases.
- New form does not require anyone to write HTML.
In our typical web projects, I as developer can choose from several templates. If the form I’m creating is a data filter, I use horizontal template. If form goes into a sidebar, I use template with labels on top of fields. For the big forms I use the one with labels on the left and with space for field hints.
Actual layout of the forms is pretty common and is defined through HTML and CSS by our designer. As a result – I do not have to worry what will happen if label takes 2 lines of text instead of one and can create forms quickly and efficiently.
Creating a good and flexible form templates can take time – positioning hints, error messages and also allowing different types of fields to appear on form, testing those forms in multiple browsers is a hard work.
Agile Toolkit comes with few default templates and CSS themes for the forms allowing developers to create a new and stylish form with simply few lines of PHP code. Different projects may want to style forms, and it’s possible through use of CSS.
For developer not worrying about the looks and being able to produce forms on his own is really effective.
Use of form templates brings in a systematic design, but it looses in flexibility. In your project it might be a low priority goal, but at one point you will want to organize your form layout and make them more compact depending on the situation. Typical benefits of forms with custom layout is being able to put multiple short fields on same line, insert additional text elements inside the form.
Agile Toolkit allows to define layout to any form. This allows designer to provide a separate template for the form, which defines the flow of input elements. Inputs are still being produced by the framework, but where they are inserted is entirely up to the layout. Form will still rely on form template to get the <form> tag and button arrangements, layout is for fields only.
Using other UI elements inside form
Suppose you have a registration form and you want to add a button saying [Check availability] next to your login name. If you are using form templates and even form layout this still is a challenging task. Without use of a UI framework, I’m not even sure how to create this.
Benefits of Form Widget
By using jQuery UI widget which works well with the back-end it allows to perform several useful tasks often required by a web applications.
Agile Toolkit comes with ui.atk4_form.js widget, which offers: field reloading, error display, form submission handling, tracking of un-saved data inside form and better file upload handling.
Apart from the form widget used in Agile Toolkit I am not aware of any other open-source implementation which help to tie together form and backend framework. If you know of any – please advise.
The way how file uploads are implemented today is a complete mess. <input type=’file’> provides with a element allowing web user to pick file. When form is then submitted it transfers file over to the server.
However if you are using file uploads with the form which requires validation, then it introduces a number of problems. What if some of the fields were filled in incorrectly – will user have to re-upload the files? If you want to keep files on the server – you certainly haven’t created data record yet (because of validation issues), where would the file be stored and how would we know it have to be attached to the form? What if user wants to remove file he has already uploaded?
Because of those problem, many web applications will include a separate step for file uploading – this helps them avoid some of the problems, but not solve them.
There are 3 techniques for asynchronous file upload. When file is selected it is being transferred to the backend while user fills out rest of the fields. A most universal approach would create <iframe> and use it as form submission target. Another approach is to use Adobe Flash Uploader. This gives benefit of showing upload progress, however is difficult when it comes to universal styling and will make your web application dependent on Adobe Flash. Last approach allows to send files through AJAX request, but it is part of HTML5 and is still not very well supported by browsers. This method also allows to show upload progress bar and is the way how files will be uploaded in the future.
Implementing IFrame approach is not easy. Especially if you wish to upload multiple files in your form. Think as being able to add multiple attachments to your form as in your email program.
Final problem is – if your users upload files before submitting form – how will you identify those files and how will you make sure he is not hacking and attaching files just uploaded by someone else. Also – how do you clean up those files if user decided not to finish the form. And if you do store those files in a directory, you might be loosing some of the meta-data such as mime type or original filename.
This is kind of problem is almost impossible to fully resolve without use of the framework or libraries. Among many other things this is what Agile Toolkit allows developers to do.
It contain a field type “upload” which will create asynchronous upload component which is using iFrames and allows to upload one or multiple files (simultaneously!). Toolkit also solves the problem of storing files temporarily by relying on FileStore implementation. FileStore keeps file’s meta-data but also can contain information about who and when uploaded the file so you can track and clean them up.
By not burdening forms with multi-part submission we can now always rely on AJAX submits even if form contains one or several upload fields. Therefore if your form contains error they will be highlighted without interrupting file uploads.
Once file upload is finished, the component will display the filename and links to view, download or delete file from the server.
Button click detection
There are at least 3 ways to add a button to the form and they produce different results as well. <input type=submit name=a value=b> is the easiest to understand and handle. If you click such a button then a=b will be added to form input. However if user hits “enter” inside the form results can be quite interesting. Some browsers will make seem like the first button was clicked. Others will not allow to submit the form if it has more than one field or button – in other words – it’s a mess.
Then there are graphical buttons which use image. <input type=image name=a value=b>. Unfortunately instead of sending a=b they will send a_x=123&a_y=234 where numbers are coordinates of your click. This approach completely breaks consistency.
<button name=a value=b> element finally introduced some consistency and is a preferred way to go. It will also consistently send it’s value in normal POST forms.
However you might be using AJAX for submitting, right? Unfortunately AJAX submitters will most usually tap into form.submit() event and by that time information on which button was actually clicked is lost. As your favorite AJAX-form collects information from the field elements, it can no longer find out which button was actually clicked. As a result you need to create on-click handlers for all the buttons and pass this information through a hidden field of some sort.
In Agile Toolkit things like those take a couple of lines. Could be a single line, actually. $f->addSubmit(‘Save’)->isClicked(); Everything what happens between the browser and the backend would be sorted by Agile Toolkit.
Creating a good forms for your web application can be challenging at times. What seems to be initially simple can produce a lot of nasty problems. Some frameworks can help you to put HTML together, however they would be very limited at the interaction between the browser and the back-end.
Agile Toolkit is one of the UI libraries for the web trying to help. Comparing raw features it might be behind some of the other approaches, however the flexibility and simplicity of the design makes it advantageous in real commercial applications or open-source applications.