Ответы пользователя по тегу Yii
  • Как продублировать фильтр-поле в footer GridView Yii2?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    1. Наследовать виджет и переписать логику отображения фильтра.
    2. Использовать генерируемый Yii файл поисковой формы «_search.php». Из Грида убираете поисковую модель и подключаете сверху и снизу форму поиска.

    Я бы лучше пошёл вторым вариантом. Так как это проще и гибче.
    Ответ написан
    2 комментария
  • Как настроить маршрутизацию Yii2 restApi?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Запрос не правильный, как я понял. Судя по вашим правилам
    'GET {id}' => 'api/get'
    Запрос должен быть такой: api/get?id=3. И, возможно, что лишний слэш
    'tokens' => [
         '{id}' => '<id:\w+>'
    ],
    Ответ написан
    Комментировать
  • Как парсить большие объёмы Yii2?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    1. Использовать консольные контроллеры вместо web и установить периодичность его работы.

    2. Использовать очереди. Кидаете задачу в очередь. Консольная команда проходит по всем очередям и выполняет задачу. Схоже с первым вариантом.

    3. Самый не актуальный, но действенный в вашей ситуации - использовать для запросов не объекты и Active Query, а «голые» SQL запросы которые выдают данные в массиве. AR потребляет не мало памяти на объекты. На какое то время вас это спасёт. Но лучше использовать консольные команды. Это больше подходит для подобный задач.

    4. Подготавливать денормализованные данные для быстрого запроса в отдельную таблицу СУБД или использовать быстрые NOSQL базы данных. И уже из них считывать ваши данные.
    Ответ написан
    1 комментарий
  • Yii2. Как реализовать реферальную систему?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    А если вы забудете где-то наследоваться от этого контроллера? Можно вам решить и без наследования от основного контроллера. Вешайте обработчик на всё приложение используя before или after:

    'as beforeAction' => function () {
    //Тут ваши действия для анонимной функции
    }


    Если логики много используйте отдельный класс, например, поведения. Но поведения уберут в Yii3. Думайте об этом тоже)
    'as beforeAction' => [
            'class' => app\modules\users\behaviors\LastVisitBehavior::class
        ],

    Очищать URL от нужного параметра можно с
    Url::current(['ref' => null]);

    PS Мне кажется, что не надо делать реферальную ссылку на все экшены. Врядли пользователь будет менять ссылку. Да и зачем вам это учитывать. Дают рабочую ссылку на регистрацию. Там вы ищите нужный параметр. Запоминаете его и уже при регистрации всегда подставляете если есть. Но зачем вам рефералка в новостях, статьях и так далее. Не пойму целесообразность решения)

    Обычно делают как то так:
    /**
         * Страница сохранения реферера (пригласившего)
         *
         * @param int $id
         *
         * @return Response|string
         */
        public function actionReferral(int $id)
        {
            if (Yii::$app->user->isGuest) {
                ReferralHelper::setReferrerId($id);
            }
            return $this->redirect('site/registration');
        }


    /**
         * Страница регистрации
         *
         * @return Response|string
         * @throws \yii\base\InvalidArgumentException
         * @throws \yii\db\Exception
         */
        public function actionRegistration()
        {
            if (!Yii::$app->user->isGuest) {
                return $this->goHome();
            }
            $userForm = new UserForm();
            if ($userForm->load(Yii::$app->request->post())) {
                $referrerId = ReferralHelper::getReferrerId();
                $referrer = $referrerId !== null ? $this->getUser((int)$referrerId) : null;
                $userForm->setReferrer($referrer);
                if ($userForm->save() && $userForm->login()) {
                    $message = 'Спасибо за регистрацию.';
                    if ($referrer !== null) {
                        $message .= ' Вас пригласил ' . $referrer;
                    }
                    Yii::$app->session->setFlash('success', $message);
                    ReferralHelper::removeReferrer();
                    return $this->goHome();
                }
                $this->addErrorForForm($userForm);
            }
            $userForm->password = '';
            return $this->render('registration', [
                'model' => $userForm,
            ]);
        }


    class ReferralHelper
    {
        const KEY_REFERRER_ID = 'referrer_id';
        public static function setReferrerId(int $referrerId)
        {
            \Yii::$app->getSession()->set(self::KEY_REFERRER_ID, $referrerId);
        }
        public static function getReferrerId()
        {
            return \Yii::$app->getSession()->get(self::KEY_REFERRER_ID, null);
        }
        public static function removeReferrer()
        {
            return \Yii::$app->getSession()->remove(self::KEY_REFERRER_ID);
        }
    }


    Взял из готового решения на Yii2. Код не совсем хороший, но рабочий.
    Ответ написан
    1 комментарий
  • Как правильно вызвать виджет со следующими данными в yupe?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    <?= $this->widget('application.modules.user.widgets.UsersList', array(
        'condition' => array(
            'limit' => 2,
            'together' => true,
            'group' => 't.id',
            'condition' => 'categories.id=":cid"',
            'params' => [':cid' => $cid]
        ),
        'type' =>'contest',
        'view' => 'contest'
    )); ?>
    Ответ написан
    Комментировать
  • Как провести сохранение связанных моделей?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    link Если этого достаточно.

    Но если вам нужно более широкое решение установите хорошее расширение: https://github.com/la-haute-societe/yii2-save-rela...
    Ответ написан
    2 комментария
  • Как правильно реализовать передачу данных в gridview yii2?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    'attributes' => array_map(function (Value $value) {
        return [
            'label' => $value->characteristic->name,
            'value' => $value->value,
        ];
    }, $product->values),
    Ответ написан
  • Архитектура приложения. Как сделать независимые модули (сервисы)?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    По этому вопросу очень долго искал ответа))
    Вам уже скинули статью по независимым модулям, но этого мало. Что вам нужно:

    1. Независимый слой MODEL.
    В этой папке находятся Use Case (Service), Сама сущность Entity (AR), Желательно иметь репозитории для изоляции от базы данных ну и другой доменный слой логики, который не зависит ни от чего. Ни от фреймворка, ни от других модулей и пакетов. Ваша задача написать код в этой части так, чтобы его можно было скопировать в любую папку, настроить зависимости и чтобы этот код заработал хоть на чистом PHP. Если не планируете менять фреймворк, то можно зависить от фреймворка.

    2. Зависимости
    Все зависимости модуля реализовать либо через Interface либо через события, но события лучше. А дальше уже синхронизируйте через приложение или отдельный модуль. Можно и по api.

    3. UI (пользовательский интерфейс)
    Он может быть зависимым от других модулей. В него входят: контроллеры, view, формы, vue.js и так далее. В общем то, с чем взаимодействует пользователь.

    Тем самым получается такая система если опираться на MVC:
    VC - могут быть зависимы от других модулей
    M - не может быть зависима ни от чего, кроме PHP. Желательно и отделять слой базы данных с помощью Repository. Тогда ваш пакет будет очень сильно независим даже от базы. И вам вообще будет без разницы куда вы это храните в user или employee.

    Если будет такой слой, то можно спокойно переносить хоть на будущий Yii3. Однако На Yii1 и Yii2 такое сделать сложно. Надо изворачиваться и займет это больше времени. Так как сам Фреймворк вставляет нам палки и приходится делать костыли из-за его монолитности. К такому подходу не привыкли Yii1 и Yii2 разработчики. Обычно на Yii такое понимание «фигак, фигак и в продакшн».

    Такую архитектуру удобно будет строить на Symfony ну и будущем Yii3.

    Рекомендую к прочтению:
    Ответ написан
    7 комментариев
  • Отправляет ли Yii2 запрос в БД при использовании такой строки?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Идёт. Посмотрите в debug панели
    Ответ написан
    Комментировать
  • Почему может возникать эта ошибка? Как запустить удаленное приложении yii локально?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Проблема с видами может быть по нескольким случаям:
    1. Неправильно указан путь рендеринга. Если вы перенесли только папки, то ещё нужно настроить и viewPath
    2. Если вы настроили viewPath и все равно проблемы остались - проблема в правильности пути. Либо указали не полный путь, либо не соблюли регистр букв.

    Скорее всего первый путь.

    Свой путь. Настройки приложения могут выглядеть так:
    return [
        'viewPath' => '@app/modules/users/views/frontend',
    ];


    Темеризация
    return [
        'components' => [
            'view' => [
                'theme' => [
                    'basePath' => '@app/themes/basic',
                    'baseUrl' => '@web/themes/basic',
                    'pathMap' => [
                        '@app/views' => '@app/themes/basic',
                    ],
                ],
            ],
        ],
    ];


    Настройка модуля:
    return [
    'modules' => [
            'users' => [
                'class' => app\modules\users\Module::class,
                'controllerNamespace' => 'app\modules\users\controllers\frontend',
                'viewPath' => '@app/modules/users/views/frontend',
                'layout' => '@app/views/layouts/column2-right.php',
            ],
    ]
    Ответ написан
    9 комментариев
  • Как сделать api yii2 basic?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Ничего сложного Нет! Создаёте модуль api и подключаете его:

    'modules' => [
            'api' => [
                'class' => app\modules\api\Module::class,
                'modules' => [
                    'v1' => [
                        'class' => app\modules\api\modules\v1\Module::class,
                        'controllerMap' => [
                            'organizations' => \app\modules\organizations\api\controllers\DefaultController::class,
                            'users' => \app\modules\users\api\Controllers\DefaultController::class,
                            'cities' => \app\modules\api\modules\v1\controllers\events\CitiesController::class,
                        ],
                    ]
                ],
            ],
        ],


    2. Создаёте Контроллер наследуемый от ActiveController
    class DefaultController extends ActiveController
    {
        public $modelClass = Organization::class;
        public $serializer = [
            'class' => 'yii\rest\Serializer',
            'collectionEnvelope' => 'items',
        ];
    
        public function behaviors()
        {
            $behaviors = parent::behaviors();
            $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
            return $behaviors;
        }
    
        public function actions()
        {
            $actions = parent::actions();
            unset($actions['delete'], $actions['create'], $actions['view']);
            return $actions;
        }
    }


    3. Настраиваете роуты например так:
    [
                        'class' => 'yii\rest\UrlRule',
                        'controller' => ['api/v1/organizations'],
                        'extraPatterns' => [
                            'GET, POST find' => 'find',
                        ],
                    ],


    4. В конфигах api примерно такое
    'components' => [
            'response' => [
                // ...
                'formatters' => [
                    \yii\web\Response::FORMAT_JSON => [
                        'class' => yii\web\JsonResponseFormatter::class,
                        'prettyPrint' => YII_DEBUG, // используем "pretty" в режиме отладки
                        'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
                    ],
                ],
            ],
            'as contentNegotiator' => [
                'class' => \yii\filters\ContentNegotiator::class,
                'formatParam' => '_format',
                'formats' => [
                    'application/json' => \yii\web\Response::FORMAT_JSON,
                    'application/octet-stream' => \yii\web\Response::FORMAT_JSON,
                    'text/html' => \yii\web\Response::FORMAT_JSON,
                    'application/xml' => \yii\web\Response::FORMAT_XML,
                ],
            ],
        ],
    Ответ написан
  • Почему выходит ошибка 404 при попытке загрузки картинки с помощью плагина elfinder?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Вы неправильно сделали настройки) Это же очевидно. Класс контроллера поместили выше action в controllerMap

    'controllerMap' => [
                'elfinder' => [
                'class' => 'mihaildev\elfinder\PathController', /////ВОТ ЗДЕСЬ ДОЛЖНО БЫТЬ!
                    'access' => ['@'],
                    'root' => [
                        'baseUrl'=>'/web',
    //                'basePath'=>'@webroot',
                        'path' => 'upload/global',
                        'name' => 'Global'
                    ],
                ]
            ],
    Ответ написан
  • Как отсортировать выборку по статусам?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Сортировка настраивается посредством свойства sort дата провайдера
    $dataProvider = new ActiveDataProvider([
         'query' => $query,
         'sort'=> [
         'attributes' => [
                'age',
                'name' => [
                    'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
                    'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
                    'default' => SORT_DESC,
                    'label' => 'Name',
                ],
            ],
     ]);


    Заполните массив attributes параметрами по которым вам необходимо сортировать, и далее передавайте данные параметры через get строку запроса в виде ...?sort=-name
    Ответ написан
    4 комментария
  • Как в gridview yii2 вывести вместо иконок glyphicon fontawesome?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Вариантов тут несколько:

    1. Создать свой класс ActionColumn и наследовать его от базового ActionColumn. В этом классе переопределить нужную реализацию. Как советует Дмитрий Дерепко

    2. Замена в одном месте. Если требуется заменить только в одном месте имеет смысл использовать решение Дмитрий

    3. Сочетать всё это используя DI контейнер. Всегда рекомендую использовать такую глобальную подмену данных. Это более гибко. Для этого создаем Bootstrap класс с реализацией интерфейса \yii\base\BootstrapInterface. Подключаем его в автозагрузку приложения (bootstrap в config.php) и заменяем всё что нам нужно:
    $actionColumnSetting = [
                'buttons' => [
                    'view' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-eye" aria-hidden="true"></i>', ['update']);
                    },
                    'update' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-pencil-alt" aria-hidden="true"></i>', ['update']);
                    },
                    'delete' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-trash" aria-hidden="true"></i>', ['delete']);
                    }
                ],
            ];
            \Yii::$container->set(ActionColumn::class, $actionColumnSetting);


    Это удобно во всех случаях. Например, вы вдруг захотите во всех gridview использовать другие экшены редактирования. Заменить это будет просто. Необходимо update переименовать в edit. Либо вам во всех gridview нужна дополнительная кнопка "перенести Архив"

    $actionColumnSetting = [
                'buttons' => [
                    'view' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-eye" aria-hidden="true"></i>', ['edit']);
                    },
                    'update' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-pencil-alt" aria-hidden="true"></i>', ['update']);
                    },
                    'delete' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-trash" aria-hidden="true"></i>', ['delete']);
                    },
      'archive' => function($name, $model, $key){
                        return Html::a('<i class="fas fa-trash" aria-hidden="true"></i>', ['archive']);
                    }
                ],
            ];
            \Yii::$container->set(ActionColumn::class, $actionColumnSetting);

    Ответ написан
    Комментировать
  • Как произвести правильный подсчет в тесте?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Такой код, где много if, else тестировать очень сложно и это сложно читаемо. Вынесите весь код логики в отдельные классы, с методами и тестируйте их. Например класс может быть класс QuestionPoint . В нем методы
    public function isAnswerExists($answers){}

    и тому подобные..

    Получится такой код, если совсем примитивно

    $question = 1;
    foreach ($questions as $key => $question) {
    $questionPoint = new  QuestionPoint($question);
    $questionPoint->isAnswerExists($question, $answer)
    }


    Поэтому делайте код по ООП или DDD и тогда будет вам счастье. В вашем случае будет гемор. Особенно если код в контроллере. Тестировать его будет крайне сложно и долго. Такие тесты запускать никому не захочется. Вам придется в тестах поднимать приложение и базу данных. Хотя в вашем случае это вообще лишнее!

    В общем выносите код из контроллера и избавляйтесь от лапши. Создавайте объекты.
    Ответ написан
    2 комментария
  • Как сделать импорт csv файлов в таблицу/БД?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Пишет, что директория не найдена. У вас путь к папке не полный. Вы указываете /загрузки....
    Начинаете искать от корня. Не уверен я в том, что загрузки у вас находятся в корне. Скорее всего они в папке web. Ваш путь должен быть полным от корня к этой папке. Либо используете Алиал web. @web/загрузки/....
    Ответ написан
  • Как сверстать формы в yii?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Я думаю, что вам поможет эта статья https://yiico.ru/blog/499-shpargalka-po-formam-act...

    Вам нужно смотреть в сторону параметра “template”. Думаю, что это поможет

    <?php $form = ActiveForm::begin([
            'layout'=>'horizontal',
            'options' => ['class' => 'signup-form form-register1'],
            'fieldConfig' => [
                 'template' => "{label}\n{beginWrapper}\n{input}\n{hint}\n{error}\n{endWrapper}",
                'horizontalCssClasses' => [
                    'label' => 'col-sm-4',
                    'offset' => 'col-sm-offset-4',
                    'wrapper' => 'col-sm-8',
                    'error' => '',
                    'hint' => '',
                ],
            ],
        ]); ?>


    Или так
    <?= Html::activeLabel($model, 'password') ?>
    <?= Html::activePasswordInput($model, 'password') ?>
    <?= Html::error($model, 'password') ?>
    
    or
    
    <?= Html::activeLabel($model, 'username', ['label' => 'name']) ?>
    <?= Html::activeTextInput($model, 'username') ?>
    <div class="hint-block">Please enter your name</div>
    <?= Html::error($model, 'username') ?>
    Ответ написан
    Комментировать
  • Как добавить кнопку import в DynaGrid?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Судя по документации это так:
    'gridOptions'=>[
            'dataProvider'=>$dataProvider,
            'filterModel'=>$searchModel,
            'showPageSummary'=>true,
            'panel'=>[
                'heading'=>'<h3 class="panel-title"><i class="glyphicon glyphicon-book">  Library',
                'before'=>'{dynagrid}' . Html::a('Custom Button', '#', ['class'=>'btn btn-default'])
            ],
        ]
    Ответ написан
  • Как можно повторно инициализировать select 2 kartik?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Вопрос не по тематике Yii2 это относится к JS и самому Select2 копайте в эту сторону. И предлагаю такой JS. Попробуйте, возможно подойдет...

    /*<!--Устраняем баг Select2-->*/
    $(document).ready(function () {
        $.fn.modal.Constructor.prototype.enforceFocus = function () {
        };
    });
    /*<!--/Устраняем баг Select2-->*/

    $(".select2me-filter").select2("destroy");
    
    ... Here do option updates you need
    
    $(".select2me-filter").select2();
    Ответ написан
    Комментировать
  • Как заменить GridView на DynaGrid?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    1. Добавьте в кофигурацию DynaGrid как модуль
    'modules'=>[
       'dynagrid'=> [
            'class'=>'\kartik\dynagrid\Module',
            // other module settings
        ],
        'gridview'=> [
            'class'=>'\kartik\grid\Module',
            // other module settings
        ],
    ];


    2. Используйте в своем приложении
    <?= \kartik\dynagrid\DynaGrid::widget([
        'columns' => $columns,
        'theme'=>'panel-warning',
        'gridOptions'=>[
            'dataProvider'=>$dataProvider,
            'filterModel'=>$searchModel,
            'showPageSummary'=>true,
            'panel'=>[
                'heading'=>'<h3 class="panel-title"><i class="glyphicon glyphicon-book">  Library',
                'before'=>'{dynagrid}' . Html::a('Custom Button', '#', ['class'=>'btn btn-secondary'])
            ],
        ]
    ]); ?>
    Ответ написан