Главный файл плагина должен быть не местом, где живет вся логика, а точкой входа. Смотите также варинат использования DI контейнера в плагине. Его задача - аккуратно запустить плагин, проверить окружение и передать управление нормальной структуре кода. Хороший главный файл обычно делает только это: содержит заголовоки плагина запрещает прямой запуск файла определяет базовые константы подключает автозагрузку […]
Главный файл плагина должен быть не местом, где живет вся логика, а точкой входа.
Его задача - аккуратно запустить плагин, проверить окружение и передать управление нормальной структуре кода.
Хороший главный файл обычно делает только это:
Пример:
<?php
/**
* Plugin Name: My Plugin
* Description: Short plugin description.
*
* Requires at least: 6.5
* Requires PHP: 8.4
*
* Author: Author Name
* Author URI: https://example.com
* License: GPL-2.0+
* Text Domain: my-plugin
*
* Version: 1.0.0
*/
defined( 'ABSPATH' ) || exit;
define( 'MY_PLUGIN_FILE', __FILE__ );
define( 'MY_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'MY_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'MY_PLUGIN_VERSION', '1.0.0' );
require_once MY_PLUGIN_DIR . 'vendor/autoload.php';
register_activation_hook( __FILE__, [ My_Plugin\Activator::class, 'activate' ] );
register_deactivation_hook( __FILE__, [ My_Plugin\Deactivator::class, 'deactivate' ] );
add_action( 'plugins_loaded', 'my_plugin_bootstrap' );
function my_plugin_bootstrap() {
if ( ! my_plugin_requirements_met() ) {
return;
}
My_Plugin\Plugin::instance()->init();
}
function my_plugin_requirements_met() {
return version_compare( PHP_VERSION, '8.1', '>=' );
}
Главный принцип: файл - это декларация, не реализация
Самая правильная логика такая: чем меньше кода в главном файле, тем лучше. Все, что можно вынести из него без потери понятности, нужно выносить. Его цель - не реализовывать плагин, а безопасно и понятно его запустить.
Плохой главный файл - это когда в нем сразу регистрируются CPT, шорткоды, AJAX, REST API, админка, настройки, крон, стили, скрипты. Сотни строк кода, хуки вперемешку с функциями, глобальные переменные... Через год такой файл превращается в свалку.
Он не должен знать детали реализации. Он только подготавливает окружение и запускает главный класс плагина.
Правильный порядок такой:
plugins_loaded или init запускается основной класс.Потому что в момент загрузки главного файла WordPress еще может быть не полностью готов. Другие плагины могут быть не загружены, переводы еще могут быть недоступны, некоторые API еще рано использовать. Поэтому главный файл должен только подготовиться, а реальный запуск лучше делать через хук.
Для маленького плагина можно обойтись функциями. Для среднего и большого лучше сразу делать отдельный класс Plugin, который регистрирует остальные части:
namespace My_Plugin;
class Plugin {
public static function instance(): self {
static $instance;
if ( ! $instance ) {
$instance = new self();
}
return $instance;
}
private function __construct() {
$this->define_constants(); // если не вынесли в главный файл
$this->load_dependencies();
$this->set_locale();
$this->define_hooks();
}
public function init(): void {
( new Assets() )->init();
( new Admin() )->init();
( new Rest_Api() )->init();
}
}
Обязательно ли Singleton
Singleton часто используют для главного класса плагина, но это не обязательный и не всегда лучший вариант.
Мне лично такой подход не особо нравится. Его минус в том, что класс сам себя создает и хранит собственный экземпляр. Из-за этого его сложнее тестировать, сложнее переинициализировать с другими параметрами, а сам класс получает лишнюю ответственность (SRP нарушен) - он отвечает не только за работу плагина, но и за свое создание.
Для меня более мягкий подход - создать объект плагина в главном файле и передать ему нужные параметры.
Если нужен быстрый доступ к объекту плагина, можно сделать helper-функцию plugin(), Однако лучше не использовать её внутри бизнес-логики, а лучше передавать зависимости явно.
Пример:
Main.php
<?php
/**
* Plugin Name: My Plugin
* Description: Short plugin description.
*
* Requires at least: 6.5
* Requires PHP: 8.4
*
* Author: Author Name
* Author URI: https://example.com
* License: GPL-2.0+
* Text Domain: my-plugin
*
* Version: 1.0.0
*/
namespace My_Plugin;
defined( 'ABSPATH' ) || exit;
require_once __DIR__ . '/vendor/autoload.php';
register_activation_hook( __FILE__, [ Activator::class, 'activate' ] );
register_deactivation_hook( __FILE__, [ Deactivator::class, 'deactivate' ] );
add_action( 'plugins_loaded', '\My_Plugin\load' );
function load(): void {
plugin()->init();
}
function plugin(): Plugin {
static $plugin = null;
$plugin ??= new Plugin( __FILE__ );
return $plugin;
}
Plugin.php
<?php
namespace My_Plugin;
class Plugin {
public readonly string $main_file;
public readonly string $dir; // no end slash
public readonly string $url; // no end slash
public readonly string $ver;
public readonly string $name;
public readonly string $desc;
public function __construct( string $main_file ) {
$file_data = get_file_data( $main_file, [
'ver' => 'Version',
'name' => 'Name',
'desc' => 'Description',
] );
$this->main_file = $main_file;
$this->dir = dirname( $main_file );
$this->url = plugins_url( '', $main_file );
$this->ver = $file_data['ver'];
$this->name = $file_data['name'];
$this->desc = $file_data['desc'];
}
public function init(): void {
( new Assets( $this->ver ) )->init();
( new Admin( $this->main_file ) )->init();
( new Rest_Api() )->init();
}
}| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | вкладчик | 0 | 10 | 15-08-2026 |
| 2 | Docker Fundamentals: что внутри compose.yaml и как там всё устроено | 0 | 8.14 | 24-07-2026 |
| 3 | Шаблоны C++ как инструмент архитектуры: compile-time dispatch, type traits и type erasure | 5 | 7 | 28-06-2026 |
| 4 | API Сайдбаров и Виджетов | 0 | 12.3 | 22-05-2026 |
| 5 | Чем занимается комплектовщик на складе | 0 | 6.94 | 18-02-2026 |
| 6 | Синхронизация стилей сайта с theme.json | 0 | 8.26 | 31-07-2026 |
| 7 | Платон Голубков | 0 | 26.67 | 12-08-2026 |
| 8 | Названы неочевидные признаки заражения гаджета вирусами | 0 | 8.23 | 16-08-2026 |
| 9 | Улучшения переводов в WP 6.5 (.l10n.php) | 0 | 12.62 | 23-05-2026 |