1. Helpers

Helpers are meant to provide functions that are commonly needed in views to format and present data in useful ways.

1.1. HTML

1.1.1. Introduction

The HTML helper is one of Cake's ways of making development less monotonous and more rapid. The HTML helper has two main goals: to aid in the insertion of oft-repeated sections of HTML code, and to aid in the quick-and-easy creation of web forms. The following sections will walk you through the highlight functions in the helper, but remember http://api.cakephp.org should always be used as a final reference.

Many of the functions in the HTML helper make use of a HTML tag definition file called tags.ini.php. Cake's core configuration contains a tags.ini.php, but if you'd like to make some changes, create a copy of /cake/config/tags.ini.php and place it in your /app/config/ folder. The HTML helper uses the tag definitions in this file to generate tags you request. Using the HTML helper to create some of your view code can be helpful, as a change to the tags.ini.php file will result in a site-wide cascading change.

Additionally, if AUTO_OUTPUT is set to true in your core config file for your application (/app/config/core.php), the helper will automatically output the the tag, rather than returning the value. This has been done in an effort to assuage those who dislike short tags (<?= ?>) or lots of echo() calls in their view code. Functions that include the $return parameter allow you to force-override the settings in your core config. Set $return to true if you'd like the HTML helper to return the HTML code regardless of any AUTO_OUTPUT settings.

HTML helper functions also include a $htmlAttributes parameter, that allow you to tack on any extra attributes on your tags. For example, if you had a tag you'd like to add a class attribute to, you'd pass this as the $htmlAttribute value:

array('class'=>'someClass')

1.1.2. Inserting Well-Formatted elements

If you'd like to use Cake to insert well-formed and oft-repeated elements in your HTML code, the HTML helper is great at doing that. There are functions in this helper that insert media, aid with tables, and there's even guiListTree which creates an unordered list based on a PHP array.

  • charset ($charset, $return)

    • This is used to generate a charset META-tag.

  • css ($path, $rel= 'stylesheet', $htmlAttributes=null, $return=false)

    • Creates a link to a CSS stylesheet. The $rel parameter allows you to provide a rel= value for the tag.

  • image ($path, $htmlAttributes=null, $return=false)

    • Renders an image tag. The code returned from this function can be used as an input for the link() function to automatically create linked images.

  • link ($title, $url=null, $htmlAttributes=null, $confirmMessage=false, $escapeTitle=true, $return=false)

    • Use this function to create links in your view. $confirmMessage is used when you need a JavaScript confirmation message to appear once the link is clicked. For example, a link that deletes an object should probably have a "Are you sure?" type message to confirm the action before the link is activated. Set $escapeTitle to true if you'd like to have the HTML helper escape the data you handed it in the $title variable.

  • tableHeaders ($names, $tr_options=null, $th_options=null)

    • Used to create a formatted table header.

  • tableCells ($data, $odd_tr_options=null, $even_tr_options=null)

    • Used to create a formatted set of table cells.

  • guiListTree ($data, $htmlAttributes=null, $bodyKey= 'body', $childrenKey='children', $return=false)

    • Generates a nested unordered list tree from an array.

1.1.3. Forms and Validation

The HTML helper really shines when it comes to quickening your form code in your views. It generates all your form tags, automatically fills values back in during error situations, and spits out error messages. To help illustrate, let's walk through a quick example. Imagine for a moment that your application has a Note model, and you want to create controller logic and a view to add and edit Note objects. In your NotesController, you would have an edit action that might look something like the following:

Example 9.1. Edit Action inside of the NotesController

   function edit($id) 
   {
      //First, let's check to see if any form data has been submitted to the action.      
      if (isset($this->params['form']['data']['note'])) 
      {
         //Here's where we try to validate the form data (see Chap. 10) and save it
         if ($this->note->save($this->params['data']))
         {
            //If we've successfully saved, take the user to the appropriate place
            $this->flash('Your information has been saved.', '/notes/edit/' . $id);
            exit();
         }
         else
         {
            //If the data didn't validate, hand the form data back to the view
            $this->set('form', $this->params['data']);
            
            //Generate the error messages for the appropriate fields
            $this->validateErrors($this->note);

            //And render the edit view code
            $this->render();
         }      
      }
      
      //If we haven't received any form data, get the note we want to edit, and hand its information to the view
      $this->set('note', $this->note->find("id = $id"));
      $this->render();
   }

Once we've got our controller set up, lets look at the view code (which would be found in app/views/notes/edit.thtml). Our Note model is pretty simple at this point – it only contains an id, a submitter's id and a body. This view code is meant to display Note data and allow the user to enter new values and save that data to the model.

The HTML helper is available in all views by default, and can be accessed using $html.

Specifically, let's just look at the table where the guts of the form are found:

Example 9.2. Edit View code (edit.thtml) sample

<!-- This tag creates our form tag -->

<?php echo $html->formTag('/notes/edit/' . $note['note']['id'])?>

<table cellpadding="10" cellspacing="0">
<tr>
   <td align="right">Body: </td>
   <td>

      <!-- Here's where we use the HTML helper to render the text area tag and its possible error message
           the $note variable was created by the controller, and contains the data for the note we're editing. -->

      <?php echo $html->textarea('note/body', array('cols'=>'60', 'rows'=>'10', 'value' => $note['note']['body']))?>
      <?php echo $html->tagErrorMsg('note/body', 'Please enter in a body for this note.') ?>
   </td>
</tr>
<tr> 
   <td></td>
   <td>

      <!-- We can also use the HTML helper to include hidden tags inside our table -->

      <?php echo $html->hiddenTag('note/id', $note['note']['id'])?>
      <?php echo $html->hiddenTag('note/submitter_id', $_SESSION['user_id'])?>
   </td>
</tr>
</table>

<!-- And finally, the submit button-->
<?php echo $html->submit()?>

</form>

Most of the form tag generating functions (along with tagErrorMsg) require you to supply a $fieldName. This $fieldName lets Cake know what data you are passing so that it can save and validate the data correclty. The string passed in the $fieldName parameter is in the form "modelname/fieldname." If you were going to add a new title field to our Note, you might add something to the view that looked like this:

<?php echo $html->input('note/title', $note['note']['title']) ?>
<?php echo $html->tagErrorMsg('note/title', 'Please supply a title for this note.')?>

Error messages displayed by the tagErrorMsg() function are wrapped in <div class="error_message"></div> for easy CSS styling.

Here are the form tags the HTML helper can generate (most of them are straightforward):

  • formTag ($target=null, $type='post', $htmlAttributes=null)

    • Generates an opening form tag. Use $target to specify the form's action. Remember, if your form is submitting a file, you need to supply the $htmlAttributes parameter with the proper enctype information.

  • submit ($caption= 'Submit', $htmlAttributes=null, $return=false)

    • Supply an alternate button title using $caption.

  • password ($fieldName, $htmlAttributes=null, $return=false)

  • textarea ($fieldName, $htmlAttributes=null, $return=false)

  • checkbox ($fieldName, $title=null, $htmlAttributes=null, $return=false)

  • file ($fieldName, $htmlAttributes=null, $return=false)

  • hidden ($fieldName, $htmlAttributes=null, $return=false)

  • input ($fieldName, $htmlAttributes=null, $return=false)

  • radio ($fieldName, $options, $inbetween=null, $htmlAttributes=null, $return=false)

  • tagErrorMsg ($field, $text)

The HTML helper also includes a set of functions that aid in creating date-related option tags. The $tagName parameter should be handled in the same way that the $fieldName parameter; Just provide the name of the field this date option tag is relevant to. Once the data is processed, you'll see it in your controller with the part of the date it handles concatenated to the end of the field name. For example, if my Note had a deadline field that was a date, and my dayOptionTag $tagName parameter was set to 'note/deadline', the day data would show up in the $params variable once the form has been submitted to a controller action:

$this->params['form']['data']['note']['deadline_day']

You can then use this information to concatenate the time data in a format that is friendly to your current database configuration. This code would be placed just before you attempt to save the data, and saved in the $data array used to save the information to the model.

Example 9.3. Concatenating time data before saving a model (excerpt from NotesController)

