Вызов метода из functions.php при клике на кнопку
Я работаю над проектом, где мне нужно вызвать метод (который принимает ID пользователя) при клике на кнопку подтверждения (Accept).
Я перепробовал разные способы, но основная сложность заключается в том, как получить ID пользователя на фронтенде и передать его в метод.
Мой метод обновляет метаданные конкретного пользователя.
HTML код:
<div id="modal">
<div class="modalconent">
<h3 align=center>GDPR</h3>
<p>Это всплывающее окно GDPR</p><br><br><br>
<form>
<input name="accept" type="checkbox" value="Gdpr" required/>Я принимаю GDPR
<input type="submit" id="accept-button" value="Принять">
</form>
</div>
</div>
<script>
window.onload = function () {
document.getElementById('accept-button').onclick = function () {
document.getElementById('modal').style.display = "none"
};
};
</script>
Сейчас моя кнопка "Принять" просто скрывает модальное окно. Мне нужно вызвать метод вместе с display:none.
Мой PHP код:
function updateHasReadFlag($user) {
// Добавлена поддержка использования функции как с ID пользователя, так и с объектом пользователя
if ( $user && is_int( $user ) ) {
$user_id = $user;
} else if ( ! empty( $user->ID ) ) {
$user_id = $user->ID;
} else {
return;
}
return update_user_meta( $user_id, 'META_KEY', true );
}
Сгенерированный код формы:
<form method="post" action="<?php echo esc_url( home_url() ); ?>">
<input name="accept" type="checkbox" value="Gdpr" required=""> Я принимаю GDPR
<input type="submit" id="accept-button" value="Принять">
<!--?php wp_nonce_field( 'accept-gdpr', 'accept_gdpr_nonce' ); ?-->
</form>
Я не понимаю, почему поле nonce закомментировано. Это именно тот код, который был сгенерирован, я ничего не редактировал.

