Вызов метода из functions.php при клике на кнопку

6 июл. 2019 г., 06:47:21
Просмотры: 16.6K
Голосов: 1

Я работаю над проектом, где мне нужно вызвать метод (который принимает 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 закомментировано. Это именно тот код, который был сгенерирован, я ничего не редактировал.

2
Комментарии

Вы пытаетесь обновить метаданные без перезагрузки текущей страницы? Как насчёт того, чтобы просто отправить форму на эту же страницу и обновить метаданные при её загрузке?

Sally CJ Sally CJ
8 июл. 2019 г. 18:22:54

Да, я пытаюсь обновить метаданные. Не могли бы вы предоставить какое-то решение того, о чём вы говорите? Это было бы замечательно.

Subham Subham
8 июл. 2019 г. 18:38:23
Все ответы на вопрос 2
0

Вы можете использовать AJAX, если не хотите перезагружать текущую страницу — например, при нажатии кнопки "Принять" отправить AJAX-запрос для обновления метаданных пользователя, не покидая текущую страницу.

Однако решение, которое я предлагаю, не использует AJAX; вместо этого мы просто отправляем форму (устанавливаем значение атрибута action) на главную страницу, а затем используем хук template_redirect для обновления метаданных (и перенаправляем обратно на предыдущую или реферерную страницу).

Шаги реализации

  1. Измените тег 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>
    
  2. Добавьте этот код в файл темы 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' );
    

    Примечания:

    1. Значение Gdpr в условии 'Gdpr' !== $_POST['accept'] должно совпадать со значением value="Gdpr" в теге <input name="accept" type="checkbox" value="Gdpr" required /> выше.

    2. Обязательно замените META_KEY на реальный ключ метаданных.

    3. Я предполагаю, что принятие GDPR предназначено только для авторизованных пользователей, поэтому в коде/функции выше используются is_user_logged_in() и get_current_user_id().

ОБНОВЛЕНИЕ

Функция wp_safe_redirect() не сработала у автора вопроса, поэтому он использовал wp_redirect().

9 июл. 2019 г. 06:05:03
13

Вам понадобится использовать 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 );

Надеюсь, это решит вашу проблему.
Я не тестировал код, но он должен работать.
Дайте мне знать после тестирования.

6 июл. 2019 г. 22:04:54
Комментарии

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

Subham Subham
7 июл. 2019 г. 07:31:46

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

Subham Subham
7 июл. 2019 г. 07:52:48

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

LebCit LebCit
7 июл. 2019 г. 11:12:37

В консоли отображается как "null" для call-php.js

Subham Subham
7 июл. 2019 г. 11:38:32

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

LebCit LebCit
7 июл. 2019 г. 11:43:49

да, @LebCit. Он скрывается.

Subham Subham
7 июл. 2019 г. 11:44:56

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

LebCit LebCit
7 июл. 2019 г. 11:49:02

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

Subham Subham
7 июл. 2019 г. 16:58:35

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

Subham Subham
7 июл. 2019 г. 17:36:32

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

LebCit LebCit
7 июл. 2019 г. 17:48:10

Да, я так и сделал. Я заменил 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' ), но лог всё равно пустой.

Subham Subham
7 июл. 2019 г. 17:51:40

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

LebCit LebCit
7 июл. 2019 г. 20:31:43

Что вы имели в виду под "неправильным вызовом действия в вашей php-функции"? Моя функция в functions.php точно такая же, как и в моем вопросе.

Subham Subham
7 июл. 2019 г. 20:41:27
Показать остальные 8 комментариев