arrow_back
Back

Yii2 Active Record: models, relations, find, and save

Andrew Dorokhov Andrew Dorokhov schedule 2 min read
menu_book Table of Contents

Queries

Because yii\db\ActiveQuery extends from yii\db\Query, you can use all query building methods and query methods.

A call to yii\db\ActiveRecord::find() always returns an ActiveQuery object.

Get a single record:

$customer = Customer::find()
    ->where(['id' => 123])
    ->one();

Get many records:

$customers = Customer::find()
    ->where(['status' => Customer::STATUS_ACTIVE])
    ->orderBy('id')
    ->all();

Relational queries:

$orders = $customer->getOrders()
    ->where(['>', 'subtotal', 200])
    ->orderBy('id')
    ->all();

Using OR operator:

$events_tba_active = Event::find()
    ->where(['makes_sense' => 1, 'type' => Event::TYPE_WITHOUT_DATE])
    ->andWhere(['OR', ['<=', 'date', new Expression('CURDATE()')], ["date" => null]])
    ->orderBy('date ASC')
    ->all();

Check if a value is null:

$query->andFilterWhere(['is', 'hourly_range', new Expression('null')]);

Another variant of specifying conditions:

Job::deleteAll("created_timestamp < $time_border AND hit != 1");

More complex example:

// DELETE FROM job WHERE publication_timestamp < $time_border AND (starred = 0 OR (starred = 1 AND viewed = 1) )
return Job::deleteAll(
    ['AND', ['<', 'publication_timestamp', $time_border], ['OR', ['starred' => 0], ['starred' => 1, 'viewed' => 1]]]
);

Comparison operators are given as the first element of the condition array:

$records = Record::find()
    ->where(['>=', 'row_index', $range_from])
    ->limit($amount)
    ->all();

Lazy and eager loading

Lazy loading means related data is fetched on demand. The code below runs an extra query per post:

<p>Category: <?= $post->category->name ?></p>

Eager loading fetches the related records together with the primary ones:

$posts = Post::find()->with('category')->all();

Dynamic relational queries

Worth remembering:

$customer->getOrders(); // returns an ActiveQuery
$customer->orders;      // returns ActiveRecord objects

Because the getter returns a query, the relation can be refined before execution:

$orders = $customer->getOrders()
    ->where(['>', 'subtotal', 200])
    ->orderBy('id')
    ->all();

Events

Hook into the record lifecycle by overriding the corresponding methods. Always call the parent implementation and respect its result:

public function beforeSave($insert)
{
    if (!parent::beforeSave($insert)) {
        return false;
    }

    // Actions...

    return true;
}
public function beforeDelete()
{
    if (!parent::beforeDelete()) {
        return false;
    }

    // Actions...

    return true;
}

Inside these methods you can tell an insert from an update:

if ($this->getIsNewRecord()) {
    // ...
}
code

Need Help with Development?

Happy to help — reach out via the contacts or go straight to my Upwork profile.

work View Upwork Profile arrow_forward
Next Article

Yii2 Query Builder: SQL composition, conditions, and joins

arrow_forward