• Как сортировать кастомное поле с ActiveDataProvider?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Мне кажется вам стоит лучше работать с массивом и SQL запросами по двум причинам:
    1. Вы не загадите сущности дополнительной, не нужной логикой и связями.
    2. Запросы на простых массивах выдают данные на много быстрее чем на объектах AR.

    Если же вы все таки хотите осуществить вашу затею, то идите по подходу денормализации данных. Создайте дополнительное поле-счётчик, которое будете изменять при создании и редактировании. Таким образом вывод и сортировка этого поля не будет нагружать базу, создавать кучу запросов при каждом изменении сортировочных и фильтруемых параметров, так как это будет поле вашей таблице. На которое ещё и можно повесить индекс для ускорения.
    Ответ написан
    Комментировать
  • Как лучше сделать управление GridView из админки?

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

    Отображением колонок предусмотрено свойство «visible» в GridViev. Ему нужно передавать булево значение (false, true)

    “visible” => true // или ваше условие

    [
        'label' => 'Executive Name',
        'attribute' => 'cs.first_name',
        'visible' => function ($data) {
            if ($data->hc_customersupport->is_supervisor) {
                return '1'; // or return true;
            } else {
                return '0'; // or return false;
            }
        },
    ],


    use Yii;
    
    ...
    
    'visible' => Yii::$app->user->can('supervisor'),
    Ответ написан
    3 комментария
  • Как авторизоваться на сервере API?

    myks92
    @myks92
    Нашёл решение — пометь вопрос ответом!
    Вы все правильно понимаете. Вам нужно:
    1. Авторизоваться послав логин и пароль на адрес для авторизации. Например api.site.ru/login
    2. После авторизации вы получаете токен.
    3. Формировать все запросы к api с токеном.

    На php удобнее работать с http-build-query

    Отправлять запрос можно file-get-contents

    Можете через curl

    Пример
    Ответ написан
    Комментировать
  • Как сделать пошагового телеграм бота на PHP?

    myks92
    @myks92 Куратор тега PHP
    Нашёл решение — пометь вопрос ответом!
    Если правильно понял вас, то Используйте Listeners и весь функционал обработчиках производите там. То есть бот посылает команду и event вы вешаете на это событие на свой listener. В итоге получается такая схема событие -> обработчик. Когда событие возникает тогда и работает обработчик.

    В обработчике уже помещаете логику в зависимости от переданных данных.
    Ответ написан
    4 комментария
  • Slider revolution выдает ошибку?

    myks92
    @myks92
    Нашёл решение — пометь вопрос ответом!
    Причина, по которой parsererror это сообщение parsererror заключается в том, что когда вы просто возвращаете строку или другое значение, на самом деле это не Json, поэтому синтаксический анализатор дает сбой при его анализе.

    Поэтому, если вы удалите dataType: json, оно не будет пытаться проанализировать его как Json.

    С помощью другого метода, если вы обязательно Json свои данные в виде Json, парсер будет знать, как с ним правильно обращаться.
    Ответ написан
  • Как можно получить атрибуты GridView для своего виджета?

    myks92
    @myks92 Куратор тега Yii
    Нашёл решение — пометь вопрос ответом!
    Если ваш виджет наследуется от грида, то да. Можно получить свойство атрибутов.

    Второе решение, если эти два виджета на одной странице. То можно создать переменную $attributes куда добавить общие переменные и добавить её в оба виджета.

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

    Иногда лучше сделать копипаст, чем гадать два дня на кофейной гуще откуда это взялось. Не стоит создавать себе проблем на ровном месте. Особенно если эти два виджета независимы друг от друга. Логику копипаста надо реализовывать не в этих виджетах, а во вне... Например, как написал выше. Или хелпер...

    Стоит просто посмотреть как это реализовано в Yii2. Три виджета GridView, ListView, DetalView. Эти виджеты используют одни и те же атрибуты одной модели. Но там никто так не стал делать как вы хотите.
    Ответ написан
    4 комментария
  • Как продублировать фильтр-поле в 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+>'
    ],
    Ответ написан
    Комментировать
  • Стоит ли использовать готовые плагины для комментариев на сайте ка от vk, facebook - или писать код самому?

    myks92
    @myks92
    Нашёл решение — пометь вопрос ответом!
    Смотря что вам нужно. Всё зависит от ваших задач. Как уже сказали выше. Но хочу дополнить свой ответ более развернуто:

    1. Писать самому.

    + Расширенное управление на основе ролей вашей системы или другой логики
    + Можно реализовать свою систему мотивации, например, как на тостер. С ВК тоже это можно сделать, но если вы пишите на PHP это будет сложнее. Например, у пользователя 1000 рейтинга, он лайкает комментарий пользователя с минимальным рейтингом и через логику ему присваивается повышенный рейтинг за ваш комментарий. Так как лайкнул авторитет... Ну и так далее
    + Если правильно написать пакет - его можно переиспользовать на других сайтах виджетом или пакетом подключённым через Composer
    + Можете управлять доступом написания комментария. Например, написать комментарий может только человек с ролью или заполненным профилем, либо с рейтингом не меньше.
    + Можете отправить письмо с уведомлениями об ответе
    + Можно оставлять комментарий без социальной сети (анонимно)

    - Для "расшаривания" комментария на стену пользователю ВК требуется дополнительный функционал (это больше для увеличения охвата)

    2. Взять виджет:

    + Не надо мучаться писать свой код (Решение для первого варианта: можно найти готовые пакеты на гит хаб)
    + Комментарии более реалистичнее для пользователя, так как нужно иметь профиль ВК. А ВК чаще всего реальные пользователи. Можно зайти и посмотреть профиль. (Решение для первого варианта: Реализовать свою систему профилей
    + Расшаривание комментария комментатору на стену с упоминанием вашего сайта (охват)

    - Все минусы из плюсов первого варианта.
    - Менее органично смотрится на вашем сайте (не вписывается в дизайн и вёрстку).
    - Нужно регистрироваться в социальной сети чтобы установить виджет. (для некоторых проблема) Так же нужно иметь хорошую группу. Если группа не развита - это будет бить по вашей репутации. Так как видно что она не развивается и подписчиков мало.

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

    Я больше склоняюсь к первому варианту
    Ответ написан
    2 комментария
  • Как парсить большие объёмы 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'
                    ],
                ]
            ],
    Ответ написан