clonefish complete reference


1 The class

introduction

Clonefish itself is a class hierarchy. We'll mostly work with the main class, which is the clonefish class. To use clonefish, we have to:

  1. create an instance of this class, and
  2. define the form fields using the configuration array (the format of this array is described under "Input types" and "Validation types" in the menu).
  3. if values are received from a submitted form, we use the $form->validate() method
  4. display the output using the $form->getHTML() method

On the first glance, it might seem to be too much work for a simple form, but when you start using clonefish, you'll find it very handy and efficient for more complicated forms - and it's always the same few lines code as above, just with a different configuration array!

Beyond the basics there are additional features already proven in dozens of applications, like:

  • template engine support: $clonefish->getVars()
  • invalidation: $clonefish->invalidate(), $clonefish->addMessage()
  • accessing element objects: $clonefish->getElementByName(), $clonefish->getValue()

A simple example:


<?php

include('clonefish/clonefish.php');
include(
'clonefish/messages_en.php');

$config = Array(
  
'login' => Array(
    
'type'        => 'inputText',  // type of field
    
'displayname' => 'Your name:'// label
    
'help'        => 'Please enter your name!'
       
// help message to display for invalid input values
    
'validation'  => Array(
       Array( 
'type' => 'required' )
       
// don't accept empty inputs
    
)
  ),
);

$clonefish = new clonefish'loginform''test.php''POST' );
$clonefish->addElements$config$_POST );

if ( isset( 
$_POST['login'] ) && $clonefish->validate() ) {
  
// do some action here
}
else
  echo 
    
"<html><body>" 
    
$clonefish->getHTML() .
    
"</body></html>";

?>





1.1 Properties

properties controlling behaviour

codepage, multibytesupport, multibytesetup

Proper string validation means that we also care about the codepage - just think of multibyte characters in UTF-8: checking length of these strings or using a byte-safe regexp needs attention! For this reason you must set the way Clonefish handles codepages:

$form->codepage         = 'utf-8';
$form->multibytesupport = 'multibyteutf8';

For the impatient: the best bet is $form->multibytesupport = 'multibyteutf8' - which is the default setting. It assumes you use UTF-8 in your application/website and have multibyte support enabled. This combination uses preg as regexp function (which supports UTF-8 encoded regular expressions). 

If you use other codepages or don't have multibyte support, you have the following built-in options:

$form->multibytesupport when to use? extension needed  strlen function call,
preg function call,
function call to set codepage
none plain ascii text strlen(%s)
preg_match('%s', '%s')
-
multibyte

any codepage (even multibyte) + ereg

multibyte mb_strlen(%s)
mb_ereg('%s','%s')
mb_internal_encoding('%s')
multibyteci any codepage (even multibyte) + case insensitive ereg multibyte mb_strlen(%s)
mb_eregi('%s', '%s')
mb_internal_encoding('%s')
multibyteutf8 best bet for UTF-8 with preg multibyte mb_strlen(%s)
preg_match('%su', '%s')
mb_internal_encoding('%s')
iconv if mb_* is missing: SINGLE byte charsets only iconv iconv_strlen(%s)
preg_match('%s', '%s')
iconv_set_encoding('internal_encoding', '%s')
iconvutf8 if mb_* is missing: UTF-8 only iconv iconv_strlen(%s)
preg_match('%su', '%s')
iconv_set_encoding('internal_encoding', '%s')

 

These combinations seem to cover all the options available in PHP - however, you can still define your own settings in $form->multibytesetup.
 

js

$clonefish->js = 1;

If set to 1, clonefish will generate JavaScript validation code when getHTML() method is called. Default value: 1.

jsalert

$clonefish->jsalert = 1;
$clonefish->jsalertmessagecontainerlayout = '%s';
$clonefish->jsalertmessagelayout          = '- %s\n';

If set to 1, clonefish will use window.alert() to show error messages when the client side validation fails. The error messages will be rendered using the other two attributes.

jshtml

$clonefish->jshtml = 1;
$clonefish->jshtmlmessagecontainerlayout = '%s';
$clonefish->jshtmlmessagelayout          = '%s<br            />';

If set to 1, clonefish will attach the error messages to the input elements when the client side validation fails. The error messages will be rendered using the other two attributes.

To use this feature, you need to use the %errordiv% placeholder in $clonefish->layouts layout settings. During form HTML rendering the %errordiv% gets replaced by a HTML snippet of a hidden div for each element where the appropriate error message will be injected into.

jspath

$clonefish->jspath = 'clonefish/clonefish.js';

Path to the JavaScript code used by the validation procedure. The path will be written in the src parameter of the script tag, for example: <script src="clonefish/clonefish.js" type="text/javascript">, so you have to use either a relative or an absolute URI here.

onbeforesubmit

In case you need to run some JavaScript right after successful form validation but still before the data is submitted to the server, use this parameter. Your code will be injected in the validation function, right above the form.submit() call. It's very useful when you want to disable submit buttons once pressed to avoid repeated form submission.

dbtype

$clonefish->dbtype = 'adodb';

This property determines the database wrapper class to use. By default, clonefish provides the following wrappers:

  • 'adodb' for AdoDB library
  • 'peardb' for Pear DB library
  • 'mysql' for the built-in PHP MySQL function
  • 'pdo' for the built-in PHP PDO extension

These options cover virtually all RDBMS-es - however, you can easily create your own wrapper class by copying and modifying any existing class!

Being a frequently used setting you can also specify this attribute in the constructor of clonefish (together with a reference of a valid connection resource or connection object).

target

The target="" attribute of the form. Default to "_self". It's the %target% placeholder in the $clonefish->formopenlayout attribute.

configfilter

