Using behaviors to add new fields for saving

In the recipe Using callbacks in behaviors we learnt how to implement different model callbacks to perform some tasks automatically. In this recipe we will continue that process and we will learn how to automatically save data that may not be provided in a save operation.

We will use the Twitter example we have been using in this chapter, so that when a profile is saved, its Twitter URL and its last tweet are saved when creating a new record, or when updating an existing one.

Getting ready

We need a working TwitterAccountBehavior together with its controllers, models, and views. Follow the recipe Using callbacks in behaviors (there's no need to enable caching in the behavior, so you can omit the There's more section).

Add two fields to the profiles table, url and last_tweet, by issuing the following SQL command:

ALTER TABLE `profiles`
ADD COLUMN `url` VARCHAR(255) default NULL,
ADD COLUMN `last_tweet` VARCHAR(140) default NULL;

How to do it...

  1. Edit your app/models/behaviors/twitter_account.php file and add the following beforeSave implementation to the TwitterAccountBehavior class:
    public function beforeSave($model) {
    $field = $this->settings[$model->alias]['field'];
    $twitter = null;
    if (!array_key_exists($field, $model->data[$model->alias]) && $model->exists()) {
    $twitter = $model->field($field, array(
    $model->primaryKey => $model->id
    ));
    } elseif (array_key_exists($field, $model->data[$model->alias])) {
    $twitter = $model->data[$model->alias][$field];
    }
    $data = array(
    'url' => !empty($twitter) ? 'http://twitter.com/' . $twitter : null,
    'last_tweet' => null
    );
    if (!empty($twitter)) {
    $tweets = $this->timeline($twitter, 1);
    if (!empty($tweets) && is_array($tweets)) {
    $data['last_tweet'] = $tweets[0]->text;
    }
    }
    $model->data[$model->alias] = array_merge(
    $model->data[$model->alias],
    $data
    );
    $this->_addToWhitelist($model, array_keys($data));
    return parent::beforeSave($model);
    }
    
  2. Whenever we create a new profile with a valid Twitter account, both the url and last_tweet fields will be automatically populated. If we are instead modifying a profile, the last_tweet field will be updated to reflect the latest tweet from the relevant account.

How it works...

The beforeSave callback is triggered before a save operation is performed on a model, giving us the chance to add new fields to the set of fields that are about to be saved, or modify other field values.

We started by determining which Twitter account is linked to the profile being saved. If no Twitter account is specified in the data that is about to be saved, and if we are modifying an existing record (we use $model->exists() for this check), we obtain the account specified in its twitter field. If instead there's an account specified in the data to be saved, we use that instead.

Regardless of the type of save operation that is about to be performed (creating or updating a record), we set the last_tweet field to the last tweet published by the specific Twitter account. However, we set the url field to the appropriate URL-based, on the Twitter account only when we are creating a new record.

Once we have set the data to be saved in the $data array, we append that data to the $model->data property that contains all the information that will be saved. We then use the behavior's _addToWhitelist() method, defined in CakePHP's ModelBehavior class from which our behavior extends, so that if the developer has chosen to limit the save operation to only a specific set of fields, then our fields are guaranteed to be saved regardless of this restriction.

See also

  • Using callbacks in behaviors
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.250.157