Ответы пользователя по тегу Yii
  • Как сделать сортировку связанных таблиц в Yii2?

    @yiiworld
    1) вы сортируете строки, а не числа, поэтому вам кажется что сортировка не работает. Используйте для хранения цен числовые форматы данных в MySQL, например DECIMAL. Но лучше всего использовать Integer(или BigInt) и хранить в них копейки или тысячные доли копеек в зависимости от требуемой точности
    2) пагинация тоже работает правильно, просто вы передаете в нее не то что подразумеваете - в totalCount вы передаете объект который подвержен мутациям. Нужно клонировать первоначальный объект от которого зависит пагинация и исполдьзовать его для count
    Controller action:
    public function actionIndex()
    {
        $query = Article::find()->where(['status' => 1]);
        $countQuery = clone $query;
        $pages = new Pagination(['totalCount' => $countQuery->count()]);
        $models = $query->offset($pages->offset)
            ->limit($pages->limit)
            ->all();
    
        return $this->render('index', [
             'models' => $models,
             'pages' => $pages,
        ]);
    }

    View:
    foreach ($models as $model) {
        // display $model here
    }
    
    // display pagination
    echo LinkPager::widget([
        'pagination' => $pages,
    ]);
    Ответ написан
    9 комментариев
  • Кеш Yii2 не работает на высоких нагрузках, что делать?

    @yiiworld
    Тоже столкнулся с проблемой параллельных запросов и на формирование данных при пустом кэше.
    Рабочее решение: (только свои константы подставьте)
    static function getData($waiting_deep = 0)
        {
            //достаем $prts из кэша
            if (!(Yii::$app->cache->exists(self::CACHE_KEY__PRTS) AND is_array($prts = Yii::$app->cache->get(self::CACHE_KEY__PRTS)) AND isset($prts['version']) AND isset($prts['data']) AND is_array($prts['data']))) {
                // данных в кэше нет
                // выполняем процедуру подготовки данных с блокировкой для других процессов - чтобы другой процесс не начал делать тоже самое. В кэш поместить флаг блокировки Yii::$app->cache->set(CACHE_KEY__PRTS_FLAG_LOCK), а после подготовки данных и помещения их в кэш снять этот флаг блокировки. Если другой параллельный запрос не находит данных в кэше и при этом выставлен флаг блокировки Yii::$app->cache->exists(CACHE_KEY__PRTS_FLAG_LOCK), то он будет ожидать несколько(столькол сколько задана максимальная глубина ожидания) раз. Ограничиваем число ожиданий и интервал этих ожиданий.
                if (Yii::$app->cache->exists(self::CACHE_KEY__PRTS_FLAG_LOCK) AND Yii::$app->cache->get(self::CACHE_KEY__PRTS_FLAG_LOCK)) {
                    if ($waiting_deep <= self::PRTS_FIND__WAITING_DEEP_MAX) {
                        usleep(self::PRTS_FIND__INTERVAL_WAITING_NEXT_CHECK_MICROSECONDS);
                        $prts = self::findPromoactionsRuleToShow($waiting_deep++);
                    } else {
                        return false;
                    }
                } else {
                    Yii::$app->cache->set(self::CACHE_KEY__PRTS_FLAG_LOCK, true, 10); //сбросить флаг блокировки через 10 секунд в любом случае. Необходимо на случай ошибок при подготовки правил и следовательно невозможности в штатном режиме сбросить флаг блокировки.
                    if (!($prts = self::prepareData())!==false){
    					// кладем данные в кэш
    					Yii::$app->cache->set(self::DATA_PRTS, $prts);
    				}
    				// Сбрасываем флаг блокировки
    					// Yii::$app->cache->set(self::CACHE_KEY__PRTS_FLAG_LOCK, false);
    				Yii::$app->cache->delete(self::CACHE_KEY__PRTS_FLAG_LOCK);
                }
            }
            return true;
        }
    Ответ написан
    Комментировать
  • Как решить проблему медленного мета запроса Yii2 Active Record?

    @yiiworld
    - кеширование это конечно хорошо, но 4 сек это не отменяет
    - такое ощущение что вашей INFORMATION_SCHEMA не хватает индексов (или с ними проблема)
    Ответ написан
  • Yii2 транзакции и события/поведения модели?

    @yiiworld
    Если у вас журнал(лог) уходит в сервис у которого нету сторнирующей функции, то можно реализовать сторнирующую функцию используя врeменный журнал в таблице той же БД, чтобы транзакционная связь была. Объединять очереди логов по transactionUniqueID. Потом по rollback чистим записи, а по commit отправляем лог в сервис и потом чистим записи. Такая себе отложенная очередь выполняемая только по событию after_commit.
    Ответ написан
    Комментировать
  • Как сделать выборку по текущей дате при помощи ActiveRecord в Yii2?

    @yiiworld
    $where =['DATE(`time`)' => new \yii\db\Expression('CURDATE()')];//текущая дата относительно серверного времени базы данных
    // или
    $where =['DATE(`time`)' => date('Y-m-d')];//текущая дата относительно серверного времени интерпретатора php
    // или
    $where =['DATE(`time`)' => '2135-12-25'];//требуемая дата
    ModelActiveRecord::find()
                ->where($where)
                ->all();

    и если строк в таблице много, то обязательно создайте индекс для поля time
    CREATE INDEX idx_tableName_time ON tableName(time);
    Ответ написан
    Комментировать
  • Как подключить настройки swift_smtptransport в config из БД в yii2?

    @yiiworld
    Есть такой модуль
    yii2-config
    Можно актуальные настройки хранить в массиве, и актуализировать их в БД
    yii config/rescan
    Ответ написан
  • Yii2 как реализовать перенаправление пользователя в свой профиль?

    @yiiworld
    А еще можно использовать события, которые для этого предназначены и не перегружать методы
    $user = \Yii::$app->user;
    $user->on($user::EVENT_AFTER_LOGIN, [$this, 'complexRedirectFilter']);
    Ответ написан
    Комментировать
  • Select MIN MAX в activerecord yii2?

    @yiiworld
    $query->find()
    ->select(['min(table_name.price)'])
    ->groupBy(['id'])
    ->all();

    в качестве id укажите свой уникальный идентификатор таблицы относительно строк которой вы хотите получить выборку. Или если уникальный идентификатор составной, то укажите поля из которых он состоит через запятую
    $query->find()
    ->select(['min(table_name.price)'])
    ->groupBy(['field1','field2','field3'])
    ->all();
    Ответ написан
    Комментировать
  • При настройке чпу у yii advanced отваливаются стили, в чем проблема?

    @yiiworld
    Если вы под стилями имеете ввиду CSS, то привели бы конкретный пример "отваливания" стиля.
    Копайте в сторону где вы используете относительные пути для подключения css, а также где вы используете относительные пути в самом CSS
    Ответ написан
    Комментировать
  • Как проверить csrf токен вручную?

    @yiiworld
    actionMethoddd(){
    // получаем переданный токен из заголовков, тела запроса, json или где вы там его передаете
    // достаем из места хранение "ранее сохраненный" токен для данной сессии(условно - пользователь, аккаунт, id приложения)
    // сравниваем друг с дружкой
    // ПРОФИТ
    }


    Только что-то мне подсказывает, что csrf токен вам и не нужен. А нужен токен(строка) который будет являться секретным ключом для идентификации сессии пользователя(уникальный для каждого пользователя)
    Ответ написан
    1 комментарий
  • Как сделать в yii2, чтобы в чпу были символьные коды разделов элементов?

    @yiiworld
    Напишите мне - дам вам рабочий пример кода из проекта.
    Ответ написан
    Комментировать
  • Почему после подгрузки полей формы через jquery load(), yii2 их не принимает в model?

    @yiiworld
    ваша проблема скорее всего здесь

    ... 'prospects[]' ...
    попробуйте так
    ...
    $form->field($model, 'prospects')->
    ...
    Ответ написан
  • В чем разница между этими запросами?

    @yiiworld
    1) результатом будет массив с объектами класса модели(наследника ActiveRecord), каждый из которых содержит данные выборки конкретной записи в БД
    Дальше этими результатами можно манипулировать(изменять и сохранять) используя механизмы ActiveRecord.
    2) результатом будет массив содержащий выборку записей из БД
    Ответ написан
    Комментировать
  • Почему updateAll не изменяет последнее поле?

    @yiiworld
    Как минимум нужно строковые операторы в кавычки взять ))
    Orders::updateAll(['partner_commission_payment_id' => $newCommissionsPayment->id], ['partner_id' => 2]);

    А использование в SQL двойных кавычек не по назначению весьма сомнительное удовольствие.
    Разберитесь в чем разница между тремя этими видами кавычек ` `, ' ', " "
    Ответ написан
  • Yii2 не работает сценарий выводит все поля, в чем подвох?

    @yiiworld
    Сценарии используются для проверки и преобразования данных.
    Для вашего случая нужно просто выбрать 2 поля:
    $resultArray = SettingsUser::find()->select(['show_name', 'show_nickname'])
        ->where(['id_user' => Yii::$app->request->post('author')])->asArray()->one();
    Ответ написан
    2 комментария
  • Как сделать такой Where в SQL-запросе на ActiveRecord?

    @yiiworld
    $arQuery->AutoParams::find()
    ...
    ->where[['in', ['feature_id','value'], [ [424, 'Бензин'], [424, 'Гибрид'], [424, 'Дизель']]]]
    -orWhere(['in', ['feature_id','value'], [ [425,'Автоматическая'], [425, 'Ручная']]])
    -orWhere(['in', ['feature_id','value'], [ [426, 'Седан'], [426, 'Фургон'], [426, 'Универсал'] ]])
    ...
    ->all();
    Ответ написан
    Комментировать
  • "Кошерна" ли такая логика модели в Yii2?

    @yiiworld
    Сам вопрос задан не "кошерно" ))
    Вар.1) логика вашего AfterFind (для отображения) действительно должна быть только в представлении. Т.е. работать с данными в модели удобнее в едином формате(например в том формате в котором вы их получаете из БД) (кроме случаев когда это невозможно).
    Вар.2) нахождение логики подготовки данных в BeforeSave немного не кошерно т.к. данные до отображения и после получения будут иметь разный формат. Поэтому предпочтительно эту логику выполнить там где данные были получены(например входящий POST в контроллере)
    Вар.3) А для вашего "Хочется "целостности"" - тут "плясать" надо от формата данных с которым вы работаете в модели(опорный формат). В таком случае:
    - перед сохранением(для проверки соответствия и преобразования) используете валидацию (см.Автономные валидаторы) или [не так кошерно]beforeSave()
    - после получения из БД выполняете преобразование в afterFind()
    - для отображения выполняете преобразование в представлениях
    - для получения из запроса выполняете преобразование в контроллере
    и все эти 4 функции(static) приспокойненько располагаете в базовой модели(или основной, если нет базовой) и дергаете их по мере необходимости.
    PS: ответы про сеттеры и геттеры это конечно хорошо, но они как таковые просто инструмент а не решение (для Вар3 можно сделать геттеры(и по необходимости сеттеры) для каждого случая(и соответственно 4 виртуальных атрибута), а можно использовать функции преобразования напрямую)
    PPS: товарищ Максим Федоров, который за форматирование на JS, пишет уж совсем глупые вещи(читайте комментарии про js и общую архитектуру), (ИМХО). Но тут и диссонанс - в других ответах на тостере он вполне себе здраво рассуждает.
    Ответ написан
  • Лучший способ хранения временных результатов поиска, полученных через VK API (в Yii2)?

    @yiiworld
    В целом правильно использовать кэш методологию для хранения результатов. А конкретная реализация может быть разная.
    1) Просто и быстро: это файловый кэш, для этого в Yii2 есть компонент yii\caching\FileCache. Если у вас быстрый SSD диск будет использоваться, то этого будет достаточно для тысячи запросов на чтение в секунду. Но тут можно упереться в запись - если будет большое количество одновременных изменений в кеше (например больше нескольких десятков в секунду). При всем этом для небольших проектов файловый кеш на SSD будет в разы быстрее работать чем специализированные системы - за счет отсутствия лишних накладных расходов на функционирование самой системы кеширования.
    2) Сложно(условно), быстро, масштабируемо: это например использование Redis, для этого в Yii2 есть компонет https://github.com/yiisoft/yii2-redis. Данные хранятся в оперативной памяти поэтому ее должно быть с запасом, конкретные атомарные действия с кешем будут медленнее чем с файловым кешем на SSD, но за счет архитектуры и возможности масштабировать систему, она может выдерживать очень высокие нагрузки по чтению и записи. А также в Redis выигрыш будет когда количество самих данных начнет увеличиваться - например более миллиона записей - это произойдет за счет использования для поиска идентификаторов быстрого индекса. Интерфейсы достаточно простые, но все же нужно понимать как все устроено и потратить на это какое-то время - достаточно часто сталкиваюсь с неправильным применением Redis в проектах.

    PS
    "большим кол-вом пользователей" понятие относительное - лучше укажите возможное среднее или необходимый "потолок".
    Ответ написан
    Комментировать
  • Как увеличить время сессии в yii?

    @yiiworld
    Для Yii2 нужно добавить в конфигурацию(/config/web.php для базового приложения) значение timeout с указанным количеством секунд.
    Например на 10 лет:
    $config = [
    ...
    	'components' => [
            ...
    		'session'=>[
    	    		'timeout'=>10*365*24*60*60,
    		],
    	...
    	],
    ...
    ];
    Ответ написан
    Комментировать