function edit($id) 
   {
      //First, let's check to see if any form data has been submitted to the action.      
      if (isset($this->params['form']['data']['note'])) 
      {

         //Concatenate time data for storage...
         $this->params['data']['note']['deadline'] = $this->params['form']['data']['note']['deadline_year'] . "-" .
                                                     $this->params['form']['data']['note']['deadline_month'] . "-" .
                                                     $this->params['form']['data']['note']['deadline_day'];                           

         //Here's where we try to validate the form data (see Chap. 10) and save it
         if ($this->note->save($this->params['data']))
         {

         ...
  • dayOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)

  • yearOptionTag ($tagName, $value=null, $minYear=null, $maxYear=null, $selected=null, $optionAttr=null)

  • monthOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)

  • hourOptionTag ($tagName, $value=null, $format24Hours=false, $selected=null, $optionAttr=null)

  • minuteOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)

  • meridianOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)

  • dateTimeOptionTag ($tagName, $dateFormat= 'DMY', $timeFormat= '12', $selected=null, $optionAttr=null)

1.2. AJAX

The Cake Ajax helper utilizes the ever-popular Prototype and script.aculo.us libraries for Ajax operations and client side effects. In order to use this helper, you must have a current version of the JavaScript libraries from http://script.aculo.us placed in /app/webroot/js/.

Most of the functions in this helper expect a special $options array as a parameter. This array is used to specify different things about your Ajax operation. Here are the different values you can specify:

Example 9.4. AjaxHelper $options Keys

/* General Options */

$options['url']         // The URL for the action you want to be called.

$options['frequency']   // The number of seconds between remoteTimer() or observeField() checks are made.

$options['update']      // The DOM ID of the element you wish you update with the resuls of a Ajax operation.

$options['with']        // The DOM ID of the form element you wish to serialize and send with an Ajax form submission.

$options['type']        // Either 'asynchronous' (default), or 'synchronous'. Allows you to pick between operation types.

/* Callbacks : JS code to be executed at certain times during the XMLHttpRequest process */

$options['loading']     // JS code to be executed when the remote document is being loaded with data by the browser.

$options['loaded']      // JS code to be executed when the browser has finished loading the remote document.

$options['interactive'] // JS code to be executed when the user can interact with the remote document, even though it has not finished loading.

$options['complete']    // JS code to be called when the XMLHttpRequest is complete.

$options['confirm']     // Text to be displayed in a confirmation dialog before a XMLHttpRequest action begins. 

$optoins['condition']   // JS condition to be met before the XMLHttpRequest is initiated.

$options['before']      // JS code to be called before request is initiated.

$options['after']       // JS code to be called immediately after request was initiated and before 'loading'.