You can use simple text config files to store any attributes of the clonefish class (so it's meant to store form level settings, as element level settings are stored in PHP arrays). Sometimes you may want to use variables or placeholders in your config files for example to support multilingual sites or introduce some sitewide configuration variables: in such cases you can use the configfilter attribute to specify a function name which does the actual replacements.

properties controlling output/layout

formopenlayout, formcloselayout

$clonefish->formopenlayout = 
  "<form %onsubmit% " . 
        "enctype=\"multipart/form-data\" " . 
        "target=\"%target%\" " . 
        "name=\"%name%\" " .
        "action=\"%action%\" " . 
        "method=\"%method%\"" . 
  ">\n";
$clonefish->formcloselayout = '';

The form open/close tags. The form open layout has several placeholders, all of them are attributes of the clonefish class. The name, action and the method are required parameters of in the clonefish constructor.

The onsubmit placeholder is set by clonefish to the validation JavaScript function when JS validation is used. Form target is "_self" by default.

prefix, postfix

$clonefish->prefix  = '';
$clonefish->postfix = '';

Form prefix/postfix. Useful if you'd like to display some form information (eg. instructions, etc.) above or below the form. Contents will be place right before the <form> and after the </form> tags.

layout

$clonefish->layout = 'tabular';

To choose from the possible layouts definend in $clonefish->layouts, use an index of the $layouts  here.
The default value is tabular, resulting in a table based form.

layouts

$clonefish->layouts is an associative array containing arrays of HTML snippets. These snippets are used to render the form HTML when getHTML() is called.

You can choose the current layout using the $clonefish->layout attribute. There are two basic layouts: tabular and rowbyrow.
Feel free to set up new layouts - just create a new array, and use its array key in the layout property.

  • The tabular layout is a container table, which includes one or more element rows and a buttonrow:

    %displayname% %erroricon% %prefix%%element%%postfix%%errordiv%
      %button%

    A tabular form with a valid and an invalid row looks like this:
      (international format)
     
     
    The default configuration is:
    $clonefish->layouts = Array(
      'tabular' => Array( 
    
        'container' =>  
          // the container for the form elements, where %s is the content
          '<table cellpadding="5" cellspacing="0" border="0">' .
            "%s" .
          '</table>\n',
    
        'element' =>
          // the table row containing one element
          '<tr %errorstyle%>' .
          '  <td width="120" align="right">' .
          '    <label for="%id%">%displayname%</label>' .
          '  </td>' .
          '  <td width="15">' .
          '    %erroricon%' .
          '  </td>' .
          '  <td>' .
          '    %prefix%%element%%postfix%%errordiv%' .
          '  </td>' .
          '</tr>',
    
        'errordiv'   => 
          // the hidden DIV where JS injects error messages for each element
          '<div id="%divid%" style="visible: hidden; display: none;"></div>',
    
        'button'     => 
          // submit button
          '<input type=submit value="OK"            />',
    
        'buttonrow'  => 
          // the row container for the submit button
          '<tr><td colspan=2></td><td>%s</td></tr>',
      )
    );
    
  • The rowbyrow layout is even simpler:

    %displayname% %erroricon%
    %prefix%%element%%postfix%%errordiv%
    %button%

    Example of a valid and an invalid row:


    (international format)




     
    The default configuration is:
    $clonefish->layouts = Array(
    
      'rowbyrow' => Array(
        // the container for the form elements, where %s is the content
        'container'      => '%s',
    
        'element'        => 
          // the HTML snippet containing one element
          "<label for="%id%">%displayname%</label> %erroricon%<br>\n".
          "%prefix%%element%%postfix%%errordiv%\n".
          "<br><br>\n",
    
        'errordiv'   => 
          // the hidden DIV where JS injects error messages for each element
          '<div id="%divid%" style="visible: hidden; display: none;"></div>',
    
        'button'     => 
          // submit button
          '<input type=submit value="OK"            />',
    
        'buttonrow'  => 
          // the row container for the submit button
          '%s',
      )
    );
    

The placeholders provided during rendering the form HTML:

  • %id% is the field id used with <label> to create accessible forms. %id% defaults to the field name, and may be configured for any element.
  • %element% is the generated HTML snippet of an element.

Placeholders provided by form class attributes:

  • %errorstyle% gets replaced by the $clonefish->errorstyle attribute. Used only if a field is invalid on the server side.
  • %errordiv% is the container for JS-injected error messages if $clonefish->jshtml is used. This DIV should be hidden normally by default.

Placeholders provided by elements (your form configuration):

  • %displayname%, %prefix%, %postfix%: element settings

layoutcleanup

$clonefish->layoutcleanup = true;

If you use the label tags in your layout to create accessible forms, empty label tag pairs might be created when there's no displayname specified for an element (for obvious reasons: <label for="%id%">%displayname%</label>). If this property is set to true, such empty tag pairs are removed. By default, it's set to true.

outputmessages 

$clonefish->outputmessages = 1;

If set to 1, clonefish will display error messages above the form in an unordered list. Default value: 1.

erroricon

$clonefish->erroricon = '<img src="images/erroricon.gif"            />';

A string displayed next to the form field names when server side validation fails. You'll find its %erroricon% placeholder counterpart in the layout arrays.

errorstyle

$clonefish->errorstyle = 'style="background-color: #e95724; "';

A string used in the output for an invalid input. You'll find its %errorstyle% placeholder counterpart in the layout arrays.

messageprefix, messagecontainerlayout, messagelayout, messagepostfix

When server side form validation fails, these attributes are used to format the error messages.

$clonefish->messagecontainerlayout = '<ul>%s</ul>';
  // %s: placeholder for 'messagelayout' rows

$clonefish->messagelayout  = '<li>%s</li>';
  // %s: placeholder for error messages
$clonefish->messageprefix  = FORM_ERRORS; 
  // 'messageprefix' is shown above the message container layout. 
  // FORM_ERRORS are defined in messages_en.php

$clonefish->messagepostfix = '';         // shown below error messages
  // 'messagepostfix' is shown below the message container layout.

showerroricon

Enable or disable displaying the error icon when server side form validation fails. Has the same effect as removing the %erroricon% placeholder from the $clonefish->layouts array.

submit

While creating multilingual websites or applications, you may need to easily change strings in your form - one of them is the text on the submit button represented by this attribute. To use this string, you can put the %s placeholder in the 'button' HTML snippet in your layout array. It's a simple way to change the button text, as you don't need to mess with the button's HTML code.




1.2 Layout overview

Generating forms is an automatic process, which is quite comfortable from the programmer's perspective - though it's no doubt that the client won't care about the beauty of a rock solid form generating method. In fact, the clients will only care about two things:

  • does it all work?
  • how does it look like?

The answer for the first answer is clonefish itself, being built to create well working forms, so let's focus on the second question: the layout.

Good news: speaking of form design there's nothing that couldn't be done using clonefish. For very complicated and "deeply designed" forms it can be tricky for the first time to "re-create" all the bells'n whistles of a beautiful form that your web designer colleague created - that's why it's important to get an overview of the layout options you have with clonefish.

in general

In clonefish, there are predefined settings that can be used to precisely override the default layouts. These settings are:

  • properties of the clonefish class itself:
    • they define the form layout itself and the default container of all the elements. These settings are required, in case they're not defined well, your form will look/behave strange.
  • there are also settings on the elements' level, placed in the configuration array:
    • you can either override the form-level element container settings (the layout/alignment of the entire element row)
    • or customize the default layout of the element control itself (eg. alignment of radio buttons)
    • However, when you'd like to customize the layout of and element (eg. a radio button group), you'll need the element level settings: these can be different for every element.

 

examples, use cases

level 1 - adding a class to an input field

In case you'd like to add special parameters in the tag for an element, you can use the 'html' setting for any element, for example:

<?php
$config 
= Array(
  
'name' => Array(
    
'displayname=> 'Your name:',
    
'type'        => 'inputText',
    
'html'        => 'class="nameclass"',
  )
);
?>

This is also the perfect way to add event handlers, special parameters to form elements (rows=N, cols=M for a textarea, multiple="multiple" for a select and so on)

level 2 - customizing elements

There are elements that are "rendered" themselves: for example inputRadio (radio button group) has a container containing multiple items, each item having a radio button and its label. That's why inputRadio has two layout settings:

  • 'layout' is the layout for the container. For example, if your layout looks like <ul>%s</ul>, the items will be inserted between <ul> and </ul>
  • 'itemlayout' is the layout for the items. Assuming the above example, you should set itemlayout to <li> %radio% %label% </li>. The %radio% and %label% are the placeholders for the button itself and the corresponding value.

 

level 3 - element row with a different layout

Imagine you have a form that uses tables - the table structure is defined at form level, it's a simple 2 column layout (one for the input name and one for the input itself).

Let's say we need a very large textarea spanning both columns - in this case you can use the 'rowlayout' setting for this element. This setting overrides the form-level 'element' setting which was defined under $form->layouts: you can freely reuse all the %placeholders% here.

level 4 - templating

Templating is the most powerful method Clonefish provides for reorganizing elements in a form. In Clonefish, templating means the usage of the template element type. This type has one important attribute: the value. In value you can use placeholders derived from the form you're creating: for example, if you have an element called login being a textfield, you can use %login% in the template, where the login element's row will be displayed.

Furthermore in most cases

  • you don't want to show the original element: this is achieved by setting display => false for that element
  • and most likely you'll want to use some different row layout than the original: that's the rowlayout setting is good for those elements

Let's see an entire example:

<?php
$config 
= Array(

  
'login' => Array( 
    
'type'        => 'inputText'
    
'displayname=> 'Login'
    
'display'     => 0,
    
'rowlayout'   => '%prefix%%element%%postfix%',
  ),

  
'password' => Array( 
    
'type'        => 'inputText'
    
'displayname=> 'Password'
    
'display'     => 0,
    
'rowlayout'   => '%prefix%%element%%postfix%',
  ),

  
'logintemplate' => Array(
    
'type'  => 'template',
    
'value=> '
      <table>
        <tr>
          <td>%login%</td>
          <td>%password%</td>
        </tr>
      </table>
    '   
  
)

);
?>

The above configuration will display a form with two fields next to each other thanks to the table used in the template. The original elements will not be displayed above the tepmlate elements thanks to the display => false setting, and as we did not use %displayname% in the rowlayout parameters, no field labels will be shown (naturally you could still include or exclude any placeholder available in the form layout arrays). Though we did not use the displayname here, there's still one advantage of using it: when using a validation for such elements, the error message will use it to refer to input elements.

level 5 - using variables in a template engine

When you are about to build forms with complex layouts, it's handy to build the structure of the form in template engines like Smarty. Clonefish supports such templating simply by exporting the parts of the form in an array you can assign to your choice of template engine like this:

$smarty->assign( 'form', $clonefish->getVars() );

This way you'll get an array with the following indexes: fields, formopen, formclose, script, messages, messageslayout of which fields and messages are arrays of the form elements and the validation error messages (these values are described under the getVars() method).

When using this method you can make use of the rowlayout setting for any element to redefine the layout of a single element row, and also the $clonefish->layouts array which includes the default settings.




1.3 Methods

 




1.3.1 constructor

constructor - Creates a clonefish instance to represent a form.

Description

class clonefish {
  clonefish clonefish() ( 
    string $name, string $action, string $method 
    [, mixed $db = null, string $dbtype = 'mysql' [, mixed $refid = null ]]
  )
}

Creates a clonefish instance to represent a form.

Parameters

name

The name="" parameter of the form tag. Also used to name the JavaScript validation function, as multiple forms on the same page need to have separate validation functions.

action

The action="" parameter of the form tag (the script name the form will be submitted to)

method

The method="" parameter of the form tag (GET or POST)

db

If you use dynamic fields or the database validation, here you'll need to pass a connection resource or a database connection reference:

  • if you use the 'mysql' database wrapper (which uses the built-in mysql functions like mysql_query() ), you are not required to use this parameter. If the link identifier is not specified (or is null), the last link opened by mysql_connect() is assumed.
  • if you use the 'adodb' database wrapper, pass an AdoDB object
  • if you use the 'peardb' database wrapper, pass a Pear DB object
  • if you use the 'mdb2' database wrapper, pass a Pear MDB2 object
  • if you use the 'pdo' database wrapper, pass a PHP PDO object

dbtype

This parameter allows you to define the database wrapper to use. It determines the filename and the class name of the wrapper, so if you want to create your own wrapper, follow this naming convention:

dbwrapper_dbtype.php
class DBWrapperdbtype

Creating a wrapper class is very easy: feel free to check the classes already available, and create your own! Currently the available following options are available: mysql, pdo, adodb, peardb, mdb2

refid

This parameter is used by the selectDynamic element. When an ID is passed, you can reuse it in the 'valuesql' setting of a selectDynamic element to pre-select options of a multiple select. In a typical 1-N database relation this is the ID of the single ("1") side of the relation.

Return Values

Returns a clonefish object on success. The constructor dies with an error message if an error occurs.

Examples

Example 1: create a form without a database connection.

<?php

  $form = new clonefish( 'loginform', 'login.php', 'POST' );

?>


Example 2: create a form with an implicit MySQL connection

<?php

  // Clonefish defaults to the MySQL database 
  // type, so both of these lines allow using database
  // related elements. You need to have an open MySQL 
  // connection.

  $form = new clonefish( 'loginform', 'login.php', 'POST' );
  $form = new clonefish( 'loginform', 'login.php', 'POST', null, 'mysql' );

?>


Example 3: create a form with an explicit database connection

<?php
  // If you use multiple connections or a different database
  // wrapper, just pass your database link resource or 
  // connection object:

  $mysql_link = mysql_connect( [...] );
  $form = new clonefish( 
    'loginform', 'login.php', 'POST', $mysql_link, 'mysql'
  );

  $form = new clonefish( 
    'loginform', 'login.php', 'POST', $conn_object, 'adodb'
  );

?>

 




1.3.2 addElements()

clonefish->addElements() - add configuration and values for the form elements.

Description

class clonefish {
  void addElements( array $elements [, array $values, $quotes_already_added ] )
}

The heart of clonefish: with this method you can pass your configuration array to clonefish, which is used to create the HTML code and the validation code fragments. To learn about the configuration array, visit the form input types and the form validation configuration pages.

Parameters

$elements

Associative array of element configuration.

$values

Associative array of element values, like

Array( 'fieldname' => 'value' )

Mostly used with the $_GET or $_POST array when processing a submitted form, or database records when preparing a modification form. This is an optional parameter, but if it's set, the third parameter is also required.

$quotes_already_added

Used to enable/disable stripslashes() on the array items given in the second parameter. By concept in Clonefish there should be no magic slashed data: if you're using the second parameter, you have to tell Clonefish whether the values passed are 'magically quoted', or not.

Examples


<?php

  $elements 
= Array(
    
'name' => Array(
      
'type' => 'inputText',
      
'displayname' => 'Please enter your name'
  
);

  
$values = Array(
    
'name' => 'James Bond'
  
);
  
// the $values array might be a $_GET or 
  // $_POST array, or a database query result
  // (or some array built manually)

  
$form->addElements$elements$_GETget_magic_quotes_gpc() );
  
$form->addElements$elements$_POSTget_magic_quotes_gpc() );
  
$form->addElements$elements$values);
  
$form->addElements$elementsmysql_fetch_row(), );
  
$form->addElements$elements$adodbresult->fields);
  
// note the third parameter for 
  // arrays that don't go through magic quoting!

?>





1.3.3 getHTML()

clonefish->getHTML() - returns the entire (X)HTML and JavaScript code of the form in a string.

Description

class clonefish {
  string getHTML( void )
}

Returns the entire (X)HTML and JavaScript code of the form in a string. The $clonefish->jspath attribute is required to use the clientside JavaScript validation. The HTML code is generated from the HTML snippets defined in the $clonefish->layouts attribute, and also affected by these clonefish attributes:

  • layout
  • layouts
  • js
  • jspath
  • jsalert, jsalertmessagecontainerlayout, jsalertmessagelayout
  • jshtml, jshtmlmessagecontainerlayout, jshtmlmessagelayout
  • outputmessages
  • showerroricon
  • erroricon
  • errorstyle
  • prefix
  • postfix
  • messageprefix
  • messagecontainerlayout, messagelayout
  • messagepostfix
  • formopenlayout
  • formcloselayout
  • layoutcleanup

Learn more about these attributes!

Return values

The entire (X)HTML and JS code on success. If an error occurs, clonefish will die with an error message.




1.3.4 validate()

clonefish->validate() - validate the form on the server side.

Description

class clonefish { 
  boolean validate( void )
}

Each time validate() is called, the elements are validated one-by-one and a boolean value is returned.

Return values

This method returns TRUE if all the elements are valid, and returns FALSE if at least one of the elements are invalid. Elements without validation settings are always valid.




1.3.5 getElementValues()

clonefish->getElementValues() - get the values of all the form elements in an array.

Description

class clonefish {
  array getElementValues( boolean $addslashes )
}

This method returns an array of element values in an associative array.

Clonefish is transparent by concept: if you rely on the magic quoting feature of PHP, you can use the following method to replace processing $_POST/$_GET/$_COOKIE/$_REQUEST arrays:

<?php

$form 
= new clonefish( [...] );
$form->addElements$_POSTget_magic_quotes_gpc() );
print_r$form->getElementValuesget_magic_quotes_gpc() );

?>

The code above will return the very same as a print_r( $_POST ); - quoted values if magic_quotes_gpc is set, and unquoted if unset.

Through the very same required parameter in addElements(), getElementValues(), setValue() and getVale() clonefish enforces building safe applications and websites.

Parameters

$addslashes

The only parameter this method requires is the $addslashes parameter. When set to TRUE, slashes will be added using the built-in addslashes() PHP function for all the values returned. When $addslashes is FALSE, no quotes are added.

Examples

<?php

$values 
$clonefish->getElementValues);
print_r$values );

?>


The output:

Array(
  'name'     => 'James Bond',
  'id'       => '007',
  'language' => 'en'
)



1.3.6 loadConfig()

clonefish->loadConfig() - loads a form configuration file

Description

class clonefish {
  void loadConfig( string $filename )
}

A really easy way to configure the layout and other settings for a form: just create a simple .ini textfile, and you're ready to go! Clonefish has a clever built-in parser for .ini files to support loading even the layout arrays from a file.

Features of the parser:

  • the first = character separates the name and value, no confusion with further =-s.
  • everything after the first = character is treated as the value of the setting: no need to use " characters, you still have all the characters at your hand (you can still escape " or ' characters)
  • feel free to use \n, \r and \t !
  • the . character in the name helps to define arrays of any depth
  • use the ; character to include comments
  • use empty lines to keep the file easy to read
  • you can use multiline settings: just indent the second and further lines with a space or a tab!

Examples

Example 1: a sample config file

; layout settings
layout = tabular
layouts.tabular.buttonrow =<tr><td colspan="2"></td><td>%s</td></tr>\n
layouts.tabular.element   =<tr %errorstyle%><td width="120" align="rig [...]
layouts.tabular.button    =<input type="submit" value="%s" />

layouts.tabular.container =
  <table cellpadding="5" cellspacing="0" border="0">
  %s
  </table> 

Example 2: loading a config file

<?php

$clonefish
->loadConfig'configs/formdefaults.ini' );

?>



1.3.7 getVars()

clonefish->getVars() - get the form as HTML/JS snippets in an array

Description

class clonefish {
  array getVars( void )
}

This method returns an array of strings to be used with template engines like Smarty.

Return values

The returned array format is the following:

fields

An associative array of HTML code snippets, something like:

Array(
  'login'    => '<input type="text" name="login" />',
  'password' => '<input type="password" name="password" />',
)

formopen

The form opening tag including all the parameters (method, action, name, etc.). To get a working clonefish form, you must include this string in your final HTML code.

script

The JavaScript code that validates the form on the client-side. To get a working clonefish form with client side validation, you must include this string in your final HTML code.

formclose

The form closing tag.

messages

An array containing error messages.

messageslayout

The error messages rendered in HTML based on the message layout settings if $clonefish->outputmessages is set to 1. Returns an empty string if $clonefish->outputmessages is set to 0.

Examples

<?php

$vars 
$clonefish->getVars();
print_r$vars );

?>


The output:

Array(

  'fields' => Array(
     'name'     => '<input type="text" name="name" value="James Bond">',
     'id'       => '<input type="text" name="id" value="007">',
     'language' => '<select name="language">' .
                     '<option value="en">English</option>' .
                     '<option value="hu">Hungarian</option>' .
                     '<option value="fr">French</option>' .
                   '</select>'
  ),

  'formopen' => '<form enctype="multipart/form-data" 
                       name="regform" action="test.php" 
                       onsubmit="return check_regform();" method="post">',

  'script' => '[...]'
              // JavaScript validation code 
              // including the <script></script>
              // tags

  'formclose' => '</form>',

  // error messages, if the validation failed:
  'messages' => Array(
    0 => "The 'login name' field is required",
    1 => "The 'password' field is required",
    2 => "The 'e-mail' field is required (specify a valid e-mail address)"

  // error messages formatted according to the
  // message layout settings
  'messageslayout' => "The following problems occured: " .
                      "<ul>"
                        "<li>The 'login name' field is required</li>" . 
                        "<li>The 'password' field is required</li>" .
                        "<li>The 'e-mail' field is required (specify " .
                        "a valid e-mail address)</li>" .
                      "</ul>"

)

 




1.3.8 removeElement()

clonefish->removeElement() - remove an element from the form.

Description

class clonefish {
  boolean removeElement( string $name )
}

Removes an element from the form.

Return values

Returns FALSE if the element cannot be removed (not found), returns TRUE if the element was successfully removed.

Examples

<?php

$removed 
$clonefish->removeElement'elementname' );
if ( 
$removed 
  echo 
'element removed';
else
  echo 
'element not found';

?>



1.3.9 getElementByName()

clonefish->getElementByName() - returns a reference to a form element.

Description

class clonefish {
  mixed getElementByName( string $name )
}

Returns a reference to an element object. Returns FALSE, if the element was not found.

Examples

<?php

$element 
$clonefish->getElementByName'elementname' );

?>



1.3.10 invalidate()

clonefish->invalidate() - invalidates the form

Description

class clonefish{
  void invalidate( void )
}

Invalidates the form. It can be used to invalidate the form even if the validation of the form elements was successful. Ideal for handling very complicated validations outside clonefish (though you can also use the custom (user-defined) validation). After invalidating a form, a repeated validation will always fail.

Most of the time clonefish->invalidate() is used together with clonefish->addMessage() to specify an error message.

Examples

<?php

if ( $clonefish->validate() ) {

  if ( 
something_bad_happened() )
    
$clonefish->invalidate();

  if ( 
$clonefish->validate() ) {
    echo 
'everything\'s OK';
  else {
    
// we could still get false
    
echo 'something bad happened!';
  }

}

?>



1.3.11 addMessage()

clonefish->addMessage() - add an error message to the form

Description

class clonefish {
  void addMessage( string $message )
}

Append an error message to the list of current error messages of the form. Most of the time it's used together with clonefish->invalidate().

Examples

<?php 

$clonefish
->invalidate();
$clonefish->addMessage(
  
'Some special fields are required!'
);

?>



1.3.12 getValue()

clonefish->getValue() - get the value of a form element

Description

class clonefish {
  mixed getValue( string $name, boolean $addslashes )
}

Returns the value of an element and adds slashes using addslashes() if needed.

It is a helpful shortcut instead of:

$element = $clonefish->getElementByName('fieldname');
$value   = $element->getValue( 1 );

Parameters

$name

The name of the form element

$addslashes

Whether or not slashes should be added to the returned value.

Return values

Returns the value of the element when the element is found, returns FALSE otherwise.

Examples

<?php 

echo $clonefish->getValue'login');

?>



1.3.13 setValue()


 

clonefish->setValue() - set the value of a form element

Description

class clonefish {
  mixed setValue( string $name, mixed $value, boolean $magic_quotes_gpc )
}

Sets the value of an element and strips slashes using stripslashes() if needed.

It is a helpful shortcut instead of:

$element = $clonefish->getElementByName('fieldname');
$element->setValue( 1 );

Parameters

$name

The name of the form element

$value

The value to set

$magic_quotes_gpc

Whether or not slashes are already added to the returned value.

Return values

Returns TRUE if the value is set successfully, returns FALSE if the element is not found.

Examples

Example 1: we have a login and a password field in our form.

<?php 

echo $clonefish->setValue( 'login', 0 ) ? 'OK' : 'failed';
echo "\n";
echo $clonefish->setValue( 'password', 0 ) ? 'OK' : 'failed';
echo "\n";
echo $clonefish->setValue( 'description', 0 ) ? 'OK' : 'failed'; 

?>


Output:

OK
OK
failed



1.4 Element class

The form elements are represented in $clonefish->elements as an array of object references. Each element is an object of the element class or one of its descendants. To manipulate the elements, you have the following options: 

Adding an element

The elements are added through the configuration array passed to the clonefish->addElements() method. The configuration array settings are described under  the Input types and the Validation types sections in the manual.

Getting a reference to an element

You can reach an element with the clonefish->getElementByName() method:

class clonefish {
  element clonefish->getElementByName( string $name ); 
}

This method returns an object reference if the element was found, and FALSE otherwise.

Setting value

class element {
  boolean element->setValue( mixed $value, boolean $slashes_already_added );
}

Sets the value of an element. The returned value is not the result of any kind of validation, do not use it for such purposes.

