Ответы пользователя по тегу Yii
  • Как настроить перенаправление в backend/web по адресу admin на хостинге?

    Часть htaccess с рабочего проекта на advanced-шаблоне, где админка лежит по адресу /admin:

    Options +SymlinksIfOwnerMatch
    IndexIgnore */*
    RewriteEngine On
    
    # Если запрос начинается с /admin, то заменяем на /backend/web/
    RewriteCond %{REQUEST_URI} ^/admin
    RewriteRule ^admin\/?(.*) /backend/web/$1
    
    RewriteCond %{REQUEST_URI} !^/(frontend/web|backend/web|admin)
    RewriteRule (.*) /frontend/web/$1
    
    # Если frontend запрос
    RewriteCond %{REQUEST_URI} ^/frontend/web
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /frontend/web/index.php
    
    # Если backend запрос
    RewriteCond %{REQUEST_URI} ^/backend/web
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /backend/web/index.php
    Ответ написан
    Комментировать
  • Как запретить вывод placeholder в yii2-images?

    Михаил Балагура, дак всё равно решение в подобных случая аналогичное, что указано по ссылке elliot ...
    Наследуемся от yii2-images, ищем место, где отдается плейсхолдер, переопределяем метод на свой.

    Если прямо совсем частный случай рассматривать, то сейчас там есть такой код:

    public function getPlaceHolder(){
            if($this->placeHolderPath){
                return new PlaceHolder();
            }else{
                return null;
            }
        }


    Т.е. если в конфиге модуля не задавать/обнулить placeHolderPath, то и вернёт null

    Если это не поможет, то совет из начала точно уже справится.
    Ответ написан
    Комментировать
  • Как добавить SPA vue в Yii2?

    Максим верно написал.
    API на Yii - отдельное приложение, SPA на vue - отдельное.
    Могут лежать как угодно, хоть на разных доменах, хоть на поддомене, хоть в субдиректории.
    Я обычно vue-app кладу в 'domain.ru/', а Yii на поддомен 'api.domain.ru'
    Ответ написан
  • Как выяснить причину расхождения по времени?

    Скорее всего такие дела: если даты выводятся через Yii::$app->formatter, то он может выводить дату через ICU.
    https://www.yiiframework.com/doc/guide/2.0/en/outp...
    You can specify date and time formats using the ICU syntax. You can also use the PHP date() syntax with a prefix php: to differentiate it from ICU syntax.


    У меня было так, что в системе стояла старая версия ICU и в ней был бардак с зимним/летним временем, как я понял. После обновления стало ок.
    В другом случае обновиться не получилось, так как не было доступа к серверу, там переписал все даты на "PHP date() syntax", он выводился правильно
    Ответ написан
  • Как сделать batchinsert yii2 с обновлением дубликатов?

    У меня так сделано в одном из проектов, наверняка можно оптимизировать, но работает

    $fullarray = [.....]; //Массив с данными
     $fields = ['product_id','name','group_id','manufacturer','fullname','code'];
           
    $db = Yii::$app->db;
    $sql = $db->queryBuilder->batchInsert(self::tableName(), $fields, $fullarray);
    $product_insert_count = $db->createCommand($sql . ' ON DUPLICATE KEY UPDATE name = VALUES(name), group_id = VALUES(group_id), manufacturer = VALUES(manufacturer), fullname = VALUES(fullname), code = VALUES(code)')->execute();
    Ответ написан
    Комментировать
  • КАк организовать панельку новичку в Yii2?

    Если без аякса (а он тут и не шибко нужен), и надо, чтобы кнопки писались один раз, то есть два очевидных варианта (и куча неочевидных):
    Вариант 1.
    Кнопки делаем любым виджетом меню, хоть стандартным, хоть своим. Или просто верстаем в основной view-шке.
    С каждой кнопки ссылаемся на один экшн контроллера, передавая get-параметр. К примеру: /site/cabinet?page=status
    В actionCabinet контроллера возвращаем view-шку cabinet, и также передаем в неё параметр page.
    Внутри view-шки cabinet сначала выводим общее меню, потом смотрим, какой параметр получен и в зависимости от него рендерим дочерний view, соответствующий нужному разделу.
    Вариант 2.
    Кнопки делаем своим виджетом, можно унаследовать от стандратных, чтобы назначить в нём ссылки.
    Ссылаемся в меню на разные экшены/контроллеры.В каждом view экшена добавляем виджет с кнопками. Если надо поменять все кнопки - меняем виджет.
    Ответ написан
    3 комментария
  • Как вывести в виджете элементы неограниченного уровня вложенности?

    В целом задача с неограниченно вложенностью решается рекурсией.

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

    class NavWidget extends Widget
    {
    
        public $items = [];
    
        /**
         * Renders the menu.
         */
        public function run()
        {
            $items = $this->items;
            if (!empty($items)) {
                echo Html::tag('ul', $this->renderItems($items));
            }
        }
    
    
        protected function renderItems($items)
        {
            $lines = [];
            foreach ($items as $item) {
                $menu = $this->renderItem($item);
                if (!empty($item['items'])) {
                    $menu .= Html::tag('ul', $this->renderItems($item['items']));
                }
                $lines[] = Html::tag('li', $menu);
            }
            return implode("\n", $lines);
        }
    
    
        protected function renderItem($item)
        {
            $link = 'Тут собранная ссылка';
            return $link;
        }
    }


    P.S. А вообще, всё отлично видно и понятно в стандартных виджетах типа yii\widgets\Menu и в данном случае он всё это сделает прекрасно. Если что-то надо изменить, можно от него унаследоваться.
    Ответ написан
    Комментировать
  • Yii2 - массовая загрузка / выгрузка / обновление в БД?

    Все пишут про то, как распарсить xls, только вот самое узкое место в процессе совсем не в том месте.

    Проблемы начинаются, когда надо с помощью activeRecord просохранять несколько тысяч моделей. Если делать это в цикле, как предлагают выше, то в один прекрасный момент сервер вам скажет пару ласковых и скинет операцию либо по таймауту, либо по памяти, даже если лимиты задрать.

    Я использую два принципиально разных варианта:
    1) В операции импорта генерировать массив с полями модели и отдавать его в SQL-запрос, в обход activeRecord.
    Просто вставляем в базу кучу записей, при повторе ключа - обновляем. Он довольно быстрый, но мне не нравится, так как не очень удобно работать со сложными структурами. Ну и теряем при этом такие вещи, как обработку behaviors, валидацию полей из rules модели, события и т.д. Конечно, если все это очень надо, то это можно вручную вызвать, но тогда и смысла в варианте не много остается.

    $db = Yii::$app->db;
    $sql = $db->queryBuilder->batchInsert(self::tableName(), $fields, $fullarray);
     $product_insert_count = $db->createCommand($sql . ' ON DUPLICATE KEY UPDATE name = VALUES(name), group_id = VALUES(group_id), manufacturer = VALUES(manufacturer), fullname = VALUES(fullname), code = VALUES(code)')->execute(); //Возвращает количество вставленных записей


    2) Очереди. Сейчас в основном этим вариантом пользуюсь.
    https://github.com/yiisoft/yii2-queue
    Парсим файл, для обработки каждого товара создаем задание, в котором проводим все нужные операции (проверку на необходимость обновления, обновление или создание новой модели и т.д.) и добавляем это задание в очередь. После формирования очереди консольной командой запускаю выполнение очереди.
    Ответ написан
    Комментировать
  • Как сделать динамическую подгрузку данных при выборе пункта из выпадающего списка формы в Yii2?

    Можно сделать GET-запросом, но учитывая activeForm, мне ближе делать это через POST
    Форма
    <?php $form = ActiveForm::begin([
        'id' => 'get_users', //Добавляем ID для отслеживания в JS
        'action' => \yii\helpers\Url::to(['ВАШ ЭКШН']) //Добавляем адрес, к которому пойдет запрос, если он отличается от текущего местоположения
    ]); ?> 
    <?= $form->field($model, 'field1')->dropDownList(\yii\helpers\ArrayHelper::map(User::find()->all(), 'id', 'username')); ?> 
    <?= Html::submitButton('Пробуем', ['class' => 'btn btn-info', 'id'=>'get_users_submit']); ?>
    <?php ActiveForm::end(); ?>
    <div id="rendered_user"></div>


    Контроллер
    public function actionYouraction()
        {
            $request = Yii::$app->request;
            if($request->isAjax){ 
                Yii::$app->response->format = Response::FORMAT_JSON; //Если запрос аяксовый,то отвечаем JSON-ом
                //Тут разбираете полученный запрос, пишете нужную логику, подтягиваете модель пользователя
               
               return ['content'=>$this->renderAjax('_userdata', [ 'model' => $model])];   //Возвращаем JSON-массив в виде вьюшки, которой передаем модель пользователя или любые другие нужные данные
            }   
        }


    JS
    $(document).on('click' , '#get_users_submit' , function(e) {
        e.preventDefault();
        var target= $('#rendered_user'), //В этот блок выводим полученные данные 
              form = $('#get_users'), //Выбираем нашу форму
              url = form.attr('action'), //Узнаем url для отправки
              data =  form.serializeArray(); //Сериализуем форму
        $.ajax({
                url: url,
                method: 'POST',
                data: data,
                error: function (response) {
                    //Если ошибка запроса, то что-то делаем
                },
                success: function (response) {
                    //Если запрос прошел, то что-то делаем
                   //Контроллер вернет данные в переменную response, разберите её, выведите что нужно
                   console.log(response);
                   target.html(response.content);
                },
            });
    
    });


    Всё по памяти, код не проверял.
    Суть вроде должна быть ясна.
    Ответ написан
    1 комментарий