Хуки входа и регистрации в WordPress: как зарегистрировать своё действие

Раздел: Разработка на WordPress -> Хуки входа и регистрации в WordPress

Регистрация действий (actions) в WordPress для хуков входа и регистрации

Действия (actions) в WordPress - это точки входа, позволяющие выполнить произвольный PHP-код в определённые моменты работы системы. Для хуков, связанных со входом и регистрацией пользователей, существуют стандартные действия, такие как user_register, wp_login, register_new_user и другие. Регистрация собственного обработчика (callback) выполняется с помощью функции add_action(), которая связывает имя действия с именем функции или замыканием.

Основной способ: использование add_action() для стандартного действия

Как зарегистрировать функцию, которая выполняется после успешной регистрации нового пользователя?


// functions.php вашей темы или в плагине
add_action( 'user_register', 'my_custom_registration_action', 10, 1 );

function my_custom_registration_action( $user_id ) {
    // $user_id - ID только что созданного пользователя
    $user = get_userdata( $user_id );
    // Например, записать время регистрации в метаполе
    update_user_meta( $user_id, 'registration_timestamp', time() );
    // Отправить приветственное письмо
    wp_mail( $user->user_email, 'Добро пожаловать!', 'Спасибо за регистрацию.' );
}
  

Action register php (регистрация действия (action) в php)

В этом примере используется приоритет 10 и один аргумент (user_id). Функция my_custom_registration_action будет вызвана сразу после создания записи пользователя в базе данных.

Как зарегистрировать обработчик для события входа пользователя?


add_action( 'wp_login', 'my_login_action', 10, 2 );

function my_login_action( $user_login, $user ) {
    // $user_login - логин, $user - объект WP_User
    // Записать время последнего входа
    update_user_meta( $user->ID, 'last_login', current_time( 'mysql' ) );
}
  

Действие wp_login передаёт два аргумента: строку с именем пользователя и объект пользователя. Важно указать правильное число принимаемых аргументов в add_action().

Вариант 1: Использование анонимной функции (замыкания)

Как зарегистрировать действие без создания именованной функции, чтобы код был компактнее?


add_action( 'register_new_user', function( $user_id ) {
    // Добавить пользователя в список рассылки
    $email = get_userdata( $user_id )->user_email;
    // условный вызов API внешнего сервиса
    error_log( 'Новый пользователь зарегистрирован: ' . $email );
} );
  

Замыкания удобны для быстрых одноразовых действий, но их нельзя удалить через remove_action() без сохранения переменной.

Вариант 2: Регистрация действия с использованием метода класса

Как организовать код в объектно-ориентированном стиле для регистрации хуков?


class User_Logging {
    public function __construct() {
        add_action( 'wp_login', [ $this, 'log_login' ], 10, 2 );
        add_action( 'user_register', [ $this, 'log_register' ] );
    }

    public function log_login( $user_login, $user ) {
        // Логирование входа
        $this->write_log( 'login', $user->ID );
    }

    public function log_register( $user_id ) {
        $this->write_log( 'register', $user_id );
    }

    private function write_log( $type, $user_id ) {
        global $wpdb;
        $wpdb->insert( $wpdb->prefix . 'user_log', [
            'user_id' => $user_id,
            'action'  => $type,
            'time'    => current_time( 'mysql' )
        ] );
    }
}

new User_Logging();
  

Использование класса упрощает управление зависимостями и позволяет легко расширять функциональность.

Вариант 3: Создание собственного действия (custom action) и его регистрация

Как создать точку входа для других разработчиков и позволить им подключать свои функции?


// В вашем плагине или теме
function my_custom_user_action( $user_id ) {
    // Ваш код
    do_action( 'my_plugin_after_user_create', $user_id );
}

// Теперь другие разработчики могут зарегистрировать своё действие
add_action( 'my_plugin_after_user_create', 'another_function', 10, 1 );
  

Такой подход позволяет расширять функциональность без изменения основного кода. При создании собственных действий важно документировать передаваемые аргументы.

Вариант 4: Изменение приоритета и количества аргументов

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


// Высокий приоритет (выполнится раньше стандартных)
add_action( 'wp_authenticate', 'early_check', 1, 2 );
// Низкий приоритет (выполнится позже)
add_action( 'wp_authenticate', 'late_check', 99, 2 );

function early_check( $username, $password ) {
    // Проверка ещё до аутентификации
}
  

Приоритет по умолчанию 10. Чем меньше число, тем раньше выполняется функция. Количество аргументов должно соответствовать тому, что передаёт действие. Ошибка в значении $accepted_args приведёт к тому, что функция получит меньше данных.

Типичные ошибки и способы их решения

Ошибка 1: Неправильное имя хука. Действие не срабатывает, потому что имя написано с опечаткой или не соответствует действительности. Решение: проверять список стандартных хуков в документации WordPress или использовать поиск по исходному коду.

Ошибка 2: Не указано количество аргументов. Функция принимает, например, один аргумент, а действие передаёт два. В результате второй аргумент игнорируется или возникает notice. Решение: всегда указывать $accepted_args в add_action().

Ошибка 3: Использование die() или exit() внутри хука, что может прервать нормальный процесс регистрации или входа. Решение: вместо прерывания использовать возврат ошибки или исключение, если это действительно необходимо, и только после основного действия.

Ошибка 4: Попытка зарегистрировать действие внутри условного блока, который не выполняется. Например, вызов add_action() внутри if ( is_admin() ) может пропустить хуки на фронтенде. Решение: размещать регистрацию в общем коде, который загружается всегда.

Ошибка 5: Глобальные переменные не объявлены. При использовании global $wpdb или $post внутри хука нужно убедиться, что они доступны в момент вызова. Решение: явно объявлять глобальные переменные внутри функции.

Расширенные примеры регистрации действий для входа и регистрации

Пример 1: Запись IP-адреса при входе пользователя

Цель: сохранять IP-адрес, с которого был выполнен вход, для целей безопасности или статистики.

Пример

add_action( 'wp_login', 'record_login_ip', 10, 2 );

function record_login_ip( $user_login, $user ) {
    $ip = $_SERVER['REMOTE_ADDR'];
    update_user_meta( $user->ID, 'last_login_ip', $ip );
}
  

После входа в метаполе last_login_ip будет записан IP. Это позволяет отслеживать необычные попытки входа.

// При входе пользователя 'admin' с IP 192.168.1.1
// В таблице wp_usermeta появится запись:
// user_id: 1, meta_key: 'last_login_ip', meta_value: '192.168.1.1'
  

Пример 2: Отправка приветственного письма с индивидуальным содержимым

Цель: после регистрации отправить письмо с логином и ссылкой для подтверждения email.

Пример

add_action( 'user_register', 'send_welcome_email', 10, 1 );

function send_welcome_email( $user_id ) {
    $user = get_userdata( $user_id );
    $subject = 'Добро пожаловать, ' . $user->display_name;
    $message = 'Вы зарегистрировались на нашем сайте. Ваш логин: ' . $user->user_login . "\n";
    $message .= 'Для подтверждения перейдите по ссылке: ' . home_url( '/confirm-email?key=' . md5( $user->user_email ) );
    wp_mail( $user->user_email, $subject, $message );
}
  

Здесь важно, чтобы письмо не попало в спам. Рекомендуется использовать HTML-формат и правильные заголовки.

Пример 3: Добавление пользователя в группу подписчиков после регистрации

Цель: автоматически добавлять всех новых пользователей в определённую роль (например, 'subscriber'), если регистрация произошла через форму на странице 'pro'.

Пример

add_action( 'register_new_user', 'set_user_role_based_on_referrer', 10, 1 );

function set_user_role_based_on_referrer( $user_id ) {
    $referrer = $_POST['_wp_http_referer'] ?? '';
    if ( strpos( $referrer, 'pro' ) !== false ) {
        $user = new WP_User( $user_id );
        $user->set_role( 'pro_subscriber' );
    }
}
  

Однако такая логика может быть небезопасной: рекомендуется проверять nonce и другие данные формы.

Пример 4: Использование хука wp_authenticate_pre для дополнительной проверки

Цель: заблокировать вход для определённых пользователей до аутентификации.

Пример

add_action( 'wp_authenticate_pre', 'check_banned_users', 10, 2 );

function check_banned_users( $username, $password ) {
    // Получаем пользователя по логину
    $user = get_user_by( 'login', $username );
    if ( $user && get_user_meta( $user->ID, 'banned', true ) ) {
        // Останавливаем процесс входа, возвращая ошибку
        wp_die( 'Ваш аккаунт заблокирован.' );
    }
}
  

Обратите внимание: wp_die() здесь уместно, так как это блокирующая проверка до основного потока аутентификации.

Пример 5: Создание собственного действия и его вызов с произвольными аргументами

Цель: дать возможность другим плагинам реагировать на пользовательское событие, например, когда пользователь завершает профиль.

Пример

// В вашем плагине
function do_after_profile_complete( $user_id, $profile_data ) {
    // Ваш код обработки
    do_action( 'my_plugin_profile_completed', $user_id, $profile_data );
}

// В другом плагине регистрируем обработчик
add_action( 'my_plugin_profile_completed', 'notify_admin_about_profile', 10, 2 );
function notify_admin_about_profile( $user_id, $data ) {
    $admin_email = get_option( 'admin_email' );
    wp_mail( $admin_email, 'Профиль завершён', 'Пользователь ID ' . $user_id . ' завершил профиль.' );
}
  

При вызове do_action() передаются все необходимые аргументы, которые могут быть использованы зарегистрированными функциями.

Пример 6: Использование анонимной функции с доступом к внешним переменным (use)

Цель: передать в замыкание дополнительные данные, определённые в контексте.

Пример

$plugin_option = get_option( 'my_plugin_log_level' );
add_action( 'wp_login', function( $user_login, $user ) use ( $plugin_option ) {
    if ( $plugin_option === 'debug' ) {
        error_log( 'Вход пользователя: ' . $user_login );
    }
}, 10, 2 );
  

Конструкция use позволяет замкнуть переменную из области видимости. Однако будьте осторожны: значение фиксируется при регистрации, а не при выполнении.

Регистрация действия (action) в PHP - comments

En
Action register php (php)