Here are the helper's functions for making Ajax in Cake quick and easy:

  • link ($title, $options=null, $html_options=null)

    • Displays linked text $title, which retrieves the remote document at $options['url'] and updates the DOM element $options['update']. Callbacks can be used with this function.

  • remoteFunction ($options=null)

    • This function creates the JavaScript needed to make a remote call it is primarily used as a helper for linkToRemote. This isn't often used unless you need to generate some custom scripting.

  • remoteTimer ($options=null)

    • Periodically calls the specified action at $options['url'], every $options['frequency'] seconds (default is 10). Usually used to update a specified div (specified by $options['update']) with the results of the remote call. Callbacks can be used with this function.

  • form ($id, $options=null, $html_options=array())

    • Returns a form tag that will submit to the action at $options['url'] using XMLHttpRequest in the background instead of the regular reload-required POST submission. The form data from this form will act just as a normal form data would (i.e. it will be available in $this->params['form']). The DOM element specified by $options['update'] will be updated with the resulting remote document. Callbacks can be used with this function.

  • observeField ($field_id, $options=null)

    • Observes the field with the DOM ID specified by $field_id (every $options['frequency'] seconds) and calls the action at $options['url'] when its contents have changed. You can update a DOM element with ID $options['update'] or specify a form element using $options['with'] as well. Callbacks can be used with this function.

  • observeForm ($form_id, $options=array())

    • Works the same as observeField(), only this observes all the elements in a given form.

  • autoComplete ($field, $url="", $options=array())

    • Renders a text field with ID $field with autocomplete. The action at $url should be able to return the autocomplete terms: basically, your action needs to spit out a unordered list (<ul></ul>) with list items that are the auto complete terms. If you wanted an autocomplete field that retrieved the subjects of your blog posts, your controller action might look something like:

      function autocomplete () {
          $this->set('posts', $this->Post->findAll("subject LIKE '{$this->params['form']['autocomplete_field_name_goes_here']}'"));
          $this->layout = "ajax";
      }

      And your view for the autocomplete() action above would look something like:

      <ul>
      <?php foreach($posts as $post): ?>
      <li><?php echo $post['Post']['subject']; ?></li>
      <?php endforeach; ?>
      </ul>

      autoComplete() will use this information to render a text field, and some divs that will be used to show the autocomplete terms supplied by your action. You might also want to style the view with the $ajax->autoComplete() call something like the following:

      <style type="text/css">
      
      div.auto_complete {
          position         :absolute;
          width            :250px;
          background-color :white;
          border           :1px solid #888;
          margin           :0px;
          padding          :0px;
      }
      
      li.selected { background-color: #ffb; }
      
      </style>
  • drag ($id, $options=array())

    • Makes the DOM element with ID $id draggable. There are some additional things you can specify using $options:

      // (The version numbers refer to script.aculo.us versions)
      
      $options['handle']     // (v1.0) Sets whether the element should only be draggable by an embedded handle. 
                             //  The value must be an element reference or element id.
      
      $options['handle']     // (V1.5) As above, except now the value may be a string referencing a CSS class value. 
                             // The first child/grandchild/etc. element found within the element that has this CSS class value will be used as the handle.
      
      $options['revert']     // (V1.0) If set to true, the element returns to its original position when the drags ends.
      
      $options['revert']     // (V1.5) Revert can also be an arbitrary function reference, called when the drag ends.
      
      $options['constraint'] // If set to ‘horizontal’ or ‘vertical’ the drag will be constrained to take place only horizontally or vertically.
  • drop ($id, $options=array())

    • Makes the DOM element with ID $id drop-able. There are some additional things you can specify using $options:

      $options['accept']      // Set accept to a string or a JavaScript array of strings describing CSS classes. 
                              // The Droppable will only accept Draggables that have one or more of these CSS classes.
      
      $options['containment'] // The droppable element will only accept the draggable element if it is contained in the given 
                              // elements (or element ids). Can be a single element or a JS array of elements.
      
      $options['overlap']     //If set to ‘horizontal’ or ‘vertical’ the droppable will only react to a draggable element if 
                              //its overlapping by more than 50% in the given direction.
  • dropRemote ($id, $options=array(), $ajaxOptions=array())

    • Used to create a drop target that initiates a XMLHttpRequest when a draggable element is dropped on it. The $options are the same as in drop(), and the $ajaxOptions are the same as in link().

  • sortable ($id, $options=array())

    • Makes a list or group of floated objects (specified by DOM element ID $id) sortable. The $options array can configure your sorting as follows:

      $options['tag']         // Sets the kind of tag (of the child elements of the container) that will be made sortable. 
                              // For UL and OL containers, this is ‘LI’, you have to provide the tag kind for other sorts of child tags.
                              // Defaults to 'li'.
      
      $options['only']        // Further restricts the selection of child elements to only encompass elements with the given CSS class 
                              // (or, if you provide an array of strings, on any of the classes).
      
      $options['overlap']     // Either ‘vertical’ (default) or ‘horizontal’. For floating sortables or horizontal lists, choose ‘horizontal’. 
                              // Vertical lists should use ‘vertical’.
      
      $options['constraint']  // Restricts the movement of draggable elements, 'vertical' or 'horizontal'.
      
      $options['containment'] // Enables dragging and dropping between Sortables. Takes an array of elements or element-ids (of the containers).
      
      $options['handle']      // Makes the created draggable elemetns use handles, see the handle option on drag().
      

1.3. Javascript

The JavaScript helper is used to aid the developer in outputting well-formatted Javascript-related tags and data.

  • codeBlock ($script)

    • Used to return $script placed within JavaScript <script> tags.

  • link ($url)

    • Returns a JavaScript include tag pointing to the script referenced by $url.

  • linkOut ($url)

    • Same as link(), only the include tag assumes that the script referenced by $url is not hosted on the same domain.

  • escapeScript ($script)

    • Escapes carriage returns and single and double quotes for JavaScript code segments.

  • event ($object, $event, $observer, $useCapture=true)

    • Attaches an event to an element. Used with the Prototype library.

  • cacheEvents ()

    • Caches JavaScript events created with event().

  • writeEvents ()

    • Writes cached events cached with cacheEvents().

  • includeScript ($script="")

    • This tag returns JavaScript include tags for all of the scripts currently residing in Cake's JavaScript directory (/app/webroot/js/).

1.4. Number

The Number helper includes a few nice functions for formatting numerical data in your views.

  • precision ($number, $precision=3)

    • Returns $number formatted to the level of precision specified by $precision.

  • toReadableSize ($size)

    • Returns a human readable size, given the $size supplied in bytes. Basically, you pass a number of bytes in, and this function returns the appropriate human-readable value in KB, MB, GB, or TB.

  • toPercentage ($number, $precision=2)

    • Returns the given number formatted as a percentage, limited to the precision specified in $precision.

1.5. Text

The Text Helper provides methods that a developer may need for outputting well formatted text to the browser.

  • highlight ($text, $phrase, $highlighter= '< span class="highlight">\1</span >')

    • Returns $text, with every occurance or $phrase wrapped with the tags specified in $highlighter.

  • stripLinks ($text)

    • Returns $text, with all HTML links (<a href= ...) removed.

  • autoLinkUrls ($text, $htmlOptions=array())

    • Returns $text with URLs wrapped in corresponding <a> tags.

  • autoLinkEmails ($text, $htmlOptions=array())

    • Returns $text with email addresses wrapped in corresponding <a> tags.

  • autoLink ($text, $htmlOptions=array())

    • Returns $text with URLs and emails wrapped in corresponding <a> tags.

  • truncate ($text, $length, $ending='...')

    • Returns the first $length number of characters of $text followed by $ending ('...' by default).

  • trim ()

    • Alias for truncate().

  • excerpt ($text, $phrase, $radius=100, $ending="...")

    • Extracts an excerpt from the $text, grabbing the $phrase with a number of characters on each side determined by $radius.

  • flay($text, $allowHtml=false)

    • Text-to-html parser, similar to Textile or RedCloth, only with a little different syntax.

1.6. Time

The Time Helper provides methods that a developer may need for outputting Unix timestamps and/or datetime strings into more understandable phrases to the browser.

Dates can be provided to all functions as either valid PHP datetime strings or Unix timestamps.

  • fromString ($date_string)

    • Returns a UNIX timestamp, given either a UNIX timestamp or a valid strtotime() date string.

  • nice ($date_string=null, $return=false)

    • Returns a nicely formatted date string. Dates are formatted as "D, M jS Y, H:i", or 'Mon, Jan 1st 2005, 12:00'.

  • niceShort ($date_string=null, $return=false)

    • Formats date strings as specified in nice(), but ouputs "Today, 12:00" if the date string is today, or "Yesterday, 12:00" if the date string was yesterday.

  • isToday ($date_string)

    • Returns true if given datetime string is today.

  • daysAsSql ($begin, $end, $field_name, $return=false)

    • Returns a partial SQL string to search for all records between two dates.

  • dayAsSql ($date_string, $field_name, $return=false)

    • Returns a partial SQL string to search for all records between two times occurring on the same day.

  • isThisYear ($date_string, $return=false)

    • Returns true if given datetime string is within current year.

  • wasYesterday ($date_string, $return=false)

    • Returns true if given datetime string was yesterday.

  • isTomorrow ($date_string, $return=false)

    • Returns true if given datetime string is tomorrow.

  • toUnix ($date_string, $return=false)

    • Returns a UNIX timestamp from a textual datetime description. Wrapper for PHP function strtotime().

  • toAtom ($date_string, $return=false)

    • Returns a date formatted for Atom RSS feeds.

  • toRSS ($date_string, $return=false)

    • Formats date for RSS feeds

  • timeAgoInWords ($datetime_string, $return=false)

    • Returns either a relative date or a formatted date depending on the difference between the current time and given datetime. $datetime should be in a strtotime-parsable format like MySQL datetime.

  • relativeTime ($datetime_string, $return=false)

    • Works much like timeAgoInWords(), but includes the ability to create output for timestamps in the future as well (i.e. "Yesterday, 10:33", "Today, 9:42", and also "Tomorrow, 4:34").

  • wasWithinLast ($timeInterval, $date_string, $return=false)

    • Returns true if specified datetime was within the interval specified, else false. The time interval should be specifed with the number as well as the units: '6 hours', '2 days', etc.