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

    DieZz
    @DieZz
    Как мне видится - самый логичный вариант сделать отдельный класс, который будет возвращать имя статуса. Это может быть хелпер, компонент и все что угодно, в зависимости от специфики вашей бизнес логики. Например
    interface HasStatus
    {
        public const STATUS_NOT_PAID = 0;
        public const STATUS_PAID     = 1;
        public const STATUS_CANCEL   = 3;
    
        public function getStatus(): int;
    }
    
    class StatusHelper
    {
        /**
         * Статистический метод получения списка статусов
         *
         * @return array
         */
        public static function getStatusList()
        {
            return [
                HasStatus::STATUS_NOT_PAID => 'Не оплачено',
                HasStatus::STATUS_PAID     => 'Оплачено',
                HasStatus::STATUS_CANCEL   => 'Отменена',
            ];
        }
    
        public function getStatusName(HasStatus $entity): string
        {
            ArrayHelper::getValue(self::getStatusList(), $entity->getStatus());
        }
    }

    Соответственно все ваши модельки должны имплементирвать интерфейс HasStatus. Таким образом вся бизнес логика находится в одном месте и отвязана от БД
    Ответ написан
    1 комментарий
  • Как подключить Adldap2 в Yii2?

    DieZz
    @DieZz
    Если вопрос еще актуален, могу поделится своей реализацией
    В первую очередь я создал компонент который является обореткой для Adldap
    spoiler
    <?php
    
    namespace app\components;
    
    use Adldap\Adldap;
    use Adldap\Auth\BindException;
    use Adldap\Auth\PasswordRequiredException;
    use Adldap\Auth\UsernameRequiredException;
    use Adldap\Connections\ProviderInterface;
    use Adldap\Models\Group;
    use Adldap\Models\Model;
    use Adldap\Models\User;
    use app\components\interfaces\ExternalAuthProviderInterface;
    use Illuminate\Support\Collection;
    use yii\base\Component;
    
    /**
     * Class LdapService
     * Wrapper to work with LDAP package.
     *
     * @package app\components
     */
    class LdapService extends Component implements ExternalAuthProviderInterface
    {
        /**
         * Account suffix.
         *
         * @var string
         */
        public $accountSuffix = '';
        /**
         * List of domain controllers.
         *
         * @var array
         */
        public $domainControllers = [];
        /**
         * Base DN.
         *
         * @var string
         */
        public $baseDn;
        /**
         * Domain admin user name.
         *
         * @var string
         */
        public $adminUserName;
        /**
         * Domain admin password.
         *
         * @var string
         */
        public $adminPassword;
        /**
         * Connection provider to the AD.
         *
         * @var ProviderInterface
         */
        private $provider;
    
        /**
         * Attempt to login in domain.
         *
         * @param string $login    login.
         * @param string $password password.
         *
         * @throws BindException if there are connections errors.
         * @throws PasswordRequiredException
         * @throws UsernameRequiredException
         *
         * @return bool
         */
        public function attempt(string $login, string $password): bool
        {
            return $this->getProvider()
                ->auth()
                ->attempt($login, $password);
        }
    
        /**
         * Find user in the AD by login(account name).
         *
         * @param string $login login/account name.
         *
         * @throws \Adldap\Models\ModelNotFoundException
         * @throws BindException
         * @throws \InvalidArgumentException
         * @return User|Model
         */
        public function findUserByLogin(string $login): User
        {
            return $this->getProvider()
                ->search()
                ->users()
                ->where('samaccountname', '=', $login)
                ->firstOrFail();
        }
    
        /**
         * Find user in the AD by full name.
         *
         * @param string $username users full name.
         *
         * @throws \Adldap\Models\ModelNotFoundException
         * @throws BindException
         * @throws \InvalidArgumentException
         * @return User|Model
         */
        public function findUserByFullName(string $username): User
        {
            return $this->getProvider()
                ->search()
                ->users()
                ->where('cn', '=', $username)
                ->firstOrFail();
        }
    
        /**
         * Returns list of all group in the AD.
         *
         * @throws BindException
         * @return Collection|Group[]
         */
        public function getAllGroups(): Collection
        {
            return $this->getProvider()
                ->search()
                ->groups()
                ->get();
        }
    
        /**
         * Returns configured AD provider.
         *
         * @throws BindException
         * @return ProviderInterface
         */
        private function getProvider(): ProviderInterface
        {
            if (null === $this->provider) {
                $ad = new Adldap($this->getConfig());
                $this->provider = $ad->connect('default');
            }
    
            return $this->provider;
        }
    
        /**
         * Returns config to connect to the ldap domain.
         *
         * @return array
         */
        private function getConfig(): array
        {
            return [
                'default' => [
                    'domain_controllers' => $this->domainControllers,
                    'base_dn'            => $this->baseDn,
                    'admin_username'     => $this->adminUserName,
                    'admin_password'     => $this->adminPassword,
                    'account_suffix'     => $this->accountSuffix,
                ],
            ];
        }
    }



    Теперь этот компонент необходимо подключить через конфиг приложения
    spoiler
    'components' => [
            ...
            'ldap' => [
                'class'             => \app\components\LdapService::class,
                'accountSuffix'     => '@test',
                'domainControllers' => ['192.168.1.1'],
                'baseDn'            => 'DC=admin',
                'adminUserName'     => 'admin',
                'adminPassword'     => 'password',
            ],
        ],



    И далее уже можем использовать его в нашем коде
    $user = \Yii::$app->get('ldap')->findUserByLogin('someLogin');
    Ответ написан
    Комментировать
  • YII2 добавить товар в разные категории?

    DieZz
    @DieZz
    Yii2 это не движок, а фреймворк. Касательно вашего вопроса - проблема тут не уровня фреймворка, а уровня проектирования БД. Тут достаточно создать три таблицы
    products
    ----------
    id
    name
    ...
    
    categories
    ------------
    id
    name
    ...
    
    products_categories
    ------------------------
    product_id
    category_id

    В этом случае каждый товар можно связать с большим числом категорий. Прочитайте про связи "многие ко многим"
    Ответ написан
    1 комментарий
  • After downloading the file from the repository, an error occurred. How i can solve this problem?

    DieZz
    @DieZz
    You might need to run composer install first
    Ответ написан
    Комментировать
  • Условие для Assets в Yii2?

    DieZz
    @DieZz
    Используйте AssetBundle и метод init() в нем, например:
    <?php
    
    namespace app\assets;
    
    use yii\web\AssetBundle;
    
    class AppAsset extends AssetBundle
    {
        public function init()
        {
            $format = 'theme/assets/global/plugins/date/locales/dater.%s.min.js';
            $this->js[] = sprintf($format, \Yii::$app->language);
        }
    }
    Ответ написан
    Комментировать
  • Как реализовать middleware-like логику в Yii2?

    DieZz
    @DieZz
    Используйте поведения (behaviors). Например в Yii из коробки есть такая штука:
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => HttpBearerAuth::className(),
        ];
        
        return $behaviors;
    }


    Если хотите свою логику для проверки токена, то создайте класс который будет имлпементировать интерфейс yii\filters\auth\AuthInterface у указывайте его в поведении. В случае ошибки авторизации бросайте UnauthorizedHttpException
    Ответ написан
    6 комментариев
  • Как проверить соответствие экземпляра ActiveRecord определенному интерфейсу?

    DieZz
    @DieZz
    Используйте интерфейс для типизации модели и используйте явное указание типа аргумента в нужном методе. Например:
    <?php
    
    interface UserInterface
    {
        public function getFirstName();
    
        public function getLastName();
    
        public function getLogin();
    }
    
    /**
     * Class User
     *
     * @property string $firstName
     * @property string $lastName
     * @property string $login
     */
    class User extends \yii\db\ActiveRecord implements UserInterface
    {
        ...
    
        public function getFirstName()
        {
            return $this->firstName;
        }
    
        public function getLastName()
        {
            return $this->lastName;
        }
    
        public function getLogin()
        {
            return $this->login;
        }
    
    }
    
    class TestController
    {
        /**
         * Здесь явно указываем тип переменной, которую ожидаем. Если мы передадим
         * объект, который не имплиментирует нужный интерфейс, то будет ошибка.
         *
         * @param UserInterface $user
         */
        public function actionTest(UserInterface $user)
        {
            $name = $user->getFirstName();
            ...
        }
    }
    Ответ написан
    Комментировать
  • Как в Yii2 ActiveForm сделать AJAX отправку и обработку данных?

    DieZz
    @DieZz
    Примерно так:
    $form = ActiveForm::begin([
        'id' => 'form-input-example',
        'options' => [
           'onsubmit' => 'sendAjax(this, myAction)'
        ],
    ]);
    ...

    Метод sendAjax:
    var myAction = function (response) {
        //Делаем то, что нам нужно с ответом
        console.log(response);
    }
    
    function sendAjax(form, callback) {
        $.ajax({
            method: 'post',
            url: '/test',
            dataType: 'json',
            data: $(form).serialize()
        }).done(function (response) {
            callback(response);
        })
    
       //Возвращаем false чтобы форма не отправилась
       return false;
    }

    Код не проверял, но теоретически должно работать.
    Ответ написан
    Комментировать
  • Можно ли запскать веб контроллер yii2, как cron задачу?

    DieZz
    @DieZz
    Используйте консольное приложение
    Ответ написан
    Комментировать
  • Есть ли возможность отключить exception?

    DieZz
    @DieZz
    Зачем отключать исключения? Они как раз говорят, что что-то идет не так. Научитесь использовать их правильно и программировать станет проще
    try {
        //Тут что то делаем с сокетом
        fsockopen();
    } catch (ErrorException $e) {
        //Что то пошло не так - обработаем исключение, например, так:
       echo $e->getMessage();
    }

    Тогда выполнение кода не прервется, и мы будем знать что произошло и как это обрабатывать.
    Ответ написан
  • Как мне заставить работать контроллер во вложенной папке вида?

    DieZz
    @DieZz
    А зачем контроллер в папке с видами?
    По идее структура должна быть такой:
    -modules/
    --pages/
    ---controllers/
    ----AdminController.php
    ----AnotherController.php
    ---config/
    ----Config.php
    ---views/
    ----аdmin/
    -----index.php

    Код файла Config.php
    <?php
    
    namespace app\modules\pages\config
    
    class Config 
    {
        ...
    }

    Ну если уж неимоверно хочется положить в директорию с видами то пропишите неймспейс app\modules\pages\views\admin\config
    Ответ написан
    Комментировать