Прощай Drush Make, Привет Composer!

Вс, 13/11/2016 - 22:42

немного вольный перевод статьи:
https://www.lullabot.com/articles/goodbye-drush-make-hello-composer
от Karen Stevenson

Karen Stevenson

Чтоб попробовать новые модули, темы Drupal 8, экспериментировать с новым функционалом, таким как миграции, мною строено-перестроено множество демо-сайтов на Drupal 8.

После длительных ручных установок Drupal 8, решено было взять и выяснить - как упростить это,
как создавать новые Drupal сайты с помощью Composer.

Это на самом деле очень удобный путь, подобный тому, как мы использовали Drush Make раньше; чтобы не хранить у себя код ядра и сопутствующих модулей Drupal, вы просто указываете, какие их версии вам нужны, и получаете их автоматически

Меня немного беспокоила перспектива смены привычного процесса, но мои опасения не оправдались. Тем, кто привык к Drush, скорей всего будет просто разобраться и с этим.

МНОГАБУКВ-НИЧИТАЛ*: Как в чистой директории, парой команд развернуть полностью функциональный Drupal сайт.

composer create-project drupal-composer/drupal-project:8.x-dev drupal --stability dev --no-interaction
cd drupal/web && ../vendor/bin/drush site-install --db-url=mysql://{username}:{password}@localhost/{database}

Установка Composer
Первый шаг - это установка Composer в вашей локальной системе.
Поглядите https://getcomposer.org/download/ для получения информации о том, как установить Composer.

Настройка проекта с Composer
Для создания нового Drupal проекта используя Composer, выполните следующие команды, где /var/drupal требуемое месторасположение кода:

cd /var
composer create-project drupal-composer/drupal-project:8.x-dev drupal --stability dev --no-interaction

В процессе сборки загрузятся все модули ядра, Drush и Drupal Console, затем весь Drupal код будет помещен в поддиректорию web. Сторонний код будет помещен в vendor вне корневой web директории. Новая файловая структура выглядит следующим образом:

файловая структура

В конечном итоге, вы получаете в основе проекта composer.json файл, который выглядит следующим образом.

{
    "name": "drupal-composer/drupal-project",
    "description": "Project template for Drupal 8 projects with composer",
    "type": "project",
    "license": "GPL-2.0+",
    "authors": [
        {
            "name": "",
            "role": ""
        }
    ],
    "repositories": [
        {
            "type": "composer",
            "url": "https://packagist.drupal-composer.org"
        }
    ],
    "require": {
        "composer/installers": "^1.0.20",
        "drupal/core": "8.3.*",
        "drush/drush": "8.*",
        "drupal/console": "~0.8",
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-install-cmd": "scripts/composer/post-install.sh"
    },
    "extra": {
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "web/drush/commands/{$name}": ["type:drupal-drush"]
        }
    }
}

Как вы видите в начале списка модулей в секции "зависимости" - Drush и Drupal console включены по умолчанию. Также вы видите, что согласно правил, сопутствующие модули расположены в подкаталоге /contrib.

Такая организация сайта происходит отсюда: https://github.com/drupal-composer/drupal-project/tree/8.x. README.md содержит описание процесса и действий, таких как обновление ядра. Сопутствующие модули получаются из Packagist а не из Drupal.org. Это обусловлено тем, что существующая система версионирования Drupal, не квалифицируется как семантическое версионирование, необходимое системе.
Дискуссия по поводу как это исправить, продолжается: https://www.drupal.org/node/1612910.

Установка Drupal
В полученном дистрибутиве собрана свежая версия Drupal 8.
Если у вас есть пустая база данных, вы можете немедля установить Drupal, используя Drush из этогоже дистрибутива:

cd drupal/web
../vendor/bin/drush site-install --db-url=mysql://{username}:{password}@localhost/{database}

