Задать вопрос
  • Как настроить дебаг в консоли с помощью инструментов vscode && docker?

    @kucheriavij
    ky0, это в никсах оно прекрасно работает, а в винде не очень. Тоже сталкивался с этим, и пока не прописал в extra_hosts отказывался xdebug работать. Правда у меня phpstorm в качестве ide.
    Написано
  • Как настроить дебаг в консоли с помощью инструментов vscode && docker?

    @kucheriavij
    Hfnas, так надо прокинуть домен в контейнер, откуда ему знать кто такой этот ваш host.docker.internal.
    В app в docker-compose.yaml добавьте следующее:
    extra_hosts:
          - "host.docker.internal:host-gateway"
    Написано
  • Как настроить или в каком направлении почитать, что бы настроить бесшовную аутентификацию через Keycloak?

    @kucheriavij
    не приходилось вводить логин и пароль и жать кнопку "войти через Kyecloak" , во втором, а бесшовно выполнить вход.

    Жать кнопку все равно придется, потому что в клоаку надо отправить запрос. А вот уже клоака сама поймет, если юзер уже авторизован - отдаст токены, если нет - попросит ввести пару логин/пароль.
    Подскажите, в какую сторону копать, если не сложно

    Если кратко, то:
    • создаете новый реалм;
    • в новом реалме настраиваете под каждый сайт свой клиент
    • отправляете запросы в клоаку через апи с помощью данных, которые у вас будут после создания нового клиента.
    Написано
  • Почему появляются наводки на микрофон?

    @kucheriavij
    Фаза на красном, жёлтый видимо ноль, и отсоединенный синий есть, вероятно земля, но я не проверял.

    Если мне память не изменяет, то принято как раз желто-зеленой жилой делать как раз заземление. Хотя в вашем случае просто вся проводка не заземлена, раз присутствует не используемая жила, поэтому вероятней всего и идет наводка...
    Написано
  • Из-за чего происходит ошибка при попытке создать миграцию в Symfony?

    @kucheriavij
    //offtop
    А еще сущности User желательно реализовать следующие интерфейсы: UserInterface, PasswordAuthenticatedUserInterface
    Написано
  • Как правильно производить деплой с gitlab ci/cd?

    @kucheriavij Автор вопроса
    Ну с этим вроде как понимание есть. Не могу понять только как это все правильно организовать и по репам раскидать. Вот у меня есть репозитории с проектами, там у них свои docker-compose.yaml и Dockerfile, чего достаточно для разработки локально. При пуше в определенную ветку будет билдиться image - ок, понятно. Только вот, например, для того же php требуются всякие php.ini, и прочие конфиги. Вот они должны лежать в тоже репе что и проект? Но тогда этих конфигов будет куча, так как локально нужны одни конфиги, на проде другие. Далее, если я правильно понимаю, мне надо завести репу, например, docker, где и будет лежать, скажем так, "мастер" docker-compose.yaml, и конфиги, которые будут тащиться уже непосредственно на сервер. И получается, что если у меня собрался образ, в определенной ветке, то этот образ уже улетает на сервер и там разворачивается? Но тут еще возникает вопрос, как быть с миграциями?
  • Как изменить заголовки запроса?

    @kucheriavij
    Добрый день. Удалось решить проблему?
  • Как найти в строке подстроку?

    @kucheriavij
    Дмитрий, там же в документации все написано. Все правильно работает. Функция вернула позицию символа. Там же, в документации даже пример есть с проверкой
  • Так ли необходима TN матрица для дизайна?

    @kucheriavij
    Mercury13, а какой у вас бюджет? Я себе пару месяцев назад взял DELL UltraSharp U2715H 27", глаз не нарадуется. Да и коллега-дизайнер говорит для дизайна только IPS, причем не важно, web или полиграфия...
  • Стоит ли делать перенаправление без слеша?

    @kucheriavij
    alohamneploha, сделайте тогда редирект на страницы со слешем. В принципи больше ничего и не надо. Хотя карту сайта все равно надо периодически обновлять. Как я уже написал, не существует принципиальной разницы, какой вариант в конечном итоге останется, важно чтоб был только один вариант
  • Стоит ли делать перенаправление без слеша?

    @kucheriavij
    alohamneploha, это в идеале, и роботы не существующие страницы выкидывает из выдачи быстрее чем склеивает дубли. Вариант со слешем или без (не важно какой) обычно надо закладывать на стадии разработки, но то что должен существовать только один - это факт. Как это будет реализовываться тоже не принципиально (склейка, ака редирект, или выкидывание), но для поисковика должен отдаваться только один вид
  • Как решить проблему с автозагрузкой в yii1?

    @kucheriavij Автор вопроса
    slo_nik, ну там под php7 начиная с 1.1.16 вроде пошла адаптация. Я собственно и апнул версию до последней актуальной (1.1.19). Но ничего не выходит, как ни крути ругается именно на эту ошибку
  • Как решить проблему с автозагрузкой в yii1?

    @kucheriavij Автор вопроса
    slo_nik, в той части которую разрабатывали прописаны. Прописать namespace по всему фреймворку, это то еще извращение. Ошибка ведет именно на самое ядро фреймворка.
  • Как решить проблему с автозагрузкой в yii1?

    @kucheriavij Автор вопроса
    Пробовал, не помогает. На вторую версию переводить это надо весь проект написать с нуля, а это уже не мне решать а руководству. А оно сделает выбор в пользу битрикса, потому что "не надо аж целую админку писать"
  • Как в хлебных крошках битрикса получить параметры компонента?

    @kucheriavij Автор вопроса
    Иван Иванов, пробовал. В настройках самого компонента это все появляется, но вот в шаблон компонента не попадает. И судя по коду самого компонента туда передаются только предустановленные настройки, новые не передаются. Добавить новые в самом компоненте тоже не получается, так как функция, которая строит саму цепочку находится в самом главном классе, и принимает только текущие параметры. Любые попытки перегрузить эту функцию ведут к тому, что надо переписать половину класса
  • Как в хлебных крошках битрикса получить параметры компонента?

    @kucheriavij Автор вопроса
    Иван Иванов, допустим строку, скажем THEME в которой будет храниться тот самый Css класс, который и меняет стилистику. Хотя можно было бы и select. Но дело не в этом, в самом component.php $arParams не существует. Там вообще какая та неведомая магия творится, и насколько я понял сами крошки формируются отложенной функцией, которая сидит в классе CMain, это вообще эпик, даже не кастомизируешь эту функцию
  • Как в хлебных крошках битрикса получить параметры компонента?

    @kucheriavij Автор вопроса
    Это такой-же кастыль как и несколько шаблонов с разными css классами. Хочется минимизировать будущие вмешательства в код, а менять стиль надстройкой компонента, как это везде работает, и не плодить одинаковые шаблоны
  • Как оставить название раздела в "хлебных крошках"?

    @kucheriavij Автор вопроса
    Да в итоге так и сделал. Просто не логично получается, почти все СЕО настройки в одном месте, а заголовок в другом. Ну да ладно. Спасибо)
  • Что почитать программисту о дизайне?

    @kucheriavij
    ой всё, он мне тоже не нравится, но эти книги у него толковые
  • Robot.txt и карта сайта для поддоменов?

    @kucheriavij
    Виктор Уманский, У меня кастомный urlManager. Писал его не я, пришлось продолжать то что было. Я бы правил в конфиги накидал
    namespace app\base;
    
    use dictionary\models\Average;
    use dictionary\models\Features;
    use dictionary\models\Kitchen;
    use dictionary\models\Position;
    use dictionary\models\Type;
    use dictionary\models\TypeFacility;
    use restaurants\models\Restaurants;
    use structure\models\Section;
    use tops\models\Collection;
    
    /**
     * Class UrlManager
     *
     * @package app\base
     */
    class UrlManager extends \yii\web\UrlManager
    {
        /**
         * @var
         */
        public $domain;
        /**
         * @var
         */
        public $original;
    
        /**
         * @var array
         */
        private $_params = [];
    
        /**
         * @param \yii\web\Request $request
         * @return mixed
         */
        public function parseRequest($request)
        {
    
            if (false !== $r = parent::parseRequest($request)) {
                return $r;
            }
    
            $result = false;
            $name = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : $_SERVER['HTTP_HOST'];
            /* @var Restaurants $rest */
            if (($rest = \Yii::$app->db->cache(function ($db) use ($name) {return Restaurants::findOne(['domain' => $name, 'publish' => 1]);}, 3600))) {
                $this->_params['rest'] = $rest;
                $this->_params['city'] = $rest->city;
    
                if ($request->url === '/') {
                    $this->_params['section'] = \Yii::$app->db->cache(function ($db) use ($rest) {
                        return Section::findOne(['rest_id' => $rest->id, 'depth' => 0, 'publish' => 1]);
                    }, 3600);
                    $result = ['restaurants/frontend/default', []];
                } else {
                    $result = $this->parseStruct($request, $rest);
                }
            } elseif ($dict = Average::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'average';
                    $result = ['dictionary/frontend/default', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'average';
                    $result = ['dictionary/frontend/default/robots', []];
                }
            } elseif ($dict = Kitchen::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'kitchen';
                    $result = ['dictionary/frontend/default', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'kitchen';
                    $result = ['dictionary/frontend/default/robots', []];
                }
            } elseif ($dict = Type::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'type';
                    $result = ['dictionary/frontend/default', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'type';
                    $result = ['dictionary/frontend/default/robots', []];
                }
            } elseif ($dict = Position::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'position';
                    $result = ['dictionary/frontend/default', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'position';
                    $result = ['dictionary/frontend/default/robots', []];
                }
            } elseif ($dict = TypeFacility::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'type_facility';
                    $result = ['dictionary/frontend/default', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'type_facility';
                    $result = ['dictionary/frontend/default/robots', []];
                }
            } elseif ($dict = Features::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'features';
                    $result = ['dictionary/frontend/default', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['dictionary'] = $dict;
                    $this->_params['model_type'] = 'features';
                    $result = ['dictionary/frontend/default/robots', []];
                }
            } elseif ($top = Collection::findOne(['domain' => $name, 'publish' => 1])) {
                if ($request->url === '/' || $request->url === '/all') {
                    $this->_params['collection'] = $top;
                    $this->_params['model_type'] = 'collection';
                    $result = ['tops/frontend/top/index', []];
                } elseif ($request->url === '/robots.txt') {
                    $this->_params['collection'] = $top;
                    $this->_params['model_type'] = 'collection';
                    $result = ['tops/frontend/top/robots', []];
                }
            } elseif (($route = $this->parseStruct($request))) {
                $section = $this->_params['section'];
    
                if (strpos($name, $section->city->name) === false) {
                    $qr = !empty($request->queryString) ? "?" . $request->queryString : "";
                    $url = sprintf("http://%s.%s%s", $section->city->name, \Yii::$app->params['domain'], $section->url, $qr);
    //                \Yii::$app->response->redirect($url, 301);
                    header("Location: {$url}");
                    // TODO убрать если что-то сломается
                    die();
                }
                $result = $route;
            }
    
            return $result;
        }
    
        /**
         * @return array
         */
        public function getParams()
        {
            return $this->_params;
        }
    
        /**
         * @param \yii\web\Request $request
         * @param Restaurants $rest
         * @return mixed
         */
        private function parseStruct($request, $rest = null)
        {
            $pathInfo = trim($request->pathInfo, '/');
    
            $query = Section::find();
    
            if ($pathInfo === '') {
                $query->where(['publish' => 1, 'depth' => 0]);
            } elseif ($pathInfo === 'robots.txt') {
                $request->pathInfo = 'robots';
            } else {
                $segments[] = '/' . $pathInfo . '/';
                while (($pos = strrpos($pathInfo, '/')) !== false) {
                    $pathInfo = substr($pathInfo, 0, $pos);
                    $segments[] = '/' . $pathInfo . '/';
                }
    
                $query->where(['publish' => 1, 'url' => $segments])
                    ->orderBy(['lft' => SORT_DESC, 'depth' => SORT_DESC]);
            }
    
            if (isset($rest)) {
                $query->andWhere(['rest_id' => $rest->id]);
            }
    
            $section = \Yii::$app->db->cache(function ($db) use ($query) {
                return $query->one();
            }, 3600);
    
            if (isset($section)) {
                $this->_params['section'] = $section;
                $this->_params['city'] = isset($rest->city_id) ? $rest->city_id : 'krasnodar';
    
                $route = trim(str_replace($section->url, '/', '/' . $request->pathInfo . '/'), '/');
    
                if ($route === '') {
                    $request->pathInfo = $section->route;
                    $route = $section->route;
                } else {
                    $route = substr($section->route, 0, strrpos($section->route, '/') + 1) . $route;
                    $request->pathInfo = $route;
                }
    
                $this->_params['route'] = $route;
    
                $this->enableStrictParsing = false;
                if (false !== $r = parent::parseRequest($request)) {
                    $this->enableStrictParsing = true;
    
                    return $r;
                }
            }
    
            return $request->pathInfo;
        }
    }

    Далее в контроллере парочка функций:
    /**
         * @return null|Robots
         */
        protected function getRobots()
        {
            $url = $_SERVER['HTTP_HOST'];
            $restName = strtok($url, '.');
            $rest = Restaurants::findOne(['name' => $restName]);
            $robots = Robots::findOne(['rest_id' => $rest->id]);
    
            return $robots;
        }
    
        /**
         * @return string
         */
        public function actionRobots()
        {
            $response = \Yii::$app->response;
            $response->format = Response::FORMAT_RAW;
            $response->getHeaders()->set('Content-Type', 'text/plain; charset=utf-8');
    
            if ($this->getRobots()) {
                return $this->renderPartial('robots', ['content' => $this->getRobots()->content]);
            }
    
            $content = <<<TEXT
    User-agent: *
    Allow: *
    Host: {$_SERVER['HTTP_HOST']}
    TEXT;
    
            return $this->renderPartial('robots', ['content' => $content]);
        }


    Ну и вьюха для вывода. В админке у соответствующих записей есть раздел для редактирования всей этой кухни с самой обычной textarea, все это пишется в БД