Hidden model fields, revisited

Two days ago I wrote a post about hidden model fields. That solution had a drawback – you couldn’t read a field once it was hidden. There was also a bug – hidden fields were shown when their values was null. Here’s upgraded version:

class AppModel extends Model {
  var $hiddenFields = array();
 
  /**
   * Sets given fields as hidden.
   *
   * @param array $fields List of fields
   * @return void
   */
  function hideFields($fields = array()) {
    foreach ($fields as $field)
      if (!in_array($field, $this->hiddenFields))
        $this->hiddenFields[] = $field;
  }
 
  /**
   * Sets given fields as visible.
   *
   * @param array $fields List of fields
   * @return void
   */
  function showFields($fields = array()) {
    foreach ($fields as $field)
      foreach ($this->hiddenFields as $k => $hiddenField)
        if ($hiddenField == $field)
          unset($this->hiddenFields[$k];
  }
 
  /**
   * Callback function.
   * Removes fields marked as hidden from the results of find operation.
   *
   * @param array $result Results of find operation
   * @param bool $primary Whether model is being queried directly
   */
  function afterSave($result, $primary = false) {
    foreach ($result as &$row)
      foreach ($this->hiddenFields as $field)
        if (array_key_exists($field, $row[$this->name]))
          unset($row[$this->name][$field]);
  }
}

The usage is pretty simple and intuitive. You can mark certain fields as hidden in your model definition, as shown in original post, but you can also show and hide them from wherever you like. For example in controller (assuming that ‘password’ field is marked as hidden in User model):

function show_me_my_password() {
  $this->User->showField(array('password'));
  $this->User->read(null, 1);
  // do something...
}

It’s just example. Generally you should avoid showing passwords as plain text for security reasons. You should always even keep them in encrypted form, ie. hashed. You won’t need to ever decrypt them. Instead of retrieving password from database for comparision during logging in, hash it and compare hashes. Instead of retrieving it to remind it to the user, generate new one.