Parameters:

  • value is not a taken as a reference but as a copy.
  • $slashes_already_added defines if slashes are already added to the value. If it evaluates to true, stripslashes() will be used on the value (even recursively if it's an array).

Return values:

TRUE on success, FALSE on failure. Failure is less likely: only selectDate->setValue() returns FALSE when strftime() wasn't successful for the incoming date/timestamp. The returned value shouldn't be used as some kind of validation flag.

Getting value

class element {
  mixed element->getValue( boolean $addslashes ); 
}

and

class select extends element {
  mixed select->getValueArray( boolean $addslashes ); 
}

Returns the value of the element.

Parameters:

  • If $addslashes is set to TRUE, the returned value will be escaped using the built-in PHP addslashes() function (even recursively, if the returned value is an array).

Return values:

It returns the value for a simple field (like an inputText).
element->getValue() for a multiple select (or selectDynamic, or selectFile) element may return the following:

  • NULL for empty arrays
  • if it's an array with only one array element, it returns that array element as scalar value (not in an array)
  • if the array has more than one elements, it returns the array.

This triplet matches the behaviour of HTTP GET/POST and PHP when receiving multiple selects during a form submission.

If you expect arrays for a multiple select in every case above, use select->getValueArray(). Arrays are often expected when the select is used as the "multiple" (N-part) in an 1-N database relation and the returned values are to be inserted in a table.

Getting type of an element

class element {
  string element->getType( string $name );
}

Returns the class name of an element.




2 Input types

To define form elements you need to learn the input types available in clonefish.

An input definition in clonefish is nothing more but a simple associative array, where array keys are the names of the settings and array values are the actual settings. These input definition arrays are then grouped together in an array container. This is the array container used with clonefish->addElements(), and is referred to as the form configuration most of the time.

Let's see the basics - the settings that are available for all the input types:

<?php

$config = Array(

  'name' => Array(

    'type'           => 'inputText', 
    'displayname'    => 'Input field name',
    'value'          => 'default value here', 
    'help'           => 'validation failed for this element',

    // layout related settings
    'html'           => 'class="inputfieldstyle"',
    'rowlayout'      => '...%element% %prefix% %postfix% etc...',

    // special purpose settings
    'readonly'       => 1 | 0,
    'display'        => 1 | 0,
    'htmlid'         => 'name1'
  )

);

?>
  • 'html' - you can use the html setting to insert anything inside the element tag: to specify eg. a CSS class, row and column sizes for a textarea, add MULTIPLE attribute for a select and so on.
  • 'help' - the help message for the element if the validation fails. You can use this message to override built-in validation error messages. However, you can also specify help messages for each validation of an element, which overrides this message.
  • 'rowlayout' - this setting changes the layout of the form element row. The $clonefish->layouts array holds the element setting, which provides the default element row layout.
  • 'readonly' - if you'd like to keep some data together with information submitted by the user, you can use read only elements. These elements get their values only from the form configuration.
    For example:
    $config['userid'] = Array(
      'type'  => 'inputHidden',
      'value' => $_SESSION['userid'],
      'readonly' => true
    );
     
  • 'htmlid' - elements get their HTML DOM ID from their config name (the array key). If for some reason you need to have a different ID, you can set it here. It's a nice way to avoid conflicts from other HTML elements on the same page.

 




2.1 inputText, inputPassword, inputHidden, textarea

These controls are largely alike, thus all of them have the same configuration.
However, there are exceptions for the inputHidden element: as this element type is not visible, it does not support displayname, rowlayout, prefix and postfix.


<?php

$config 
= Array(
  
'id' => Array(
    
'type'           => 'inputText|inputPassword|inputHidden|textarea',
    
'displayname'    => 'This is an input field',
    
'value'          => 'default value here',
    
'html'           => 'class="inputfieldstyle"'
    'help'           
=> 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',
  )
);

?>


Live examples:

Validators to use together with this element:



2.2 inputCheckbox

A simple checkbox, like this: .
You can specify values for the unchecked and checked checkboxes. These values will be returned by $clonefish->getElementValues().

Note: according to the HTML specification, the unchecked checkbox values are missing when forms are submitted. Clonefish fixes this behaviour by design, so a checkbox value received from Clonefish is immediately insertable into a database for example.


<?php

$config 
= Array(
  
'answer' => Array(
    
'type'           => 'inputCheckbox',
    
'displayname'    => 'Please do check this checkbox!',
    
'onvalue'        => 1// value returned for a checked checkbox
    
'offvalue'       => 0// value returned for an unchecked checkbox
    
'value'          => 0// the value of 'onvalue' or 'offvalue'

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',
  )
);

?>


Live examples:

Validators to use together with this element:



2.3 inputCheckboxDynamic

This element is checkbox group that takes values and labels from a database query (like selectDynamic or inputRadioDynamic does), and returns only those values that were checked.

Using a multiple select might be cumbersome for users: in such cases inputCheckboxDynamic is a great built-in alternative.

This element also features a very useful validation to minimum/maximum number of checkboxes required!

You can specify values for the unchecked and checked checkboxes. These values will be returned by $clonefish->getElementValues().

Note: according to the HTML specification, the unchecked checkbox values are missing when forms are submitted. Clonefish fixes this behaviour by design, so a checkbox value received from Clonefish is immediately insertable into a database for example.

Note: as this element contains multiple form inputs, there's no htmlid setting for this element.


<?php

$config 
= Array(
  
'id' => Array(
    
'type'           => 'inputCheckboxDynamic',
    
'displayname'    => 'This is a dynamic checkbox group',

    
// first field: checkbox value, 
    // second field: checkbox label
    
'sql'            => 'SELECT id, name FROM categories'

    
// an array to create additional checkboxes, with id => value pairs
    
'values'         => Array(), 
    
// eg. Array( 1 => 'Asia', 2 => 'Africa', 3 => 'Australia', ... )

    
'onvalue'        => 1// value returned for a checked checkbox
    
'offvalue'       => 0// value returned for an unchecked checkbox

    // an array containing the ids (the first field from the SQL query).
    // Values with these ids will be checked, so you can pre-check
    // several/all checkboxes.
    
'value'          => Array(), // eg. Array( 1, 3, 5 )

    // an SQL query that returns ids to pre-check checkboxes
    // similarly to the 'values' setting
    
'valuesql'       => "SELECT categoryid FROM bookcategories WHERE id='12'",

    
// layout: the container for the checkbox group
    
'layout'         => '%s',

    
// itemlayout: the layout of a checkbox row
    
'itemlayout'     => "%checkbox% %label%<br />\n",

    
// divider settings: to create multiple columns
    
'divide'         => 5// default: null
    
'divider'        => "</td><td>"// default: null, see example!

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0
  
)
);

?>


Live examples:

Validators to use together with this element:



2.4 inputRadio

Radio buttons like these:

The labels ('yes', 'no', 'maybe') for the buttons are automatically equipped with the <label> tag, that's why you may also click on the labels and not just the controls themselves.


<?php

$config 
= Array(

    
'type'           => 'inputRadio',
    
'displayname'    => 'This is a static radio button collection',
    
'values'         => Array( 
      
=> 'zero',
      
=> 'one',
      
=> 'two',
      
=> 'more'
    
),
    
'value'          => '0',

    
// layout: the container for the entire radio group
    
'layout'         => '%s',

    
// itemlayout: the layout of a radio row
    
'itemlayout'     => '%radio% %label%\n',

    
// divider settings: to create multiple columns
    
'divide'         => 5// default: null
    
'divider'        => '</td><td>'// default: '', see example!

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0
  
)

);

?>


Live examples:

Validators to use together with this element:



2.5 inputRadioDynamic

Identical to inputRadio, but taking its options not only from the 'value' field, but also from the results of a database query.


<?php

$config 
= Array(
  
'id' => Array(
    
'type'           => 'inputRadioDynamic',
    
'displayname'    => 'This is a dynamic radio button collection',

    
// first field is the option value, second is the displayed 
    // option text, field names do not count
    
'sql'            => 'SELECT id, name FROM categories'

    
'values'         => Array( => 'choose nothing' ),
    
'value'          => '0',

    
// layout: the container for the entire radio group
    
'layout'         => '%s',

    
// itemlayout: the layout of a radio row
    
'itemlayout'     => '%radio% %label%\n',

    
// divider settings: to create multiple columns
    
'divide'         => 5// default: null
    
'divider'        => ''// default: '', see example!

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0
  
)

);

?>


Live examples:

Validators to use together with this element:



2.6 select

A single select like this:

or a multiple select like this (use the mouse button to select a range by dragging, or use the Control key while clicking on some values to select/deselect values that are not in a range):

single select

<?php
$config 
= Array(
  
'id' => Array(
    
'type'           => 'select',
    
'displayname'    => 'This is a static select',
    
'values'         => 
      Array( 
        
=> 'choose nothing'
        
=> 'value 1'
        
=> 'value 2'
      
),
    
'value'          => '0',
    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',
  )
);
?>

multiple select

IMPORTANT: always use multiple="multiple" in the 'html' parameter and [] in the field name.

<?php
$config 
= Array(

  
'id[]' => Array(
    
'type'           => 'select',
    
'displayname'    => 'This is a static multiple select',
    
'values'         => 
      Array( 
        
=> 'choose nothing'
        
=> 'value 1'
        
=> 'value 2'
      
),
    
'value'     => '0' | Array( 1,),
    
'html'      => 'multiple="multiple"'// an XHTML compatible way of the multiple parameter
    
'help'      => 'validation failed for this element',
    
'rowlayout=> '...%element% %prefix% %postfix% etc...',
    
'prefix'    => 'string to display before element',
    
'postfix'   => 'string to display after element',
    
'readonly'  => 0,
    
'display'   => 0,
    
'htmlid'    => 'name1',
  )
);
?>

Live examples:

Validators to use together with this element:



2.7 selectDynamic

A single or multiple select with values coming from a database. This control also handles tree-like structures (like a multi-level category structure for an online shop).

You can also use another database query to pre-select values for a selectDynamic element:


For such a select:

  1. create an SQL query using the sql setting that fetches all the possible values from a database, for example: Array( 1 => 'WAV', 2 => 'MP3', 3 => 'AVI', 4 => 'MPEG' ),
  2. and create another SQL query using the valuesql setting that specifies which options are to be selected -
    Array( 1, 3 ) in this example.

single dynamic select

<?php