Если вы не производите установку с помощью Drush, вам придется вручную сделать все, что Drush делает за вас.
Ручной процесс установки Drupal8 следующий:

  • Скопировать default.settings.php в settings.php, и открыть для записи.
  • Скопировать default.license.yml в license.yml , и открыть для записи.
  • Создать и открыть для записи директорию sites/files
  • Перейти по адресу EXAMPLE.COM/install для предоставления данных доступа к базе данных и следовать дальнейшим инструкциям.

Добавление дополнительных модулей из Packagist
Добавление дополнительных модулей происходит немного иначе. Вместо добавления модулей используя drush dl, дополнительные модули добавляются путем выполнения composer команд из корня проекта. (это на один уровень выше корневой директории Drupal):

composer require drupal/migrate_upgrade 8.1.*@dev
composer require drupal/migrate_plus 8.1.*@dev

По мере выполнения этих команд, каждый модуль будет загружен из Packagist, а
composer.json файл будет обновлен с добавлением соответствующей строки в список модулей.
Вы можете взглянуть на содержимое composer.json файла и увидеть, как эволюционирует секция зависимостей.
Делайте так, пока не добавите все необходимые дополнительные модули.
Такой composer.json файл будет эквивалентом Drush make файла, документирующего все ваши модули.

Для достижения еще большего паритета с Drush Make, вы также можете добавлять в composer.json сторонние библиотеки, и используя плагин, указывать необходимые патчи. Более подробно обо всех этих вариантах читайте https://www.drupal.org/node/2471553.

Фиксация файлов в репозитории
Зафиксируйте изменения composer.json в репозитории. Файлы, загруженные Composer, не нужны в репозитории. Гляньте содержимое .gitignore полученного из коробки. В вашем git репозитории будут сохранены только composer.json, .gitignore, код в /web/modules/custom и контент в /web/sites подкаталоге (кроме директории files).

# Ignore directories generated by Composer
vendor
web/core
web/modules/contrib
web/themes/contrib
web/profiles/contrib

# Ignore Drupal's file directory
web/sites/default/files

Обновление файлов
Для получения обновленных версий файлов в любое время, перейдите в корневую директорию Drupal и выполните в командной строке:

composer update

Для добавления дополнительных модулей, тем и библиотек, в любое время, выполните в корневой директории проекта используемую ранее команду:

composer require drupal/module_name 8.1.*@dev

Это добавит еще одну строку в composer.json для соответствующего нового модуля. Теперь изменение composer.json должно быть зафиксировано и отправлено в репозиторий. Остальные инсталляции, в последствии будут принимать эти изменения, и получать новые модули в результате выполнения composer update.

Команда composer update должна быть запущена после каждой отправки или получения изменений от git репозитория. Таким образом, стандартная процедура для обновления из репозитория может быть следующей:

git pull
composer update
drush updb

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

composer install

Это все
Итак, это все. По началу было немного стремно, но, как оказалось, этим очень легко управлять.
Вы можете использовать этот-же метод, с незначительными изменениями, для Drupal 7 сайтов.
Для своих нужд - измените 8.3.*@dev из примера, на необходимые вам актуальные стабильные версии ядра и дополнительных модулей.

multpix: Конец статьи и мое небольшое дополнение

*TLDR (а также tldr и тлдр) — сокращение от too long; didn’t read (слишком длинно; не читал). Аналог фразы «многа букаф, ниасилил». Часто замещает «Резюмируя» после пространных объяснений, которые, как справедливо считает автор этих объяснений, не вся аудитория возжелает прочитать целиком, либо, наоборот, идет первым абзацем.

Полезные ссылки по теме:
Packagist The PHP Package Repository
Шпаргалка по Composer
Drupal Composer рецепты
Освоение Composer: советы и приемы использования
https://github.com/drupal-composer/drupal-project
https://www.drupal.org/docs/develop/using-composer/using-composer-with-drupal
Drupal Composer

И помните главное правило:
Где не работает голова - там работают руки

Спасибо всем указавшим на опечатки и неточности в публикации :-)

12 Спасибо

Комментарии

Аватар пользователя multpix
7 months 2 недели назад multpix #

Товарищи, если кто обратил внимание на неточности перевода, опечатки,
у кого возникли какие вопросы,
добро пожаловать в комментарии.

