Using the before save and after save functions in Yii2

Blog image

Yii2 is a great framework for rapidly building web apps. Yii2 has tons of built in tools and functions to make your life easier. One of those functions is the active record implementation which includes the very handy before save and after save functions. These two functions are part of the saving life-cycle of a model and allow you to perform certain actions just before the model saves to the database, and then just after. There are tons of great reasons to use these functions. Keep reading for more life changing information!

Before save

Using the beforeSave function is great for:

  • Adding created and updated dates
  • Adding default values
  • Creating generated attributes

beforeSave created and updated date example

I regularly use the beforeSave function to input updated and created dates for my models.

Below is an example of using the beforeSave function to add an updated and created date example:

/**
 * Invoice model
 */
class Invoice extends \yii\db\ActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public function beforeSave($insert)
    {
        if ($this->isNewRecord) {

            $this->created_datetime = date('Y-m-d H:i:s');
        }

        $this->updated_datetime = date('Y-m-d H:i:s');

        return parent::beforeSave($insert);
    }
}

You can use whatever method you like to generate the date/datetime, in this case i simply used the php date function. We use the built in Yii2 $this->isNewRecord function to check if the Invoice is new and if so create the original created_datetime which should never be changed after that point. beforeSave generated attributes example

I often use the beforeSave function to create generated attributes, for example like a token to obscure a models ID when viewing it on your web apps frontend. Token are useful when you don’t want end users to guess id’s and view all your records, ideal for something like invoices or receipts.

Below is an example of using the beforeSave function to create a token, via a trait in this case the TokenTrait which is a separate PHP trait class.

use namespace\traits\TokenTrait;

/**
 * Invoice model
 */
class Invoice extends \yii\db\ActiveRecord
{
    use TokenTrait;

    // your other typical model functions go here

    /**
     * {@inheritdoc}
     */
    public function beforeSave($insert)
    {
        if ($this->isNewRecord) {

            $this->id_token = $this->generateUniqueToken('invoice', 30);
        }

        return parent::beforeSave($insert);
    }
}

After save

Using the afterSave function is ideal for:

  • Working with related records
  • Triggering actions

afterSave Amazon style delivery address contacts

If you use Amazon you might have seen how when you add a new shipping address it saves it to your account so you can use it again later. I have mimicked the same functionality in one of my Yii2 modules. When you add shipping to an invoice after you save the invoice it checks to see if the customer the invoice is issued to has a contact/address that matches the shipping recipient and address. If the customer already has it it ignores it, but if not it adds it as a new contact/address for future usage.

The below example is from my Shipping model and triggers the Contact model to check if the contact exists and if not it creates it.

use namespace\models\Contact;

/**
 * Shipping model
 */
class Shipping extends \yii\db\ActiveRecord
{
    // your other typical model functions go here

    /**
     * {@inheritdoc}
     */
    public function afterSave($insert, $changedAttributes)
    {
        if ($this->isNewRecord) {
        }

        if (Contact::doesContactExist(
            $this->invoice->customer->id,
            $this->name,
            $this->address,
            $this->phone,
            $this->email
        ) == False) {
            Contact::createFromShipping($this);
        }

        return parent::afterSave($insert, $changedAttributes);
    } 
}

Final word and beforeValidation Vs beforeSave

So that about wraps up my quick examples on using Yii2 beforeSave and afterSave. The final point to mention would be beforeSave or beforeValidation. If you model for example has a required field that will need to be populated to pass validation, then you should use beforeValidation function over beforeSave to ensure the model->save() function does not fail on the validation. Resources: