При разработке продуктов на WordPress рано или поздно встает вопрос о правильной настройке процесса. Сюда входит все: начиная от выбора локального окружения, отладки, тестирования и заканчивая настройкой развертывания (деплоя) итогового кода на сервер. От того, как работает каждое звено, зависит итоговая скорость появления новых фич на сайте, поэтому лучше ответственно подойти к задаче с самого начала.
Я не буду подробно рассматривать сейчас настройки собственно локального окружения, потому что это слишком обширная тема. Просто скажу, что есть 3 основных подхода, каждый со своими плюсами и минусами: Vagrant, Local by Flywheel и Docker. Код, предлагаемый в этой статье, подходит для первых двух окружений. Также, нет смысла в предлагаемой структуре проекта для разработки плагинов или тем — ведь они в принципе должны работать на любых окружения.
Инфраструктура как код
Но что если у вас продуктовый сайт с собственной темой, уникальным функционалом и командой, которая над ним работает? Хорошо бы сделать так, чтобы все разработчики работали над одним и тем же кодом, с одной и той же базой, могли показывать свои коммиты на тестовом сервере (например, для QA) и при этом держали все изменения в git? Особенно если эти изменения в wp-config.php
.
Перепробовав довольно много вариантов, я не нашел ничего лучше, чем положить в git вообще весь сайт, вместе с локальным окружением и сопутствующими настройками. Это значительно упростило ввод новых разработчиков, а также позволило контролировать вообще все изменения в проекте, включая оптимизации локальной версии. Но если у нас один код, который работает локально, на тестовом сайте и на живом проекте — как быть с базой данных? Что будет в wp-config.php
? А вот что:
wp-config.php
if ( file_exists( __DIR__ . '/wp-content/.local' ) ) {
# Настройки локального окружения (присутствует файл .local)
define( 'WP_LOCAL_DEV', true );
define( 'WP_CLI_CONFIG_PATH', '~/.wp-cli/config.yml' );
if ( defined( 'WP_CLI' ) and 'WP_CLI' ) {
# Дебаг через WP CLI, пишем ошибки в логи
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
$_SERVER['HTTP_HOST'] = 'dev.site.com';
} else {
# Дебаг через PHP FPM and HTTP, пишем и показываем ошибки
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
}
define( 'WP_CACHE', false );
define( 'DB_NAME', 'local' );
define( 'DB_USER', 'local' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'DB_HOST_SLAVE', '127.0.0.1' );
define( 'WP_HOME', 'http://dev.site.com' );
define( 'WP_SITEURL', 'http://dev.site.com' );
} elseif ( file_exists( __DIR__ . '/wp-content/.test' ) ) {
# Настройки тестового окружения
define( 'WP_CACHE', false );
define( 'DB_NAME', 'test' );
define( 'DB_USER', 'test' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'WP_HOME', 'https://test.site.com' );
define( 'WP_SITEURL', 'https://test.site.com' );
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
error_reporting( E_STRICT );
} else {
# Настройки продакшн-окружения
define( 'WP_CACHE', true );
define( 'DB_NAME', 'database' );
define( 'DB_USER', 'user' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'WP_HOME', 'https://site.com' );
define( 'WP_SITEURL', 'https://site.com' );
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
}
По-сути, мы добавляем настройки всех сайтов в wp-config.php
, а переключение реализуем на основе наличия определенных файлов-ключей. Если в wp-content
лежит файлик .local
— активируются настройки локального окружения и константа WP_LOCAL_DEV
становится true
. Наличие файла .test
говорит wp-config.php
о том, что мы на тестовом сервере и нужно использовать соответствующие настройки базы. А если никаких файлов нет, значит, мы не продакшене.
Стоит упомянуть, что файлы .test
и .local
добавлены в файл исключений .gitignore
и не попадают в репозиторий. Для начала работы их нужно создавать вручную. Самое простой способ сделать это — с помощью командной строки, подключившись к серверу по SSH:
cd wp-content
touch .test
А если не хранить доступы в Git?
Для некоторых проектов такой подход плох тем, что все доступы хранятся в общем репозитории и могут быть доступны любому участнику команды. В таком случае можно вынести все в отдельные файлы, например local.php, live.php, stage.php и подключать их в php для каждого окружения, вот так:
if ( file_exists( __DIR__ . '/wp-content/local.php' ) ) {
# Настройки локального окружения
require_once(__DIR__ . '/wp-content/local.php');
} elseif ( file_exists( __DIR__ . '/wp-content/test.php' ) ) {
# Настройки тестового окружения
require_once(__DIR__ . '/wp-content/test.php');
} else {
# Настройки продакшн-окружения
require_once(__DIR__ . '/wp-content/live.php');
}
Доступы будут лежать в отдельных файлах и их можно исключить из репозитория, добавив в .gitignore. Но тогда придется вручную создавать их на каждом сервере.
<?php # Настройки продакшн-окружения
define( 'WP_CACHE', true );
define( 'DB_NAME', 'database' );
define( 'DB_USER', 'user' );
define( 'DB_PASSWORD', 'password' );
define( 'DB_HOST', 'localhost' );
define( 'WP_HOME', 'https://site.com' );
define( 'WP_SITEURL', 'https://site.com' );
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
?>
Спасибо uptimizt за идею и наводку на подход Infrastructure as code.
Если у вас есть вопросы по применению этого кода, критика или идеи по его улучшению — пишите их в комментариях. Любая обратная связь приветствуется!