Вы можете использовать AJAX, если не хотите перезагружать текущую страницу — например, при нажатии кнопки "Принять" отправить AJAX-запрос для обновления метаданных пользователя, не покидая текущую страницу.
Однако решение, которое я предлагаю, не использует AJAX; вместо этого мы просто отправляем форму (устанавливаем значение атрибута action
) на главную страницу, а затем используем хук template_redirect
для обновления метаданных (и перенаправляем обратно на предыдущую или реферерную страницу).
Шаги реализации
Измените тег
form
на:<form method="post" action="<?php echo esc_url( home_url() ); ?>">
и добавьте это поле nonce:
<?php wp_nonce_field( 'accept-gdpr', 'accept_gdpr_nonce' ); ?>
Теперь ваша форма выглядит так:
<form method="post" action="<?php echo esc_url( home_url() ); ?>"> <input name="accept" type="checkbox" value="Gdpr" required /> Я принимаю условия GDPR <input type="submit" id="accept-button" value="Принять" /> <?php wp_nonce_field( 'accept-gdpr', 'accept_gdpr_nonce' ); ?> </form>
Добавьте этот код в файл темы
functions.php
:function accept_gdpr() { // Проверяем, авторизован ли пользователь. if ( ! is_user_logged_in() ) { return; } // Проверяем наличие всех необходимых данных. if ( empty( $_POST['accept_gdpr_nonce'] ) || empty( $_POST['accept'] ) || 'Gdpr' !== $_POST['accept'] ) { return; } // Проверяем nonce. if ( ! wp_verify_nonce( $_POST['accept_gdpr_nonce'], 'accept-gdpr' ) ) { return; } // Обновляем метаданные. update_user_meta( get_current_user_id(), 'META_KEY', '1' ); // Перенаправляем обратно на предыдущую страницу. wp_safe_redirect( wp_get_referer() ); exit; } add_action( 'template_redirect', 'accept_gdpr' );
Примечания:
Значение
Gdpr
в условии'Gdpr' !== $_POST['accept']
должно совпадать со значениемvalue="Gdpr"
в теге<input name="accept" type="checkbox" value="Gdpr" required />
выше.Обязательно замените
META_KEY
на реальный ключ метаданных.Я предполагаю, что принятие GDPR предназначено только для авторизованных пользователей, поэтому в коде/функции выше используются
is_user_logged_in()
иget_current_user_id()
.
ОБНОВЛЕНИЕ
Функция wp_safe_redirect()
не сработала у автора вопроса, поэтому он использовал wp_redirect()
.

Вам понадобится использовать wp_localize_script(), также доступную здесь.
Коротко: это способ WordPress вызывать PHP
в JS
.
Итак, вы можете сделать следующее.
ПЕРВОЕ: создайте папку js
в корне вашей темы, на том же уровне, что и style.css, если её ещё нет. Затем в этой папке js
создайте файл call-php.js
. Вы можете назвать его как угодно, главное, чтобы это был файл с расширением .js
.
В вашем файле functions.php, после функции function updateHasReadFlag($user)
, добавьте:
/**
* Подключение JS кода.
*/
function call_php_in_js() {
wp_enqueue_script( 'call-php-in-js', get_template_directory_uri() . '/js/call-php.js', array( 'jquery' ), filemtime( get_theme_file_path( '/js/call-php.js' ) ), true );
$php_to_js = array(
'my_php_function' => updateHasReadFlag( $user ),
);
wp_localize_script( 'call-php-in-js', 'object_name', $php_to_js );
}
add_action( 'wp_enqueue_scripts', 'call_php_in_js' );
ВТОРОЕ: в файле call-php.js
добавьте:
( function( $ ) {
$( "#accept-button" ).click( function( e ) {
e.preventDefault();
$( "#modal" ).hide();
object_name.my_php_function;
});
} )( jQuery );
Надеюсь, это решит вашу проблему.
Я не тестировал код, но он должен работать.
Дайте мне знать после тестирования.

спасибо за ответ. Я ценю это. Но почему-то это не работает. Моя функция function updateHasReadFlag($user)
не вызывается. Или, может быть, она вызывается, но update_user_meta( $user_id, 'META_KEY', true );
по какой-то причине не работает. Можете проверить? Я также удалил <script>
</script>
из моего HTML-кода.

Спрашиваю, чтобы подтвердить: моя функция function updateHasReadFlag($user)
принимает userID или объект пользователя в качестве параметра, чтобы обновить метаданные конкретного пользователя. Передаем ли мы этот параметр при вызове функции function updateHasReadFlag($user)
?

Не могли бы вы заменить object_name.my_php_function;
на console.log(object_name.my_php_function);
и сказать, что вы видите в консоли? Просто чтобы узнать: скрывается ли #modal
при клике на #accept-button
с использованием моего ответа?

скрывается ли #modal
при клике на #accept-button
с использованием моего ответа?

Не могли бы вы использовать BugFu Console Debugger в вашей функции function updateHasReadFlag($user)
, чтобы увидеть точный вывод, работает ли она... Сообщите мне, когда вы это сделаете, я думаю, что вы поймёте, в чём проблема.

Я использовал BugFu debugger. my_php_function
возвращает null. Вот что я обнаружил.

Кажется, я нашёл проблему. Мой php-код updateHasReadFlag($user)
находится в дочерней теме, тогда как call-php.js
— в родительской теме. get_template_directory_uri()
указывает на родительскую тему. Я подумал, что, возможно, поэтому my_php_function
возвращает null. Но теперь я перенаправил всё на дочернюю тему, а my_php_function
всё равно возвращает null.

Всё вышеперечисленное нужно делать ТОЛЬКО в дочерней теме !!! Таким образом, ваша функция должна быть помещена в functions.php дочерней темы, и все шаги из моего ответа должны применяться в дочерней теме.

Да, я так и сделал. Я заменил get_template_directory_uri()
на get_stylesheet_directory_uri()
и filemtime( get_theme_file_path( '/js/call-php.js' )
на filemtime( get_stylesheet_directory( '/js/call-php.js' )
, но лог всё равно пустой.

Используйте код как указано! filemtime( get_stylesheet_directory( '/js/call-php.js' )
— это неправильно! Если вы хотите изменить это, должно быть filemtime( get_stylesheet_directory() . '/js/call-php.js' )
. Проверьте Справочник по коду перед внесением изменений. Думаю, вы неправильно вызываете действие в вашей PHP-функции.
