ка

В этой статье я решил предоставить как можно больше примеров, т.к. здесь они гораздно полезнее рассуждений.

Однако, если что-то останется непонятным, то полную документацию по работе с ActiveRecord в Yii2 всегда можно найти по ссылке:

https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/db-active-record.md

Это ссылка на документацию, которая постоянно обновляется и дополняется.

Извлечение данных

// возвращает покупателя с идентификатором 123
// SELECT * FROM `customer` WHERE `id` = 123
$customer = Customer::find()
    ->where(['id' => 123])
    ->one();

// возвращает всех активных покупателей, сортируя их по идентификаторам
// SELECT * FROM `customer` WHERE `status` = 1 ORDER BY `id`
$customers = Customer::find()
    ->where(['status' => Customer::STATUS_ACTIVE])
    ->orderBy('id')
    ->all();

// возвращает количество активных покупателей
// SELECT COUNT(*) FROM `customer` WHERE `status` = 1
$count = Customer::find()
    ->where(['status' => Customer::STATUS_ACTIVE])
    ->count();

// возвращает всех покупателей массивом, индексированным их идентификаторами
// SELECT * FROM `customer`
$customers = Customer::find()
    ->indexBy('id')
    ->all();

Шорткаты для методов, которые сразу возвращают данные:

// возвращает покупателя с идентификатором 123
// SELECT * FROM `customer` WHERE `id` = 123
$customer = Customer::findOne(123);

// возвращает покупателей с идентификаторами 100, 101, 123 и 124
// SELECT * FROM `customer` WHERE `id` IN (100, 101, 123, 124)
$customers = Customer::findAll([100, 101, 123, 124]);

// возвращает активного покупателя с идентификатором 123
// SELECT * FROM `customer` WHERE `id` = 123 AND `status` = 1
$customer = Customer::findOne([
    'id' => 123,
    'status' => Customer::STATUS_ACTIVE,
]);

// возвращает всех неактивных покупателей
// SELECT * FROM `customer` WHERE `status` = 0
$customers = Customer::findAll([
    'status' => Customer::STATUS_INACTIVE,
]);

Note: Ни метод [[yii\db\ActiveRecord::findOne()]], ни [[yii\db\ActiveQuery::one()]] не добавляет условие LIMIT 1 к генерируемым SQL-запросам. Если ваш запрос может вернуть много строк данных, вы должны вызвать метод limit(1) явно в целях улучшения производительности, например: Customer::find()->limit(1)->one().

Пример на голом SQL

// возвращает всех неактивных покупателей
$sql = 'SELECT * FROM customer WHERE status=:status';
$customers = Customer::findBySql($sql, [
    ':status' => Customer::STATUS_INACTIVE
])->all();

Можно получить данные в виде массива:

// возвращает всех покупателей
// каждый покупатель будет представлен в виде ассоциативного массива
$customers = Customer::find()
    ->asArray()
    ->all();

Пример пакетной выборки для снижения потребления ресурсов:

// получить 10 покупателей одновременно
foreach (Customer::find()->batch(10) as $customers) {
    // $customers - это массив, в котором находится 10 
    // или меньше объектов класса Customer
}

// получить одновременно десять покупателей и перебрать их одного за другим
foreach (Customer::find()->each(10) as $customer) {
    // $customer - это объект класса Customer
}

// пакетная выборка с жадной загрузкой
foreach (Customer::find()->with('orders')->each() as $customer) {
    // $customer - это объекта класса Customer
}

Обновление счетчика. Метод save() здесь не особо пригоден из-за параллельных запросов.

$post = Post::findOne(100);

// UPDATE `post` SET `view_count` = `view_count` + 1 WHERE `id` = 100
$post->updateCounters(['view_count' => 1]);

ActiveRecord не получает автоматически данные по умолчанию из таблиц. Но их можно загрузить:

$customer = new Customer();
$customer->loadDefaultValues();
// $customer->xyz получит значение по умолчанию, 
// которое было указано при объявлении столбца "xyz"

Обновление данных

Обновление нескольких строк в таблице:

// UPDATE `customer` SET `status` = 1 WHERE `email` LIKE `%@example.com%`
Customer::updateAll(
    ['status' => Customer::STATUS_ACTIVE], 
    ['like', 'email', '@example.com']
);

Обновление счетчиков:

// UPDATE `customer` SET `age` = `age` + 1
Customer::updateAllCounters(['age' => 1]);

Удаление данных

$customer = Customer::findOne(123);
$customer->delete();

Удаление сразу многих записей. Осторожно: немного напортачишь с условиями и удалятся все данные.

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);

Работа с транзакциями

$customer = Customer::findOne(123);

Customer::getDb()->transaction(function($db) use ($customer) {
    $customer->id = 200;
    $customer->save();
    // ...другие операции с базой данных...
});

// или по-другому

$transaction = Customer::getDb()->beginTransaction();
try {
    $customer->id = 200;
    $customer->save();
    // ...другие операции с базой данных...
    $transaction->commit();
} catch(\Exception $e) {
    $transaction->rollBack();
    throw $e;
} catch(\Throwable $e) {
    $transaction->rollBack();
    throw $e;
}

Так можно указать в ActiveRecord, какие именно операции требуют транзакционного выполнения:

class Customer extends ActiveRecord
{
    public function transactions()
    {
        return [
            'admin' => self::OP_INSERT,
            'api' => self::OP_INSERT | self::OP_UPDATE | self::OP_DELETE,
            // вышеприведённая строка эквивалентна следующей:
            // 'api' => self::OP_ALL,
        ];
    }
}

Связи

class Customer extends ActiveRecord
{
    public function getOrders()
    {
        return $this->hasMany(Order::className(), ['customer_id' => 'id']);
    }
}

class Order extends ActiveRecord
{
    public function getCustomer
                        
Источник: Перейти
Комментарии (0):
Чтобы оставить свой комментарий, необходимо пройти аутентификацию