108 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						||
 | 
						||
namespace dominion\db;
 | 
						||
 | 
						||
use Yii;
 | 
						||
 | 
						||
/**
 | 
						||
 * Обертка над стандартным классом \yii\db\Query
 | 
						||
 * Описывает общие методы для работы, которые могут понадобиться при запросах
 | 
						||
 */
 | 
						||
class Query extends \yii\db\Query
 | 
						||
{
 | 
						||
 | 
						||
    /**
 | 
						||
     * Множественное обновление записей в таблице по первичному ключу id
 | 
						||
     * @param string $table Название таблицы бд
 | 
						||
     * @param array $data Массив данных для обновления
 | 
						||
     * Например:
 | 
						||
     * [
 | 
						||
     * 	23 => ['name' => 'обновленное название 23', 'description' => 'обновленное описание 23'],
 | 
						||
     * 	24 => ['name' => 'обновленное название 24', 'description' => 'обновленное описание 24'],
 | 
						||
     * ]
 | 
						||
     * Обновит поля name и description у полей с id=23 и id=24 одним запросом
 | 
						||
     * @return int Количество обновленных записей
 | 
						||
     */
 | 
						||
    public function batchUpdate($table, $data)
 | 
						||
    {
 | 
						||
        $fields = [];
 | 
						||
        $columns = [];
 | 
						||
        $rows = [];
 | 
						||
        foreach ($data as $id => $values)
 | 
						||
        {
 | 
						||
            if (empty($columns))
 | 
						||
            {
 | 
						||
                $fields = array_keys($values);
 | 
						||
                $columns = array_merge(['id'], $fields);
 | 
						||
            }
 | 
						||
 | 
						||
            $row = [$id];
 | 
						||
            foreach ($values as $value)
 | 
						||
            {
 | 
						||
                $row[] = $value;
 | 
						||
            }
 | 
						||
 | 
						||
            $rows[] = $row;
 | 
						||
        }
 | 
						||
 | 
						||
        $sql = Yii::$app->db->getQueryBuilder()->batchInsert($table, $columns, $rows);
 | 
						||
        $update = [];
 | 
						||
        foreach ($fields as $field)
 | 
						||
        {
 | 
						||
            $field = Yii::$app->db->quoteColumnName($field);
 | 
						||
            $update[] = $field . ' = VALUES(' . $field . ')';
 | 
						||
        }
 | 
						||
 | 
						||
        if (!empty($update))
 | 
						||
        {
 | 
						||
            $sql .= ' ON DUPLICATE KEY UPDATE ' . implode(',', $update);
 | 
						||
        }
 | 
						||
        \Yii::beginProfile('batchUpdate_' . $table);
 | 
						||
        $result = Yii::$app->db->createCommand($sql)->execute();
 | 
						||
        \Yii::endProfile('batchUpdate_' . $table);
 | 
						||
        return $result;
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * Множественное добавление записей в таблицу
 | 
						||
     * @param string $table Название таблицы бд
 | 
						||
     * @param array $data Массив данных для добавления
 | 
						||
     * Например:
 | 
						||
     * [
 | 
						||
     * 	['name' => 'Название 1', 'description' => 'Описание 1'],
 | 
						||
     * 	['name' => 'Название 2', 'description' => 'Описание 2'],
 | 
						||
     * ]
 | 
						||
     * Добавит две записи с заполненными полями name и description одним запросом
 | 
						||
     * Если в массиве больще 5000 элементов, то будет несколько запросов с добавлением по 5000 элементов в одном запросе
 | 
						||
     */
 | 
						||
    public function batchInsert($table, $data)
 | 
						||
    {
 | 
						||
        $columns = [];
 | 
						||
        $rows = [];
 | 
						||
        foreach ($data as $values)
 | 
						||
        {
 | 
						||
            if (empty($columns))
 | 
						||
            {
 | 
						||
                $columns = array_keys($values);
 | 
						||
            }
 | 
						||
 | 
						||
            $row = [];
 | 
						||
            foreach ($values as $value)
 | 
						||
            {
 | 
						||
                $row[] = $value;
 | 
						||
            }
 | 
						||
 | 
						||
            $rows[] = $row;
 | 
						||
        }
 | 
						||
 | 
						||
        $limit = 5000;
 | 
						||
        $count = (int) floor(count($rows) / $limit);
 | 
						||
        for ($i = 0; $i <= $count; $i++)
 | 
						||
        {
 | 
						||
            $partRows = array_slice($rows, $i * $limit, $limit);
 | 
						||
            Yii::$app->db->createCommand()->batchInsert($table, $columns, $partRows)->execute();
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
}
 |