Ответы пользователя по тегу Yii
  • Как внедрить Vue в существующий Yii-проект?

    copist
    @copist
    Empower people to give
    Комментировать
  • Как внедрять vue в проект на Yii2?

    copist
    @copist
    Empower people to give
    Ты сборку на базе webpack используешь?

    В Yii2 надо будет сделать два layout: один для обычных страниц (view/layouts/main.php), второй для страниц с Vue (view/layouts/vue.php)

    Для режима dev в файле view/layouts/vue.php нужно подключать JS скрипты, которые генерит npm start. Для этого открой исходный код страницы, которую раздаёт webpack и скопируй оттуда все подключенные <script>. Либо вручную, либо парсер напиши. Вроде бы у этих скриптов статичные имена, поэтому тут проще. Можно один раз скопировать и забыть.

    Для режима prod нужно в лэйауте view/layouts/vue.php подключать финальные сжатые JS скрипты, которые генерит npm run build - тут сложность в том, что эти скрипты с уникальными именами всегда.

    Попробую сделать пример на github
    Ответ написан
    5 комментариев
  • Получение данных из БД на Yii2. Как это сделать?

    copist
    @copist
    Empower people to give
    Судя по всему это не таблица, а вычислимая функция, возвращающая датасет.
    Не используй ActiveRecord для работы с этим записями, формируй SQL запросы вручную.
    Ответ написан
    Комментировать
  • Почему не устанавливается расширение на yii2 через composer?

    copist
    @copist
    Empower people to give
    Светлана Галенко, у вас в файле composer.json
    "minimum-stability": "stable"


    В репозитории пакетов указано
    https://packagist.org/packages/2amigos/translitera...

    If you are looking for Yii 2.* version please check its own repository https://github.com/2amigos/yii2-transliterator-helper


    Стало быть у вас устанавливается какая-то нестабильная или несовместимая версия.
    Попробуйте поставить пакет из репозитория как описано тут https://getcomposer.org/doc/05-repositories.md#loa... и тут www.andrew-kirkpatrick.com/2012/10/add-a-git-repos...
    Ответ написан
  • Как вы поддерживаете фикстуры актуальными?

    copist
    @copist
    Empower people to give
    Писать в массивы файлами (как рекомендует Yii) - пробывали - сложно держать актуальными - у нас в неделю по 5-10 миграций, структура довольно активно меняется + сами объекты сложные, некоторые агрегаты раскиданы по 10и таблицам.

    Конечно сложно. А откуда появляется метрика "Код с тестами писать в три раза медленнее"
    Код поддерживать, тесты поддерживать, фикстуры поддерживать.
    Ответ написан
    3 комментария
  • Как сделать большое количество запросов?

    copist
    @copist
    Empower people to give
    Мне кажется, 2 250 000 HTTP запросов - это очень нехорошая архитектура. Мало того что сервер опухнет, так и клиент не дождётся. Один запрос предположим 3ms (очень оптимистично, прям идеально), тогда всё вместе будет 6750s или 112 минут. Два часа непрерывной долбёжки по API без таймаутов.

    Предлагаю перенести логику либо в клиентское приложение (кто хочет сделать 2М запросов) либо в серверное (которое должно вернуть 2М запросов).

    Либо пусть клиент получает сразу 1500 записей целиком или порциями и самостоятельно анализирует.
    Либо пусть сервер подготавливает данные в нужном виде.

    Если считаете, что не барское это дело серверу делать бизнес-аналитику, то разработайте промежуточный микросервис, который получит 1500 записей из исходного сервиса и подготовит выгрузку в нужном формате для клиента. Три звена.
    Ответ написан
    2 комментария
  • За сколько реально освоить Yii?

    copist
    @copist
    Empower people to give
    Я изучал около 3х месяцев до трудоустройства и год после :) Никто за тебя оценку по времени не сделает.

    ... дали тестовое задание по Yii


    Сделай задание правильно (как требуется по заданию), потом получи оценку, потребуй сделать review. Переделай, если что-то им не понравилось. В следующий раз то же самое будешь делать быстрее. А тонкости фреймворка изучишь по мере работы.
    Ответ написан
    Комментировать
  • Как организовать связь "родительской" таблицы с 2мя одинаковыми наборами данных в "дочерних"?

    copist
    @copist
    Empower people to give
    Не очень понятно слово "связь". Ты подразумеваешь понятие "отношение" реляционной модели данных? (wikipedia)

    CREATE TABLE `A` (
      `ID` INT(11) NOT NULL AUTO_INCREMENT,
       PRIMARY KEY (`ID`)
    );
    
    CREATE TABLE `B` (
      `ID` INT(11) NOT NULL AUTO_INCREMENT,
      `A_ID` INT(11) NOT NULL,
      PRIMARY KEY (`ID`)
    );
    
    -- связь между дочерними записями и родительской записью
    ALTER TABLE `B` ADD CONSTRAINT `B_A_ID` FOREIGN KEY `B` (`A_ID`) REFERENCES `A` (`ID`);


    А то, что у тебя должно быть не больше двух записей B, ссылающихся на A.ID - это средствами MySQL не решается. Можно было бы триггерами решить, но нельзя в триггере обращаться к записям той же таблицы.
    Поэтому это решают внешними средствами, в прикладном приложении.
    Ответ написан
  • Как реализовать опрос сайта yii2?

    copist
    @copist
    Empower people to give
    Я бы поискал утилиту на любом языке, которая опрашивает сайты и хранит данные в MySQL или другой СУБД. А из PHP написал "мост", который позволяет записать в СУБД задачи для мониторинга и читать оттуда результаты.

    На PHP делать монитор не стал бы принципиально - он медленный в этом вопросе и мульти-поточностью придётся возиться.
    Ответ написан
    Комментировать
  • Как работает Yii::app()?

    copist
    @copist
    Empower people to give
    1. Инициализация Yii::app()

    Смотри, в файле www/index.php такие строки
    1. $config = APP_PATH . '/protected/config/main.php';
    2. $app = \Yii::createWebApplication($config); // @var CWebApplication $app
    3. $app->run();


    При отработке строки 2 выполняется код
    1. class YiiBase {
    2. {
    3.     // ... другой код
    4. 
    5.     public static function createWebApplication($config=null)
    6.     {
    7.         return self::createApplication('CWebApplication',$config);
    8.     }
    9.
    10.    public static function createApplication($class,$config=null)
    11.    {
    12.        return new $class($config);
    13.    }
    14. }


    В строке 12 с учётом динамического связывания выполняется return new CWebApplication($config);

    Если пройти по родительским классам, то можно найти, что
    class CWebApplication extends CApplication ...

    и далее
    1. abstract class CApplication extends CModule
    2. {
    3.     // ... другой код
    4. 
    5.     public function __construct($config=null)
    6.     {
    7.         Yii::setApplication($this);
    8.         // ... и другой код
    9.     }
    10. }


    В строке 7 вызывается Yii::setApplication($this);, а если посмотреть класс Yii и его родителя YiiBase, то можно увидеть как в итоге инициализируется переменная для конструкции Yii::app()
    class Yii extends YiiBase { }

    class YiiBase {
    {
        private static $_app;
        public static function setApplication($app) // тут определяется значение self::$_app для Yii::app()
        {
            if(self::$_app===null || $app===null)
                self::$_app=$app;
            else
                throw new CException(Yii::t('yii','Yii application can only be created once.'));
        }
        public static function app() // тут можно прочитать значение self::$_app через Yii::app()
        {
            return self::$_app;
        }
    }


    Теперь понятно, что при инициализации сущности типа CWebApplication эта сущность установилась в приватную переменную YiiBase::$_app, которая доступна через вызов Yii::app()

    Это была инициализация

    2. Использование Yii::app()->module или Yii::app()->component

    Ещё раз посмотри на класс CApplication
    abstract class CApplication extends CModule
    {
        public function __construct($config=null)
        {
            Yii::setApplication($this);
    
            // ... другой код
    
            $this->configure($config);
    
            // ... другой код
        }
    }


    В методе configure($config) происходит подготовка данных, которые понадобятся позже для таких вызовов как (к примеру) Yii::app()->db

    Давай посмотрим на класс Module, в котором и реализуется логика таких вызовов
    abstract class CModule extends CComponent
    {
        public function configure($config) // сохранить всё что передали по переменным
        {
            if(is_array($config))
            {
                foreach($config as $key=>$value)
                    $this->$key=$value;
            }
        }
    
        public function __get($name) // если кто-то пытается вызвать несуществующее свойство, например Yii::app()->db
        {
            if($this->hasComponent($name)) // проверить что есть настройки или готовая сущность компоненты
                return $this->getComponent($name); // вернуть сущность компоненты
            else
                return parent::__get($name);
        }
    
        public function hasComponent($id) // проверить что есть настройки или готовая сущность компоненты
        {
            return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
        }
    
        public function getComponent($id,$createIfNull=true) // вернуть сущность компоненты
        {
            if(isset($this->_components[$id])) // если есть готовая сущность компоненты, вернуть её
                return $this->_components[$id];
            elseif(isset($this->_componentConfig[$id]) && $createIfNull)
            {
                $config=$this->_componentConfig[$id];
                if(!isset($config['enabled']) || $config['enabled'])
                {
                    unset($config['enabled']);
                    $component=Yii::createComponent($config); // создать новую сущность компоненты
                    $component->init();
                    return $this->_components[$id]=$component; // сохранить и вернуть её
                }
            }
        }
    }


    Попробуем расшифровать вызов Yii::app()->db

    Как я уже показал, Yii::app() - это сущность типа CWebApplication, а у неё нет публичного свойства $db, поэтому PHP вызывает магический метод __get() из базового класса CModule. (Посмотри в документации "магические методы")

    Итак, свойства CWebApplication->db не существует и вызывается CModule->__get('db'), далее код считает, что, возможно производится вызов компоненты.

    Метод CModule->hasComponent('db') проверяет, что ранее были заданы какие-то настройки указанной через файл конфигурации protected/config/main.php или иным способом. Если так, то то вызывается CModule->getComponent('db', ...), который вызывает Yii::createComponent($config), где $config - это найденные настройки указанной компоненты, например, параметры соединения с базой данных для компоненты db

    Посмотрим, что делает Yii::createComponent($config)
    class YiiBase
    {
        public static function createComponent($config)
        {
            // посмотри сам, тут интересно
        }
    }


    Cложный метод. Суть его в инстанциировании новой сущности какого-то класса, 5 или 6 способов. Дело в том, что этот метод CModule::createComponent() может быть вызван откуда угодно и у него куча вариантов передачи параметров.

    Итак, CModule::createComponent() создал и вернул новую сущность. И на выходе из метода CModule::getComponent() полученная сущность записывается в массив CModule->_components под именем 'db'.

    Все последующие вызовы Yii::app()->db будут проверять наличие инстанциинованной сущности в массиве CModule->_components['db'] и использовать его, если он там найден

    Заключение:

    Вызов Yii::app()->db
    А. Динамически инициализирует компоненту, по мере необходимости
    Б. Настраивает её данными, которые в частновти можно определить через файл конфигурации protected/config/main.php
    В. Инициализируют компоненту только один раз за цикл работы PHP приложения

    Надеюсь я понятно изложил механизм ленивой инициализации компонент
    Ответ написан
    1 комментарий
  • Почему первый запрос выполняется долго?

    copist
    @copist
    Empower people to give
    Active Record пытается прочесть данные о таблицах, наверное.
    Пройдись по пунктам статьи по оптимизации для Yii2 www.yiiframework.com/doc-2.0/guide-tutorial-perfor... в частности кэширование схем данных и запросов.

    Для Yii1 не могу найти такой же. Был раньше, но в гуглопоиске покрылся пылью.

    Кэширование схемы данных для ActiveRecord
    return array(
        …
        'components'=>array(
            …
            'cache'=>array( // ... компонента для работы с кэшем
                'class'=>'CDbCache',
            ),
            'db'=>array( // ... компонента для работы с БД
                // ... настройки компоненты
                'schemaCachingDuration'=>3600, // <-- кэшировать схему данных для ActiveRecord на 1 час
            ),
        ),
    );


    Ещё есть вариант, используя кэширование, подавить создание коннектов к БД, если они вообще не нужны: copist.ru/blog/2014/09/29/high-speed-yii-database
    Ответ написан
    Комментировать
  • Кто может стать наставником(PHP)?

    copist
    @copist
    Empower people to give
    Привет. Давай сначала твои навыки и уже имеющийся опыт упорядочим в портфолио. Может быть всё не так уж и плохо.

    webmentor.pro/portfolio/#free
    Ответ написан
    Комментировать
  • Что делать с Parse error в Yii?

    copist
    @copist
    Empower people to give
    Сервер специально для Yii скачал последнюю версию Open Servera (5.2.3) с PHP версии 5.3.29. Запустил на нём свой ПХП-скрипт для проверки, всё работает. Что делать?

    Установи виртуальную машину с PHP 5.4+ и в ней работай, если Windows XP заменять не собираешься.

    Кстати, никакой папки vendor, которую он зачем-то ищет не существует, зачем он её ищет?

    Это зависимости: проект включает код других проектов, они хранятся в разным местах и собираются вместе с помощью утилиты composer.

    ... к тому же с черточками / не в ту сторону

    Обратные чёрточки - это для Linux. Windows вроде тоже их понимает.
    Вот пример:
    C:\>cd C:\Windows\
    C:\Windows\>cd C:/Windows/
    C:\Windows\>
    Ответ написан
    Комментировать
  • Какой лучший способ изучить основы фреймфорк?

    copist
    @copist
    Empower people to give
    Как Вы изучили фреймворки? Что бы вы порекомендовали? Реально ли это при практически нулевом знании английского?

    Когда-то пытался придумать свой, пару лет работал на нескольких проектах с ним.

    Потом познакомился с Zend Framework. Мой велосипед стал не интересен.
    Потом Yii и сразу сменил работу. ZF стал неинтересен.
    Потом Laravel, в свободное время экспериментировал. И симфонию - они похожие.
    Потом Phalcon, в свободное время и он мне очень понравился, сделал несколько более сложных проектов для себя самого.
    Потом Python, укрепил язык и на Django для себя сделал проект.
    Потом nodejs, и на Express сделал для себя проект.

    Фактически на мелких задачах тренировался.
    Книги прочитал по ZF, Yii, Laravel. На русском. Это помимо всего того, что я вообще читал про разработку и языки.
    Видео-уроки смотрел по Laravel.
    Читал код фрейворков в особо непонятных местах - смотрел, как они это реализуют, присылал свои исправления в официальные репозитории.

    Английский надо. Но он не сложный
    Ответ написан
    Комментировать
  • Как правильно сохранять отношения в Yii2?

    copist
    @copist
    Empower people to give
    Прямых методов нет, то ты можешь реализовать их таким образом самостоятельно

    class Comment extends CActiveRecord
    {
        public function setUser(\User $user = null)
        {
            if (is_null($user))
            {
                $this->user_id = null;
            } else
            {
                $this->user_id = $user->id;
            }
        }
    }
    
    $comment = new Comment;
    $comment->user = $user;
    // или
    $comment->setUser($user);


    На самом деле схема значительно более сложная, чем просто написать setter для свойства user.
    Что делать, если поменять свойство user_id через которое вычисляется user - его же вроде опять надо подгрузить из базы?
    Будут ли идентичными сущности $user для двух разных комментариев с одинаковым user_id?
    Что делать, если $user ещё не был сохранён ? Не давать присваивать $comment->setUser($user) или делать автоматическое сохранение цепочкой (сначала $user, затем $comment) ?

    Много много много вопросов.
    В Yii2 такие сложности не реализованы, поскольку универсальное всеохватывающее решение как в Doctrina или PropelORM работают очень медленно и жрут память. Там как раз иногда приходится запрещать навороченную логику.
    Ответ написан
    1 комментарий
  • Почему PDO::lastInsertId возвращает неверный ID при частых вставках в БД?

    copist
    @copist
    Empower people to give
    Нет ли у вас такого, что запрос всталяет сразу несколько записей?
    Тогда вернётся ID самой последней вставленной

    P.S. Кстати, использованный метод UUIDv4 не самый надёжный в плане уникальности ключей
    Ответ написан
  • YII. Настройка маршрутизации?

    copist
    @copist
    Empower people to give
    Вариант 1

    'urlManager'=>array(
    		'urlFormat'=>'path',
    		'baseUrl' => '/~abcd', // <-- имя вашей директории, куда перенесён проект
    		'rules'=>array(
    				// стандартное правило для обработки '/' как 'site/index'
    				'' => 'site/index',
    				'user/<action:.*>'=>'user/<action>',
                                    
    				'<controller:\w+>/<id:\d+>'=>'<controller>/view',
    				'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
    				'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
    		),
    		'showScriptName' => false
    	),


    Вариант 2
    server {
        listen   80;
        charset utf-8;
    
        set_real_ip_from 127.0.0.1;
        real_ip_header X-Real-IP;
    
        root /path/to/~abcd; # <-- полный путь к вашей директории, куда перенесён проект
    
        location / {
            index index.html index.php;
            try_files $uri $uri/ /index.php?$args;
        }
    
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        location ~ \.php {
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            #let yii catch the calls to unexising PHP files
            set $fsn /index.php;
            if (-f $document_root$fastcgi_script_name){
                set $fsn $fastcgi_script_name;
            }
    
            # With php5-cgi alone:
            fastcgi_pass 127.0.0.1:9000;
    
            # With php5-fpm:
            #fastcgi_pass   unix:/tmp/php-fastcgi.sock;
    
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fsn;
            #PATH_INFO and PATH_TRANSLATED can be omitted, but RFC 3875 specifies them for CGI
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param PATH_TRANSLATED $document_root$fsn;
        }
    }
    Ответ написан
    3 комментария
  • Как выполнить action с долгим временем работы на Yii2?

    copist
    @copist
    Empower people to give
    Короткий ответ: очереди.
    Ищи информацию про Yii + RabbitMQ/ActiveMQ/ZeroMQ

    Или сделай свою реализацию - сохранить файл-задание в специальную папку, а по крону запускать консольную команду, которая будет эти файлы-задания обрабатывать. Вместо папки можно базу данных использовать.
    Ответ написан
    3 комментария
  • Как оптимизировать работу сайта на yii?

    copist
    @copist
    Empower people to give
    Изучите профилирование кода. Например, используйте для сбора метрик xdebug или xhprof.

    Используйте то, что HaruAtari порекомендовал
    + к этому
    Подавление создания сессий
    Подавление создания коннектов к базе данных
    Ещё нужно оптимизировать загрузку файла конфигурации и полностью отказаться от
    'import' => array('application.components.*', и.т.д. )
    Ответ написан
    Комментировать
  • Как изменить uri на новый (для обработки другим локейшном) без редиректа?

    copist
    @copist
    Empower people to give
    Посмотри документацию на nginx/rewrite
    Если правило "куда" не включает схему (http:// или https://), то можно сделать внутренний редирект.

    Файлы
    /old/path/index.html с текстом "Old";
    /new/path/index.html с текстом "New";
    download?id=AmPy05G2J5pmqNOR6UxhRP56pXVj

    Попробуй такое правило
    location ~ /old/path {
        rewrite /old/path(.*) /new/path$1 break;
    }

    У меня браузер остался с прежним URL, но показал файл по новому пути
    download?id=jNnoITrzRcwF9wcxezeF8AzSoWp6
    Ответ написан
    Комментировать