p/s
прошу воспринимать статью не как полное руководство к действию,
но как информацию к размышлению в нужном направлении,
не делать бездумный копипаст.


ответ экстрасенса на самый избитый и частый вопрос:
https://www.virtualbox.org/wiki/Downloads
https://www.linuxmint.com/
https://ru.wikipedia.org/wiki/Bash
https://ru.wikipedia.org/wiki/SSH

0 Спасибо
Аватар пользователя Mihail.space
7 months 2 недели назад Mihail.space #

Грацио!)

0 Спасибо
Аватар пользователя bumble
7 months 2 недели назад bumble #

На главной

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

Вот так можно свои сборки распространять - публиковать их на GitHub/BitBucket,
а в README.md - подробную инструкцию по развертке.

0 Спасибо
Аватар пользователя fairrandir
7 months 2 недели назад fairrandir #

С работой composer знаком чисто теоретически, но правильно я понимаю, что с его помощью можно без свистопляски с git submodules указывать некоторым модулям (патченным) обновляться со своего, кастомного репозитория, а не с орга? Да собственно, и своим модулям.

Второй вопрос - как это дело дружит со стандартным механизмом обновления. В плане - стандартную систему обновления наверное лучше отключать?

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

Отсюда получаем код
https://packagist.drupal-composer.org/

отсюда и обновляем

Практика будет лучше любых теорий)
поэкспериментируйте.
Установите ядро из ветки 8.1 и модуль какой-нибудь, тоже старой ветки.
Потом обновите до актуальных 8.2(или 3).
Вывод в консоли снимет массу вопросов.

0 Спасибо
Аватар пользователя ХулиGUN
7 months 2 недели назад ХулиGUN #