$config 
= Array(

  
'id' => Array(
    
'type'           => 'selectDynamic',
    
'displayname'    => 'This is a dynamic select',
    
'sql'            => 'SELECT id, name FROM writers',
    
'values'         =>
      Array( 
        
=> 'choose nothing'
        
=> 'value 1'
        
=> 'value 2'
      
),
    
'value'          => '0',

    
// if you want a tree-select (check the tree-select 
    // example!), you should use these
    // settings:

    
'treeid'         => 'id',
    
'treestart'      => '0',
    
'treeparent'     => 'parentid',

    
// in such a case you should use %s in the 'sql'
    // parameter as the placeholder of the WHERE clause
    // of the query (the WHERE clause is automatically 
    // created based on the tree-settings, eg.
    // 'parentid = current_treeid' ).
    // example: 
    // 'sql' => 'SELECT id, name FROM table 
    //           WHERE active = 1 AND %s
    // if you omit this template, a complete
    // WHERE clause will be automatically 
    // appended to the value of the 'sql' setting.

    
'levelprefix' => '&nbsp;&nbsp;',
       
// a string prefix for option texts
       // to create the tree visually.
       // At the root level it's used 0 times, 
       //        level 1: once, 
       //        level n: n times.

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',

  ),

);

?>

multiple dynamic select

The differences between a single and a multiple select are:

  • the name of the multiple select element must have trailing [] (square brackets).
  • the multiple select must have the following string injected in its 'html' setting: multiple="multiple"
  • you can use the 'valuesql' setting to pre-select values
  • in the Clonefish constructor you can pass an id parameter to the class. In 'valuesql' you can reuse this value as a %s placeholder. It makes easier to create modification forms without injecting the ID manually into the SQL query.

All the settings of a single dynamic select can still be used (including the tree format). These settings are not repeated in the following configuration definition.

<?php 

$config 
= Array(

  
'booksofawriter[]' => Array(
    
'type'           => 'selectDynamic',
    
'displayname'    => 'This is a dynamic multiple select',

    
// an XHTML compatible way of the multiple parameter
    
'html'           => 'multiple="multiple"',

    
// first field is the option value, second is the displayed 
    // option text, field names do not count
    
'sql'            => 'SELECT id, title FROM books',
    
'values'         => Array( => 'choose nothing' ),
    
'valuesql'       => 
      
"SELECT bookid
       FROM booksofawriter
       WHERE writerid = %s"
,
    
'value'          => '0' | Array( 1)
  )

);

?>

Live examples:

Validators to use together with this element:



2.8 selectFile

This control reads the contents (file and directory entries) of a directory and creates a select of the items found. Some examples:

  1. Directory tree containing only files, with relative paths:
  2. Directory tree containing only files, with absolute paths:
  3. Directory tree containing only directories, with relative paths:

There are many options to customize apperance and behaviour like file inclusion/exclusion, display format, recursive traversal settings.


<?php

$config 
= Array(

  
'id' => Array(

    
'type'          => 'selectFile',
    
'displayname'   => 'Please select a file',

    
'directory'     => '/home/www/www.example.com/files/',
    
'tree'          => 0// default: 1
    
'includedirs'   => 0// default: 0
    
'includefiles'  => 0// default: 1

    // exclusion of specific files:
    
'exclude'       => Array( 'autoexec.bat''config.sys' ), 
    
// exlusion using regular expression (preg_match compatible string):
    
'excludere'     => '/\.txt$/i'// matching files will be discarded
    // inclusion using regular expression (preg_match compatible string)
    
'includere'     => '/\.xls$/i'// matching files will be included
    
    // ordering the files in the list
    
'order'         => 'name'// default: empty (unordered, as-is)
    // ordering options: name, namedesc, size, sizedesc

    // display format string (sprintf style) for regular files
    
'format'        => '%1$s (%2$d bytes)',
    
// %1$s means filename, %2$d is the size

    // display format string (sprintf style) for directories
    
'formatdir'     => '%1$s',    
    
// %1$s is the filename, %2$d is the size (omitted by default for dirs)

    // show directory paths in filename
    
'fullpath'      => 0// default: 0

    // include directory path in returned value
    
'fullpathvalue' => 0// default: 0

    // should directory names end with /
    
'trailingslash' => 0// default: 1

    
'values'        => 
      Array(
        
'/home/www/www.example.com/' => 'Your home directory'
      ),
    
'value'         => '/home/www/www.example.com/',

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',

  )

);

?>


Live examples:

Validators to use together with this element:



2.9 selectDate

Date selection input type with separate selects for year, month and day.

  • a hidden input field is automatically attached for this element to hold the actual values of the selects. This way you can still use the standard 'date' validation type as you would do on a text input
  • You can use the layout setting to change the order of the separate selects (eg. if your visitors prefer M D Y instead of the ISO standard Y M D)
  • Use the format setting to change the resulting date format of the concatenation: by default, selectDate returns dates in Y-M-D format.
  • Use padding, null, yearfrom, yearuntil, months to customize your date selector!

<?php