Во, уже что-то человеческое и похоже на нормальный процесс разработки. Годнота, Сань. Единственное что, я бы всё же весь кастом хранил в sites/* а не раскидывал бы по всему проекту))) Но это уже фломастеры.

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

Да вроде как людям понятны эти core, modules, themes и contrib/custom
Вот и кладут ))

.
├── autoload.php
├── core
├── index.php
├── modules
│   ├── contrib
│   └── custom
├── profiles
│   ├── contrib
│   └── custom
├── robots.txt
├── sites
├── themes
│   ├── contrib
│   └── custom
├── update.php
└── web.config
0 Спасибо
Аватар пользователя ХулиGUN
7 months 2 недели назад ХулиGUN #
multpix написал:
Да вроде как людям понятны эти core, modules, themes и contrib/custom

Вот и кладут ))

Это понятно. Говорю ж - фломастеры. Лично мне удобнее воспринимается такой репозиторий:

.
├── sites
│   └── all
│   │   ├── themes
│   │   └── modules
└── composer.json

Не знаю на сколько это правильно

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

фломастеры)

upd:
хотя, возможно, с точки зрения человекочитаемости файловой структуры,
sites - это место для мультисайтинга, и разделения модулей специфичных для отдельных проектов,
а modules и themes в корневой - для одного проекта.

ох и долго же еще друпалу до Drupal on Rails)))

0 Спасибо
Аватар пользователя gun_dose
7 months 2 недели назад gun_dose #

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

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

Почему?
сотрутся modules/custom/* и themes/custom/* ?
и что-то произойдет с git репозиторием?

Как по мне - описанный метод как раз и позволяет избежать подобных казусов))))

0 Спасибо
Аватар пользователя gun_dose
7 months 2 недели назад gun_dose #

Объясняю ситуацию:
2028 год. Сайт достался по наследству внукам заказчика. Вы решили поставить автоочистку своих репозиториев, в которых 10 и более лет не было никаких изменений. Сайт всё это время исправно работал. Но наступает очередной друпалгедон. Внуки заказчика думают, что надо бы обновить сайт. Контакты разраба остались в скайпе их деда, который завещал пароль внучке, которая с внуками не в ладах. Поэтому новоиспечённые хозяева сайта решают обновить по первой попавшейся инструкции из интернета, где написано "Удалите из корня сайта всё, кроме папки sites". Естественно папки modules, themes и .git отправятся на кладбище удалённых файлов. Далее последует паника, ругань, драки, и, возможно, даже слёзы. А всё потому, что кто-то решил не следовать общепринятоым правилам.

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

ого, сразу видно - не бодыль.
спасибо конечно, но я сегодня не буду, мне еще работать
)))

но ты побереги себя - хороших собеседников - по пальцам пересчитать.

0 Спасибо
Аватар пользователя ХулиGUN
7 months 2 недели назад ХулиGUN #
multpix написал:
upd:

хотя, возможно, с точки зрения человекочитаемости файловой структуры,

sites - это место для мультисайтинга, и разделения модулей специфичных для отдельных проектов,

а modules и themes в корневой - для одного проекта.

Размышления рубиста и питониста в ветке друпал форума об организации процесса разработки смотрится забавно

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

не, ну так я не без греха - друпалю помаленьку...

но, потребовалось время и возможность взгляда со стороны,
чтоб понять, что когда я только друпалил, это по сути было: "из-за угла одной левой и причем ногой из позиции вниз головой"
)))

0 Спасибо
Аватар пользователя ХулиGUN
7 months 2 недели назад ХулиGUN #
gun_dose написал:
Объясняю ситуацию:

2028 год. Сайт достался по наследству внукам заказчика. Вы решили поставить автоочистку своих репозиториев, в которых 10 и более лет не было никаких изменений. Сайт всё это время исправно работал. Но наступает очередной друпалгедон. Внуки заказчика думают, что надо бы обновить сайт. Контакты разраба остались в скайпе их деда, который завещал пароль внучке, которая с внуками не в ладах. Поэтому новоиспечённые хозяева сайта решают обновить по первой попавшейся инструкции из интернета, где написано "Удалите из корня сайта всё, кроме папки sites". Естественно папки modules, themes и .git отправятся на кладбище удалённых файлов. Далее последует паника, ругань, драки, и, возможно, даже слёзы. А всё потому, что кто-то решил не следовать общепринятоым правилам.

В таких случаях обычно В корне пишут какой-нить README.txt ))) дабы власть имущие с умом тронутые подались бы во все тяжкие

0 Спасибо
Аватар пользователя gun_dose
7 months 2 недели назад gun_dose #

Но ведь не просто так придумали структуру, что бесчинствовать можно только в sites, а остальное - священное ядро

0 Спасибо
Аватар пользователя multpix
7 months 2 недели назад multpix #

Я попробую перевести это на русский.

Создавая свой код, привлекая код других людей,
вы должны дать себе ответ на следующие вопросы:
привлеченный в ваше приложение сторонний код - это ваш код или нет,
если не вы сопровождаете код - где его хранить и как собирать.

хранить, собирать
сейчас в php проектах для этого применяются два инструмента:
git и composer.

0 Спасибо
Аватар пользователя ХулиGUN
7 months 2 недели назад ХулиGUN #
gun_dose написал:
Но ведь не просто так придумали структуру, что бесчинствовать можно только в sites, а остальное - священное ядро

Уже ж написали, что фломастеры это всё. Всё зависит от самой организации рабочего процесса... И про бесчинства имелось ввиду, что так легче переносить, обновлять и т.д. А когда ты работаешь с системой контроля версий + установщик пакетов, то тут уже учитываются особенности вышеназванных. Проще говоря - делай, как удобнее для тебя. Я уже писал, что для меня удобнее держать весь кастом в sites. И это чисто из визуальных предпочтений.
В любом случае подход к разработке зачотный. Тебе не нужно в репе хранить весь друпал, а только свой кастом. composer.json это отличный инструмент по переносу конфигурации проекта. Например в питоне подобное - requirements.txt. И весь процесс разработки строится на том, что нужна какая-нить новая либа для проекта - pip install ЛИБА, нужна другая pip install ДРУГАЯ. Перед коммитом выгружаем все наши новые зависимости в requirements.txt - pip freeze > requirements.txt. Другой разработчик пуллится с репы, и устанавливает себе эти зависимости pip install -r requirements.txt. Так и тут с composer.json. Не нужно тянуть в репу весь контриб, достаточно иметь указатель на то, что будет использовано в проекте

1 Спасибо
Аватар пользователя gun_dose
7 months 2 недели назад gun_dose #

Мне тоже нравится этот подход, но я пока как кэлх тупо храню в гите весь сайт, кроме files.

Что касается фломастеров, я всё же настаиваю, что кастомный и контрибный код должен быть в sites. Потому что если он там, то обновить ядро сможет любой колхозник за 10 минут.

С другой стороны, чего париться о проблемах заказчика, который перестал с тобой сотрудничать?)))

0 Спасибо
Аватар пользователя ХулиGUN
7 months 2 недели назад ХулиGUN #
gun_dose написал:
Что касается фломастеров, я всё же настаиваю, что кастомный и контрибный код должен быть в sites

Храните. Я Вам разрешаю))) Более того - мне даже импонирует данный подход

0 Спасибо
Аватар пользователя Mihail.space
7 months 2 недели назад Mihail.space #

семерка с годами того,а в восьмерке только папку core менять при обновляшке и весь контриб/кастом на месте

1 Спасибо
Аватар пользователя sergeybelya
7 months 1 неделя назад sergeybelya #

не только ее.

0 Спасибо
Аватар пользователя Grenuy
1 month 3 недели назад Grenuy #

КАК КАЧНУТЬ ПАПКУ CORE???
пытаюсь перейти на трушный метод разработки, и с drupal 7 на drupal 8
собственно первое что привлекает это как раз возможность работать с гитом.
так вот ВОПРОС знатоки!
Поставил все через композер, инстальнул возможно даже добавил модли

composer create-project drupal/drupal dir 8.*@stable
drush site-install --db-url=mysql://{username}:{password}@localhost/{database}
composer require drupal/token @stable
drush en token

все классно! далее гитнул это все дело, и перехожу на другой сервер(к примеру с локального на дев сервер)
Вот сделал

git clone repo
composer install

И папки core нет уже и там подпилял, и там, и то попробовал и се, а папки нет, как сделать через cli что бы она появилась?

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #

тут в статье используется шаблон https://github.com/drupal-composer/drupal-project
не помешает изучить его док.
в корне созданного проекта делаем composer install
а то, что привыкли называть drupal root - это в кат. web, туда заходим только чтоб подрашить)

0 Спасибо
Аватар пользователя Grenuy
1 month 3 недели назад Grenuy #

С установкой через композер проблем нет. Вопрос именно переноса проекта с одной машины на другую посредством git+composer использовая gitignore core сидит там, и при розворачивания по мануалу не подтягивается.

0 Спасибо
Аватар пользователя gun_dose
1 month 3 недели назад gun_dose #
multpix написал:
подрашить

Главное, ударение не перепутать.

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #

Дали драш - е**ш)

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #

@Grenuy

в систему контроля версий - весь проект:

PROJECT_NAME
├── .gitignore
├── composer.json
├── composer.lock
├── config
├── drush
├── LICENSE
├── phpunit.xml.dist
├── README.md
├── scripts
├── vendor
└── web
    ├── autoload.php
    ├── core
    ├── index.php
    ├── modules
    ├── profiles
    ├── robots.txt
    ├── sites
    ├── themes
    ├── update.php
    ├── web.config
    └── white.png

Дале:

git clone REMOTE_REPO/PROJECT_NAME
cd PROJECT_NAME
composer install
0 Спасибо
Аватар пользователя Grenuy
1 month 3 недели назад Grenuy #

gitignore имеет

# Ignore core and vendor when managing dependencies with Composer.
core
vendor

вот вендер роворачиваеться, а core все никак... ( да и по логики должно было бы подтянуться, ведь везде одинаковый и с репы должно тянуться, да и что бы по трушному делать... Вот и ищу где что сделал не так, или чудо команду которая на новой машине, с которой подтянул проект с гита, что бы еще и подтянулся core

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #

все работает в лучшем виде.

давай весь листинг из консоли, как эт делаешь

0 Спасибо
Аватар пользователя Grenuy
1 month 3 недели назад Grenuy #

install на локальную машину

composer create-project drupal/drupal . 8.*@stable

добавляем для теста несколько модулей

composer require drupal/token @stable
composer require drupal/metatag  @stable
composer require drupal/pathauto @stable
composer require drupal/panels @stable
composer require drupal/linkit @stable
composer require drupal/module_filter @stable

далее добавляем .gitignore

# Ignore files generated by PhpStorm
.idea

# This file contains default .gitignore rules. To use it, copy it to .gitignore,
# and it will cause files like your settings.php and user-uploaded files to be
# excluded from Git version control. This is a common strategy to avoid
# accidentally including private information in public repositories and patch
# files.
#
# Because .gitignore can be specific to your site, this file has a different
# name; updating Drupal core will not override your custom .gitignore file.

# Ignore core and vendor when managing dependencies with Composer.
core
vendor
modules/contrib
themes/contrib
profiles/contrib

# Ignore configuration files that may contain sensitive information.
sites/*/settings*.php
sites/*/
services*.yml

# Ignore paths that contain user-generated content.
sites/*/files
sites/*/
private

!sites/default/files/config_*/sync/

# Ignore SimpleTest multi-site environment.
sites/simpletest

# If you prefer to store your .gitignore file in the sites/ folder, comment
# or delete the previous settings and uncomment the following ones, instead.

# Ignore configuration files that may contain sensitive information.
# */settings*.php

# Ignore paths that contain user-generated content.
# */files
# */private

# Ignore SimpleTest multi-site environment.
# simpletest
vendor/doctrine/common/lib/vendor/
vendor/guzzlehttp/guzzle/build/
vendor/guzzlehttp/guzzle/docs/
vendor/guzzlehttp/guzzle/tests/
#Would skip repository libraries/dropzone
#libraries/composer.json

далее заливка на гит

git add .
git commit -m "Bla bla"
git push

Устанавливать пока не обязательно, позже буду, хотя бы движок развернуть что бы работало

далее уже в новой папке

git clone MyRepo .
composer install

все... вендор появился, модуля так же, core нет.

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #
composer create-project drupal-composer/drupal-project:~8.3 PROJECT_NAME
cd PROGECT_NAME
git init
git add -A && git commit -m "initial"
git remote add origin REMOTE_REPO/PROJECT_NAME
git push -u origin master

откуда то еще

git clone REMOTE_REPO/PROJECT_NAME
cd PROJECT_NAME
composer install