$config 
= Array(

  
'selectdate' => Array(
    
'type'           => 'selectDate',
    
'displayname'    => 'Your birthdate is...'',

    '
layout' => '%%%D',
      // we use % here to avoid problems with Y, M and D letters
      // in the layout string.
      // eg. if you'
d like to use a select like
      
//   Year: [    ] Month: [    ] Day: [    ]
      // you should specify:
      //   $layout = 'Year: %Y Month: %M Day: %D'
  
    
'format' => '%Y-%M-%D',
      
// format is used to specify the 'compiled' result of
      // the selects returned by getValue
  
    
'padding' => true,
      
// store month and day with two digits 
      // (01..12, 01..31 )
      // (affects only the 'results' not the option texts)
  
    
'null' => Array( '' => '' ),
      
// if $null is not false, but an array, it is used
      // for enabling empty dates. You may set it like:
      // Array( '' => '-- choose --' ) and combine
      // the element with a date validation.
  
    
'yearfrom' => false
    
// if ===false, will be set to current year in constructor
  
    
'yearuntil' => 1900,  
    
// if ===false, will be set to current year in constructor
  
    // if $yearfrom is larger than $yearuntil, you'll get a 
    // decrementing list of years, which is more natural to the users
    
    
'months' => Array( 
      
=> MONTH_01,  => MONTH_02,  => MONTH_03,  => MONTH_04
      
=> MONTH_05,  => MONTH_06,  => MONTH_07,  => MONTH_08
      
=> MONTH_0910 => MONTH_1011 => MONTH_1112 => MONTH_12
    
),
    
// these default month names are defined in messages_en.php

    
'onbeforechange' => 'JS_code_here_with_trailing_semicolon();',
    
'onafterchange'  => 'JS_code_here_with_trailing_semicolon();',
    
// these hooks allow you to run your own function(s)
    // whenever the selects change

    
'value'          => 'default value here',
    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',
);

?>


Live examples:

Validators to use together with this element:



2.10 mapMarker - Google Maps


 

The mapMarker element is a quite helpful one allowing users to specify map coordinates (latitude, longitude) using a drag and drop marker. This element type uses Maptimize AddressChooser and Google Maps, so you'll need to create a Google Map API to use it and also include some simple JS files (Clonefish helps with this).

You can also add autocomplete field(s) to help users finding the right location. To use autocomplete a single helper field is enough, though you can refer to other already defined form elements (like country, zip, city, address fields) - the values of these fields can be stored in your database too. The autocomplete feature needs Prototype and Scriptaculous - Clonefish includes them automatically from Google AJAX JS API by default, which is a better-faster-cleaner approach for users.

This component naturally relies on JavaScript heavily: however if JS is turned off for some reason, users can specify latitude and longitude values by hand.

The component returns a simple string value containing latitude and longitude glued together with a string (which is ### by default). If you need the separate values, you can use the getValueArray() method of this element.

Valid latitude values are -90° .. 90°, longitude: -180° .. 180° - the element doesn't record (accept, store) invalid values even when there's no validation, so you'll get either a valid value or null when using the getValue methods.

 


<?php

$config 
= Array(

  
'coordinates' => Array( 

    
'type'           => 'mapMarker',
    
'displayname'    => 'Specify your location!',

    
'key'            => '...',  // Google API key, required
    
'width'          => 350,    // width of map in pixels, default: 350
    
'height'         => 350,    // width of map in pixels, default: 350
    
'jspath'         => '/js/'
    
// Path (URL) to addresschooser.js and proxy/googlemaps.js
    // These are AddressChooser javascript files.

    
'autocomplete'      => true,  // turn on/off autocomplete feature

    
'prototypepath'     => 'http://ajax.googleapis.com/...',
    
'scriptaculouspath' => 'http://ajax.googleapis.com/...',
    
// path to Prototype and script.aculo.us required by AddressChooser
    // autocompletion feature. Defaults to Google AJAX JS API URLs.

    // String displayed when JS is not available
    
'jshelp     => 
      '
Turn on JavaScript in your browser to use ' . 
      '
Google Maps instead of typing coordinates!',

    '
latitude'  => 'Latitude:', 
    // Label for latitude field when JS is not available
    '
longitude' => 'Longitude:', 
    // Label for longitude field when JS is not available

    '
glue'      => '###',
    // Glue string used to separate latitude and longitude numbers
    // in concatenated element value (eg. 42.12312938###34.124812498)

    
'autofocus' => true,
    
// whether or not to autofocus on the autocomplete street element

    // The following 5 settings may be used for autocompletion.
    // The settings contain DOM IDs. When they're used, 
    // the input elements must exist.

    
'street'    => null,
    
// When the street field is not specified (which is the default),
    // Clonefish automatically creates a "throw away" autocomplete input 
    // field above the map (only if autocomplete is used).
    // When only the street field is used (no city, zip, etc), it is used as 
    // a joker field: any part of an address can be used Google knows can be 
    // used.
    //
    // This field is not validated nor returned by Clonefish: if you want to
    // store the value of this field, create a separate inputText element
    // and specify it's its DOM ID here (DOM ID is the name by default, or 
    // htmlid setting if set).

    
'country'   => 'cf_Country'// setting defaults to non-existing
    
'state'     => 'cf_State',   // DOM ids to avoid unwanted default
    
'city'      => 'cf_City',    // behaviour
    
'zip'       => 'cf_Zip',

    
'autofocus' => true
    
// when autocomplete field is used, sets focus to the street input field.

    
'value'          => 'default value here',
    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',
);

?>





2.11 FCKEditorArea2

This element uses the most famous and feature rich WYSIWYG editor on the web, the FCK Editor v2. This element supports the required validation which uses JavaScript FCKEditorAPI calls to tell if the editor is empty.


<?php 

$config 
= Array( 

  
'body' => Array(  

    
'type'           => 'mapMarker'
    
'displayname'    => 'Specify your location!'

    
'width'          => 350,    // width of editor in pixels, default: 700 
    
'height'         => 350,    // height of editor in pixels, default: 300 

    
'jspath'         => '/js/',
    
// Path (URL) to FCK Editor. Tries to find $GLOBALS['FCKEditorBasePath'] 
    // if jspath is not specified. Trailing slash required.

    
'includepath'    => '.../',
    
// filesystem path to fckeditor.php wrapper included in FCK Editor
    // releases. Trailing slash required.

    
'value'          => 'default value here'
    
'help'           => 'validation failed for this element'
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...'
    
'prefix'         => 'string to display before element'
    
'postfix'        => 'string to display after element'
    
'readonly'       => 0
    
'display'        => 0
    
'htmlid'         => 'name1'
); 

?>





2.12 reCaptcha

A CAPTCHA or Captcha is a type of challenge-response test used in computing to ensure that the response is not generated by a computer. ReCaptcha is a popular captcha system that uses successful decodings to helps digitise books for online use. The reCaptcha technology works together with the reCaptcha servers, so you cannot use it in a network which is not connected to the internet.

This element is to be used together with the reCaptcha validation - you'll need to use both, as the element only displays the reCaptcha interface.

To use this element, you'll need to get your own API keys first! The public API key is used for the element (this is used in the HTML code), while the private API key is used for the validation (used only between your server and the reCaptcha server).

You need to include the reCaptcha PHP library before using this element (recaptcha_get_html function must be defined).


<?php 

$config 
= Array( 

  
'recaptcha' => Array(  

    
'type'           => 'reCaptcha'
    
'displayname'    => 'Please take the reCaptcha challenge!'

    
'key'            => '...',  // Google API key, required 

    
'help'           => 'validation failed for this element'
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...'
    
'prefix'         => 'string to display before element'
    
'postfix'        => 'string to display after element'
    
'display'        => 0
); 

?>





2.13 inputFile

A simple file selector, like this: .

This control aborts with an error message if file upload is not allowed by php.ini (file_uploads=0).

When you need modify forms

Once you're in a need to create a modify form including this element, you can use a few extra settings to create common controls like

  • a "delete file" button that opens a given URL
  • a text link or a clickable image preview (or icon) of the file already uploaded.

    To display such a link you need to use the href option. Instead of long explanation of other settings some pseudo code follows (not used in this manner but it's much easier to follow):

    if ( strlen( $settings['thubmnail'] ) )
      $linktext = $settings['thumbnail'];
    elseif ( strlen( $settings['text'] ) )
      $linktext = $settings['text'];
    else 
      $linktext = basename( $settings['href'] );
    echo '<a href="' . $settings['href'] . '">' . $linktext . '</a>';
    The actual code is a little different as you can alter the tags themselves using linklayout and thumbnaillayout, etc.

When you need to get the binary value

You may use the binaryvalue setting (set to 1) to get the binary file contents returned by any of the clonefish methods (getElementValue(), getValues() ) after a successful validation. Further notes:

  • The contents of the uploaded file is loaded from the $_FILES['inputname']['tmp_name'] file.
  • The null PHP value is returned by the value getter methods after submitting an invalid file (not false, since that's a one-byte long value which is misleading).
  • If you've set the value attribute of the file input previously, it'll be overwritten if an invalid file was submitted.

<?php

$config 
= Array(

  
'portrait' => Array(
    
'type'           => 'inputFile',
    
'displayname'    => 'Choose a picture',

    
// optional settings
    
'href' =>      // URL of the file itself
      
'http://www.example.com/uploaded/images/12.gif',
    
'text' =>      // link text - used if the thumbnail is unused
      
'click here to download the current file',
    
'thumbnail' => // thumbnail used as clickable image when set
      
'http://www.example.com/uploaded/images/thumbs/12.gif',
    
'delete' =>    // displays a button with onclick handler to open URL
      
'somescript.php?target=delete&filename=something.gif',

    
// layout settings
    
'linklayout' => 
      
'<a target="_blank" href="%href%">%thumbortext%</a><br />',
    
'thumbnaillayout' => 
      
'<img src="%thumbnail%" border="0" alt="%text%" />',
    
'deletelayout' => 
      
'<br /><input type="button" value="' STR_IMAGE_DELETE '" 
      onclick="location.href='
%delete%';" />';

    
// misc
    
'binaryvalue' => '1 | 0'// default: 0

    
'html'           => 'class="inputfieldstyle"',
    
'help'           => 'validation failed for this element',
    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'readonly'       => 0,
    
'display'        => 0,
    
'htmlid'         => 'name1',
);
?>


Live examples:

Validators to use together with this element:



2.14 fieldset

This is a special element type to create a fieldset.

If you use a fieldset element in your form with the submit setting set to 1, the fieldset will contain the submit button (which looks much better). You can use as many fieldsets as you like, and you can use even multiple submit buttons in several fieldsets (useful if fields are not required in every fieldsets).

As this element only affects form layout there's no returned element value  by $clonefish->getElementValues() or other getter methods.

Sometimes styling fieldsets can be very tricky, as several browsers (mostly the IE family) do not support detailed styling for <fieldset> and/or <legend>. In such cases you can still use the layout and legendtag settings to replace even the entire fieldset logic to DIVs and H1s for example. This way you can keep the very same comfortable behaviour of form generation and visual impression while you don't have to bother about styling tricks.

You can also attach anything above/below the contents of a fieldset using prefix and postfix.


<?php

$config 
= Array(

  
'fieldset' => Array(

    
'type'   => 'fieldset',

    
'layout=> '
       <fieldset %html% id="%id%">
          <%legendtag%>%legend%</%legendtag%>
          %prefix%
             %content%
          %postfix%
       </fieldset>'
,
    
'legendtag' => 'legend',

    
// this is the default layout of a fieldset.
    //
    // the %...% placeholders are used to build the entire fieldset.
    // the '%prefix%', '%postfix%', '%html%' placeholders are the generally 
    // used element parameters, while %legend% is only available
    // for fieldsets.

    
'legend' => 'Personal information',
    
'submit' => '1 | 0'// default: 0
    
'value'  => false,
    
// use a number here to define number of elements to include
    // in the fieldset. If you omit this value, all elements after
    // fieldset will be included until the next fieldset or until the
    // last element.

    
'html'           => 'class="inputfieldstyle"',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'display'        => 0,
    
'htmlid'         => 'name1',

  )

);

?>


Live examples:




2.15 text

A simple display-only element.

Typical usage is:

  • displaying text information in between for elements
  • displaying non-changeable input data (like a login name) for modify forms.

Please note, that the value of this element is not returned by $clonefish->getElementValues().


<?php
$config 
= Array(

  
'id' => Array(
    
'type'           => 'text',
    
'displayname'    => 'This is an informational field',
    
'value'          => 'Some string here',

    
'rowlayout'      => '...%element% %prefix% %postfix% etc...',
    
'prefix'         => 'string to display before element',
    
'postfix'        => 'string to display after element',
    
'display'        => 0,
  )

);
?>





2.16 template

An element type to reorganize your form layout.

It's a template (or a container) for displaying any other form elements grouped together. A great way to

  • group together title - first name - lastname fields in one form row (by removing table tags from the rowlayout of these elements and display them in a template)
  • build special layouts like this:

As this element only affects form layout, there's no returned value by $clonefish->getElementValues() or other getter methods.


<php
$config = Array(
  'id' => Array(
    'type'           => 'template',
    'value'          => 
      '<table>' .
      '%newslettercheckbox%' . 
      '%confirmcheckbox%' . 
      '%marketingcheckbox%' . 
      '</table>' .
  )
);

// This setting assumes that the elements called 
// newslettercheckbox,
// confirmcheckbox,
// marketingcheckbox are already defined, 
// and they have inherited the form 'element' layout setting 
// of a tabular form layout, which is a table row.

?>


Live examples:




3 Validation types

Clonefish has strong validation features to support building secure forms. Elements are validated two times: once in the browser using JavaScript, and once again on the server using PHP.

To use validation you only need to add a few lines to the element configuration, for example: 

<?php

$config = Array(
  'name' => Array(
    'type'       => 'inputText',
    'validation' => Array(
      Array( 'type' => 'required' )
    )
  )
);

?>

Well, that's the simplest validation. But there's much more! 

  • As you may have noticed, the validation setting is an array of arrays: this approach allows adding multiple validation rules to a single element.
  • Depending on the validation type you can specify further settings when defining a validation: for example a string validation can have minimum and maximum string length, or regular expressions to match.
  • The validation types all have some kind of built-in help messages, when the validation fails - however, they're kind of generic, so you may need to override them. Help messages can be set on element level or validation level using the 'help' setting.
  • A very powerful validation feature is the dependency handling: you can tie a validation to the value of an expression. Imagine you have a drop-down select with some options an "other" option. When the user chooses the "other" option, you want the user to fill a text field. To make it work you simple set the validation of the text field to depend on the value of the current selection.


 




3.1 string validation

Codepage-aware string validation helps validating string length, equality, difference, and regular expression patterns. 

Proper string validation means that we also care about the codepage - just think of multibyte characters in UTF-8, checking length or provide a safe regexp needs attention! For this reason you must set the way Clonefish handles codepages using form properties.

Depending on the codepage-related settings your regular expressions may be handled by preg_match, ereg or eregi on the PHP side. Use the PHP/JS regexp settings to define similar regular expressions in JS and PHP even if the regexp syntaxes are different.


<?php

$config 
= Array(

  
'element' => Array(

    
'type' => '...',
    
// ...further element settings here...

    
'validation' => Array( 

      Array(
        
'type'         => 'string',
        
'required'     => 1// required or not
        
'minimum'      => '2'// minimum length
        
'maximum'      => '5'// maximum length

        
'regexp'       => '/^[a-zA-Z]{5,10}$/'// regular expression to match
        
'regexpnot'    => '/^[a-zA-Z]{5,10}$/'// regular expression to unmatch
 
        // in several cases the same regexp cannot be used both in JS and PHP,
        // so we have separate settings for each.
        
'jsregexp'     => '/^[a-zA-Z]{5,10}$/'// JS regular expression to match
        
'jsregexpnot'  => '/^[a-zA-Z]{5,10}$/'// JS regular expression to unmatch
        
'phpregexp'    => '/^[a-zA-Z]{5,10}$/msUi'// PHP regular expression to match
        
'phpregexpnot' => '/^[a-zA-Z]{5,10}$/'// PHP regular expression to unmatch 

        
'equals'       => 'password2'// equals to another field (eg. two passwords)
        
'differs'      => 'fieldname'// differs from another field
        
'help'         => 'Help message value for this validator only'
      
)

    )
  )
);

?>


Live examples:




3.2 CAPTCHA validation

CAPTCHA validation is "a type of challenge-response test used in computing to determine whether or not the user is human" (for details see the related Wikipedia page) - in short, it's a great way to avoid form spamming.

To use the CAPTCHA validation, follow these steps:

  • you can freely use your favourite CAPTCHA generator (eg. PEAR Text_CAPTCHA, pwImage, etc.) - the only requirement is to store the string used in the image in the $_SESSION array. In general a CAPTCHA generator script is like:

    <?php

    $captcha 
    Text_CAPTCHA::factory'Image' );
    $captcha->init(15060NULL, array( 'font_file' => 'arial.ttf' ) ); 
    header("Content-type: image/jpeg"); 
    echo 
    $captcha->getCAPTCHAAsJPEG(); 
    $_SESSION['captchapass'] = $captcha->getPhrase();

    ?>
  • attach an <img src="..."> tag pointing to your CAPTCHA script: use the postfix setting of an inputText element 
  • add the captcha validation to the inputText element: define the key of the $_SESSION variable ('captchapass' in the above example) in the 'index' setting of the validation array of the element - and now you're done! 

<?php 

$config 
= Array( 

  
'element' => Array( 

    
'type' => '...'
    
// ...further element settings here... 

    
'validation' => Array(  

      Array(
        
'type'     => 'captcha',

        
'index'    => 'captchatext',
        
// 'index' is the $_SESSION array key:
        // if your CAPTCHA image generator
        // uses $_SESSION['captchatext'] to save
        // the CAPTCHA letters, use 'captchatext' 
        // here

        
'casesensitive' => 1// default: 0
        // CAPTCHAs are typically case insensitive

        
'help'    => 'Help message value for this validator only'
      
)
    )
  )
);

?>


Live examples:




3.3 Dependency validation

Adding dependency validation is the key to implement clever form logic: it lets you define how to validate fields based on some criteria.

Actually dependency validation is not a validation type like the date or string validation: instead it's a setting for all the validation types available in Clonefish.

Adding dependency practically means adding a condition group to a validation of an element: if conditions in the group are met, the element gets validated as normally. If conditions don't meet, the validation is not applied.

For example, you can make a text input required using a string validation. To make this validation depend on the value of a specific select option value, you need to add the appropriate condition ("when the select options equals X") to the string validation of the text field.

Let's see how it works:

  'theselect' => Array(
'displayname' => 'Where did you hear about us?' 'type' => 'select', 'values' => Array( 'internet' => 'internet' 'newspaper' => 'newspaper' 'friend' => 'friend' 'other' => 'other (please specify!)' // we want more info in this case ), ), 'thetextfield' => Array(
'type' => 'inputText',
'displayname' => 'Other:',
'validation' => Array(
Array(
'anddepend' => Array(
Array(
'js' => ' <FORM.theselect> == "other" ',
'php' => ' <FORM.theselect> == "other" ',
)
),
'type' => 'required'
),
),
),

As you can see, the validation rules are equipped with a condition group (the anddepend array). Conditions in a group are always in a relation: AND or OR relation is available (anddepend or ordepend, respectively). You can simply tell how the conditions are related by putting them in a validation setting named as anddepend or ordepend (at least one of these array keys must exist in the validation setting). If you have only a single condition (like in the above example), it doesn't matter which one you choose. 

Now about conditions: conditions must be defined for both PHP and JavaScript. (this approach may be familiar from the custom validation). While defining a condition, Clonefish helps you with JavaScript and PHP shortcuts: <FORM.elementname> returns the actual element value, so you don't have to dig through the JS DOM or PHP POST arrays to get the element value. This shortcut works for all element types and calls the appropriate function for you both in JS and PHP:

  • for inputCheckbox it returns
    • true  or  false
    • or onvalue or false if you have provided onvalue for the checkbox 
  • for inputCheckboxDynamic it returns an array including checkbox values, or false if no checkboxes are checked in the group
  • for multiple selects (select, selectDynamic) it returns an array of option values or false
  • for any other fields it returns the field value or selected field value, if present (it may not present for an inputRadio without a default value), or false otherwise

Even though the above may sound complex at first, check the detailed example: all the things above are actually quite simple! Make sure to try it live - follow the link below the example array!


$config = Array(

  'wanttea' => Array(
    'type'        => 'inputRadio',
    'displayname' => 'Would you like some tea?',
    'values'      => Array( 0 => 'no', 1 => 'yes' ),
    'validation'     => Array(
      Array( 'type'    => 'required' ),
    ),
  ),

  // if the user drinks tea, make him/her choose a flavor!
  'teaflavor' => Array(
    'type'        => 'inputRadio',
    'displayname' => 'Choose a flavor!',
    'values'      => Array( 
      0 => 'almond', 
      1 => 'cherry',
      2 => 'ginger',
      3 => 'lemon',
      4 => 'peach',
      5 => 'vanilla',
    ),
    'validation' => Array(
      Array( 
        'anddepend' => Array(
          Array(
            'js'  => '<FORM.wanttea> == 1',
            'php' => '<FORM.wanttea> == 1',
          )
        ),
        'type'    => 'required' 
      ),
    ),
  ),

  // if the user chooses not to drink tea, try to sell some coffee then: 
  'wantcoffee' => Array(
    'type'        => 'inputRadio',
    'displayname' => 'Some coffee?',
    'values'      => Array( 0 => 'no', 1 => 'yes' ),
    'validation'     => Array(
      Array( 
        'anddepend' => Array( 
          Array(
            'js'  => '<FORM.wanttea> == 0',
            'php' => '<FORM.wanttea> == 0',
          )
        ),
        'type' => 'required' 
      ),
    ),
  ),

  // if the users said yes for tea OR coffee, we require him/her to
  // select at least one addon (okay, it's not that polite, but it's just
  // an example ;) )

  'addons' => Array(
    'type'        => 'inputCheckboxDynamic',
    'displayname' => 'Addons',
    'values'      => Array(
      'sugar'       => 'sugar',
      'brown sugar' => 'brown sugar',
      'cream'       => 'cream',
      'milk'        => 'milk',
    ),
    'validation'     => Array(
      Array( 
        'ordepend' => Array(
          Array(
            'php' => '<FORM.wanttea> == 1',
            'js'  => '<FORM.wanttea> == 1'
          ),
          Array(
            'php' => '<FORM.wantcoffee> == 1',
            'js'  => '<FORM.wantcoffee> == 1'
          ),
        ),
        'type'    => 'required'
      ),
    ),
  ),

  // no coffee, no tea? It MUST be something else then ;)
  'custom' => Array(
    'type'        => 'select',
    'displayname' => 'Please choose something else!',
    'values'      => Array( 
      0 => '',
      1 => 'Coke',
      2 => 'Orange juice',
      3 => 'Mineral water',
      4 => 'Energy drink',
    ),
    'validation'     => Array(
      Array( 
        'anddepend' => Array(
          Array(
            'php' => '<FORM.wanttea> == 0',
            'js'  => '<FORM.wanttea> == 0'
          ),
          Array(
            'php' => '<FORM.wantcoffee> == 0',
            'js'  => '<FORM.wantcoffee> == 0'
          ),
        ),
        'type' => 'number', 
        'minimum' => 1 
      ),
    ),
  ),

);


Live examples:




3.4 number validation

No more, no less - validates numbers. Supports scientific notation too!


<?php

$config 
= Array(  

  
'element' => Array(  

    
'type' => '...',  
    
// ...further element settings here...  

    
'validation' => Array(   

      Array(
        
'type'     => 'number',
        
'required' => 1// required or not (number or empty), default: 1
        
'minimum'  => 2// minimum value, negative numbers too
        
'maximum'  => 5// maximum value
        
'real'     => 'sci'
        
// Defines notation allowed: 
        // 0 - integers only,
        // 1 - integers or real, eg. 12 or 2.3
        // sci - scientific/hex notation: 123.03E+35, 0xFA235F
        
'help'     => 'Help message value for this validator only'
      
)

    )
  )
);

?>


Live examples:




3.5 date validation

Date validation allows validating a date against a format string, minimum/maximum date values and value of other fields (compared fields need to be date validated too).

The key to date validation is the format string. To create a format string, use the following date and/or time elements combined with some delimiter characters:

  • YYYY: year, 4 digits
  • YY: year, 2 digits
  • M: month, 1 or 2 digits (MM for 2 mandatory digits)
  • D: days, 1 or 2 digits (DD for 2 mandatory digits)
  • h: hour, 1 or 2 digits (hh for 2 mandatory digits)
  • m: minute, 1 or 2 digits (mm for 2 mandatory digits)
  • s: seconds, 1 or 2 digits (ss for 2 mandatory digits)

Using these elements you can build most of the numeric date formats used in the world. You can use any kind of delimiters in the format string.

The input is validated syntactically first (number of digits must be correct), then comes the validation against the following rules (if the element exists):

  • 1 <= month <= 12
  • 1 <= days <= 31
  • days must be less or equal than 28, 29, 30 or 31 depending on (leap) year and month
  • 0 <= hours <= 23
  • 0 <= minutes <= 59
  • 0 <= seconds <= 59 

Furthermore, you can specify whether the date is required or not (not required date fields may be left empty).

Date validation is Y2K38 aware: this platform dependent overflow problems of future dates (from 2038) using the DateTime class available since PHP 5.2. This feature gracefully degrades: Clonefish notifies the users with a message about the limitation of date validation on systems where DateTime class is not available, or in other words: users are not allowed to enter overflowing future dates when date validation is used.


<?php 

$config 
= Array(   

  
'element' => Array(   

    
'type' => '...',   
    
// ...further element settings here...   

    
'validation' => Array(    

      Array(
        
'type'     => 'date',
        
'required' => 1// default: 1
        
'format'   => 'formatstring'// default: 'YYYY-MM-DD'
        
'minimum'  => -2125999898// minimum date(+time) as UNIX timestamp
                                   // this value is 1902-08-19
        
'maximum'  => time(),      // maximum date(+time) as UNIX timestamp

        // compare to other fields (both fields need to have at least date
        // format validation set to be comparable)
        
'lessthan'      => 'fieldname'
        
'lesseqthan'    => 'fieldname'
        
'greaterthan'   => 'fieldname'
        
'greatereqthan' => 'fieldname'

        
'help'     => 'Help message value for this validator only'
      
)
    )
  )
);

?>


Live examples:




3.6 required validation

  • For an inputText, inputHidden, inputPassword, textarea or FCKEditorArea2 field it examines if the length of the input field is not zero without the trailing and leading whitespace.
  • For an inputCheckbox, it requires the checkbox to be checked
  • For an inputRadio, inputRadioDynamic, a multiple select, a multiple selectDynamic or a multiple selectFile it requires at least one option to be selected
  • For inputCheckboxDynamic element (checkbox group) you can finetune how many checkboxes must be checked (min/max number)

Tips:

  • If you'd like to make an inputFile mandatory, you'll need to use the 'required' parameter of the file validation.
  • You can achieve the opposite of this validation using the 'required' parameter available for several validation types: this way you can accept valid or empty fields, for example a valid number OR an empty field.

<?php  

$config 
= Array(    

  
'element' => Array(    

    
'type' => '...',    
    
// ...further element settings here...    

    
'validation' => Array(     

      Array(

        
'type'    => 'required'
 
        
// only for inputCheckboxDynamic:
        
'minimum' => 1// default: 1 
        
'maximum' => 5  // default: false (no maximum)
 
        
'help'    => 'Help message value for this validator only'
      
)
    )
  )
);

?>


Live examples:




3.7 file validation

The file validator helps validating files and  even image file types. It relies on the built-in getimagesize() function.

Tips:

  • The validator also helps to limit the filesize, the maximum filesize defaults to the upload_max_filesize setting of PHP.
  • Set the required parameter to zero (false) if file upload is not mandatory.
  • To make validation extra safe you can use the imagecreatecheck option, which uses the imagecreatefrom...() GD functions to create an image variable of the uploaded file in the memory. If it fails, the image is broken, if it succeeds, you'll most likely won't have problems during converting the image.
  • Please note that you have to make sure that there's enough memory for your PHP process to create large image variables using imagecreatecheck! If in doubt, take a look at this PHP memory limit calculator for image resizing!

<?php  

$config 
= Array(    

  
'element' => Array(    

    
'type' => 'inputFile',    
    
// ...further element settings here...    

    
'validation' => Array(     

      Array(
        
'type'     => 'file',
        
'types'    => Array('gif','jpgrgb','png','bmp','swf'),
          
// feel free to finetune jpg validation:
          //   - jpgrgb for JPEGs with RGB channel
          //   - jpgcmyk for JPEGs with CMYK channel
          //     (some browsers (IE) have problems with 
          //      displaying CMYK JPGs, best to avoid!)
          //   - jpg for both jpgrgb and jpgcmyk

        
'imagecreatecheck' => 0// default is 0,
        
'minimum'  => 123,
        
'maximum'  => 4900// default value is: ini_get('upload_max_filesize')
        
'required' => 0// default is 1
        
'help'     => 'Help message value for this validator only'
      
)
    )
  )
);

?>


Live examples:




3.8 database validation

Database validation is a powerful validation type: creating a login form simply becomes a Clonefish form with a database validation included.

There are two ways to validate:

  • use field and  value settings to validate against a value returned by a query
  • use minrows and/or maxrows to examine the number of rows returned by a query

In the query you can use the <FORM.fieldname> placeholders to represent values from the form. Do not use quotes around the placeholders as Clonefish takes care of proper quoting through its database wrappers.

Using the condition parameter you can deffine the relation between settings: by default it's set to 'and', this way each of minrows, maxrows and value conditions (if used) must be valid to have the element validated. Accordingly, 'or' is used when any of these settings may validate the element by itself.


<?php

$config 
= Array(

  
'element' => Array(

    
'type' => 'inputFile',     
    
// ...further element settings here...     

    
'validation' => Array(      

      Array(
        
'type'     => 'database',
        
'sql'       => 
          
"SELECT count(*) AS counter FROM users " .
          
"WHERE login= <FORM.login> AND password = <FORM.password>",
        
'minrows'   => 0,
        
'maxrows'   => 0,
        
'field'     => 'counter',
        
'value'     => 1,
        
'condition' => 'and | or'// default: 'and'
        
'help'        => 'Help message value for this validator only',
        
'helpmaxrows' => 'Help message when number of rows > maxrows',
        
'helpminrows' => 'Help message when number of rows < minrows',
        
'helpvalue'   => 'Help message when value <> query field value',
      )
    )
  )
);

?>


Live examples:




3.9 user-defined (custom) validation

Though the best way to define custom validation types is to simply extend Clonefish using your own validator class (feel free to explore the validators for examples!), a simple 'drop in' validator is also available in Clonefish. This one is used to get an element validated using JS or PHP expressions, which is a very quick and easy solution actually.

  • You can define a PHP and a JS expression or both, where can use placeholders like <FORM.fieldname> as shortcuts to elements.
  • In the PHP expression you can also access $this->form  which is the Clonefish object or $this->element which is the element holding the custom validator.
  • Please note that you can only use one error message for each validator (when you create an own validator class, you can return any error message depending on the type of problems encountered)

<?php 

$config 
= Array( 

  
'element' => Array( 

    
'type' => 'inputFile',      
    
// ...further element settings here...      

    
'validation' => Array(       

      Array(
       
'type' => 'custom',
       
'php'  => 'strlen( <FORM.fieldname> ) > 0'// php expression
       
'js'   => '<FORM.fieldname>.length > 0',    // javascript expression
       
'help=> 'Help message value for this validator only'
      
)
    )
  )
);

?>


Live examples:




4 Features

 




4.1 Handling quotes

As you may already know, there's a common problem with forms, databases and PHP: all of them have their special way of handling quotes. After all, it's not some terrific problem that couldn't be solved: it is only something you have to take care of:

  • the root of the problem: to insert data in a database, quotes must be escaped: INSERT INTO books (title) VALUES ("John's book")
  • otherwise we rarely need escaping quotes (no escaping needed for sending submitted form data in e-mail for example)
  • PHP has a built-in feature called magic quotes (magic_quotes_gpc setting in php.ini). In earlier PHP versions it seemed to be a good idea to have every $_GET, $_POST and $_COOKIE data automatically escaped, so it was the factory default - that's why there was no need to use addslashes() before inserting data into a database. This concept has already led to unportable applications.
  • Current PHP versions come with magic_quotes_gpc turned off - now you have to decide if you'd like to take care of the quotes.

Clonefish was built to provide a transparent form handling method, so you can even migrate your current code to clonefish, no matter if your magic_quotes_gpc is on or off. That's why you can control whether you're passing or want to receive escaped or unescaped data using the following methods and parameters:

  • $cf->addElements( $config, $_POST, get_magic_quotes_gpc() )
  • $cf->getElementValues( get_magic_quotes_gpc() )
  • $cf->getValue( 'elementname', get_magic_quotes_gpc() )
  • $element->getValue( get_magic_quotes_gpc() )
  • $element->setValue( 'value', get_magic_quotes_gpc() )

Why are these extra parameters so useful? There's just one thing to remember: things are to be kept clear in clonefish. Whatever you give to clonefish, it needs to be 'flagged' whether it's already escaped or not: this way clonefish will know what to do, has to strip those unwanted slashes or not. This way clonefish will always contain unescaped values, which is the essence of this process.

When you use the get...() methods, you surely know what will you use those values for: if you use it for a database query, you will want to get it escaped; if your database abstraction layer automatically adds the slashes, you won't need them; and if you send an e-mail built from the values, you won't need them again. So feel free to use the parameters as they fit your needs. For detailed description, see the reference for the methods!

Note: the method calls above uses get_magic_quotes_gpc() everywhere. If you use the method calls this way, clonefish will be transparent, and will return values the very same way as PHP would: depending on the magic_quotes_gpc settings. It's very much advisable to use finetuned settings depending on your current needs instead! For example:

  • $cf->addElements( $config, $_POST, get_magic_quotes_gpc() )
    (it's fine to use get_magic_quotes_gpc() as PHP knows very well how the $_POST array is escape)
  • $cf->addElements( $config, $dbrow, false )
    (in case we've just selected a row from database (where the array values are unescaped) and we're passing the values to clonefish)
  • $cf->getElementValues( true ) (if you need escaping)
  • $cf->getElementValues( false ) (if you don't need escaping)



4.2 Multiple values in GET/POST: "variable[]"

To receive multiple values in an array, PHP understands the <select multiple="multiple" name="variable[]">...</select> syntax and converts the submitted values to an array that you can reach through $_POST['variable'] (see the related faq).

As clonefish was planned to be universal, it also has this feature built-in: depending on the element names in the configuration array, it finds out, if the value of the element was meant to be an array.

The latest version of clonefish also identifies multidimensional arrays
(eg. <select name="variable[1][]" multiple="multiple">).
Naturally, when using $clonefish->getElementValues() to get all the submitted values, you'll find that there's a value "variable[1]" which is an array (the brackets in "variable[1]" are treated literally, as part of the name).




4.3 Accessibility, usability

Visually impaired users, users with sight problems or mobility cognitive impairments: they all use the same internet as the others do, they only use screen readers or special navigation instead of the mouse and/or the keyboard. Building accessible websites, paying attention to usability slowly became a standard, so it wasn't a question if clonefish needs to be prepared to such requirements.

Let's see how clonefish supports accessibility/usability:

  • the label tags (form labels) are automatically generated for every single input: this way clicking on text around the input controls will focus on the input (text, textarea, select), select it (radio button) or change its state (checkbox). It's something that's been used by desktop applications for a long time - since HTML 4.01 it's a standard on the web too.
  • fieldset support: another HTML feature to group form elements together. It's not only a great visual guidance to users, but also helps screen reader users to understand your form much better.
  • XHTML support - XHTML basically is a stricter way to write HTML. Clonefish generates XHTML code, it means that it will not break your XHTML-compliant website while it still renders great even in XHTML-incapable browsers.
  • cross-browser JavaScript: clonefish generates cross-browser JavaScript tested in IE 5-6-7, Firefox, Opera, Safari, Pocket Internet Explorer, Opera for Windows Mobile Pocket PC. Due to the fallback methods used, client-side validation works fine even under Netscape Navigator 4.5 (released in 1998!). This versatility is not just for fun: it means, that virtually every JavaScript-supporting browser will understand the generated code (including not just PDAs, but even set-top boxes).
  • Set-top boxes, strict IT policies at companies/banks, special browsers and browser settings: all these can lead to missing/turned off JavaScript. Since clonefish uses exactly the same validation methods on the server side, you will never receive invalid data - just say good-bye to script kiddies and hackers trying to break your site or database through your forms!

Besides helping your users, you can also benefit from these features by simply quoting them when you're about to convince your clients and exceed you rivals - and even search engines will understand your pages better. All that without a single line of extra code. Isn't it what you were looking for?

In case you're interested in usability, accessibility, there's a lot to read at http://evolt.org/ia_usability!




affiliate program!

Do you run a PHP blog or related website? Join as an affiliate and earn money!
know more

form validation for developers!

clonefish is a proven, mature form generator class that helps PHP developers to create, validate and process secure, flexible and easy-to-maintain forms
learn more
Bookmark and Share