Распространяем весь проект, в его корне работаем с composer
(не в web, в котором друпал и куда нацелен вебсервер)

#PROJECT_NAME/.gitignore

# Ignore directories generated by Composer
/drush/contrib/
/vendor/
/web/core/
/web/modules/contrib/
/web/themes/contrib/
/web/profiles/contrib/
/web/libraries/

# Ignore sensitive information
/web/sites/*/settings.php
/web/sites/*/
settings.local.php

# Ignore Drupal's file directory
/web/sites/*/files/

# Ignore SimpleTest multi-site environment.
/web/sites/simpletest

# Ignore files generated by PhpStorm
/.idea/

0 Спасибо
Аватар пользователя Grenuy
1 month 3 недели назад Grenuy #

С этим работает
composer create-project drupal-composer/drupal-project:8.x-dev some-dir --stability dev --no-interaction
А вот с офф не работает
composer create-project drupal/drupal dir 8.*@stable

Жаль.. Будем пока жить не с официальным :) спасибо!

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #

все нормально, этож гитигнор используемого шаблона

0 Спасибо
Аватар пользователя Grenuy
1 month 3 недели назад Grenuy #

Причина не только в нем, а в строении папок файлов, с офф репы, папки web нет

0 Спасибо
Аватар пользователя multpix
1 month 3 недели назад multpix #

Я советую почитать конфиг шаблона - там ответы на все незаданные вопросы)

0 Спасибо

Страницы