Вызов внешнего API и создание глобальной переменной для любого посетителя страницы, страницы-начальной, страницы, одиночной и т.д.

Вопрос или проблема

Я совершенно нов в мире WordPress, поэтому извините, если мой вопрос не совсем ясен вам…

Я хотел реализовать следующий сценарий для своего веб-сайта. Задача заключалась в том, чтобы вызвать внешний API и получить некоторые данные, которые зависят от посетителя.

Сначала я добавил пользовательскую функцию с помощью add_action('init','имя_функции',1), которую я определил в functions.php

Я устанавливал данные API как глобальные и использовал их в нужном месте сайта с успехом. Но после проверки использования кредитов я обнаружил, что functions.php выполняется несколько раз для одной страницы.

После добавления error_log(debug_backtrace()[1]['file']) в functions.php было показано, что файл functions.php вызывается несколько раз, что происходит из-за строки wp-confing.php: require_once( ABSPATH . 'wp-settings.php' );

Для временного решения я отключил add_action('init'....) и добавил выполнение функции для каждого типа страницы (страница-главная, одиночная и т.д.), но, насколько я понимаю, это не правильное решение.

Код, который я использовал:

    add_action('init',имя_функции,1);
    function имя_функции(){
       global $data;
       //пробовал с !isset(), но так как functions.php 
       //вызывается несколько раз, это не сработает и кредиты будут использоваться
       // Вызов API
       $data_api= $api_object->value1;
    }

Поэтому мои вопросы:

  1. Почему functions.php темы загружается так много раз? На что мне стоит обратить внимание?
  2. Какой правильный способ реализовать описанный мной сценарий? Выполнить функцию один раз, когда пользователь/посетитель входит на сайт, а затем использовать либо глобальную, либо сессионную переменную?

Почему functions.php темы загружается так много раз? На что мне стоит обратить внимание?

На самом деле это не так, так WP темы не работают. Если вы вручную загружаете functions.php, тогда это и есть причина, но вы не должны этого делать.

WP загружает functions.php один раз на каждый HTTP запрос. Имейте в виду, что браузер может делать несколько запросов. Например, он может загрузить страницу, а затем сделать AJAX запросы на JavaScript. Если вы загружаете сайт, и сайт делает 5 AJAX вызовов, это 6 запросов, а не 1, так что functions.php и WP загружаются 6 раз.

Единственная другая причина, о которой я могу подумать, это то, что вы изменили сам WordPress, чтобы получить желаемые изменения, никогда не делайте этого. Используйте темы, плагины, действия и фильтры, чтобы изменить поведение WordPress.

Какой правильный способ реализовать описанный мной сценарий? Выполнить функцию один раз, когда пользователь/посетитель входит на сайт.

Вам нужно оставить какой-то индикатор, что посетитель уже был здесь раньше, то есть куки.

Я отделил последнюю часть этого вопроса в отдельный пункт, так как это предполагает, что у вас есть фундаментальное непонимание того, как работают программы на PHP.

и затем использовать либо глобальную, либо сессионную переменную.

Сессия PHP — это плохая идея, так как она все равно включает куки на стороне пользователя, поэтому она не обходит законы о куки. Она также не будет работать на многих хостингах, так как они либо отключат это, либо их кэширование и оптимизации будут несовместимы.

Итак, почему бы не использовать глобальную переменную?

Потому что это не то, как работает PHP. Программы на PHP не похожи на Node или Java CMS, которые работают в фоновом режиме. Нет постоянной программы.

Каждый раз, когда вы делаете запрос, создается процесс PHP, с нуля, каждый запрос — это чистый лист. Никакие переменные, которые вы храните в PHP, не будут доступны, и все файлы загружаются.

WordPress пытается смягчить это, будучи умным в том, как он загружает вещи из базы данных, предоставляя API для постоянного хранения и т. д. Если у вас есть сервер memcached или Redis, вы можете установить кэш объектов, который может значительно повысить производительность, но вы не можете просто объявить переменную и ожидать, что она сохранит свое значение при следующей загрузке страницы. В конце запроса программа завершается, все очищается.

Так что такое global переменные в PHP?

Ключевое слово global — это способ сделать переменную доступной повсеместно без какой-либо структуры. Это грубый способ вытащить что-то из ниоткуда, что может вызвать множество проблем. Это не просто функция приложений на PHP, бедствие глобального состояния известно во многих языках программирования. Посмотрите лекции Google о чистом коде на тему глобального состояния, чтобы узнать о ужасах и опасностях.

Вы также заметите, что некоторые разработчики WP являются большими поклонниками “одиночек”. Это когда они берут вещи и помещают их в класс, чтобы это выглядело как объектно-ориентированное, но это не так. Затем они дают ему статический метод, чтобы получить к нему доступ откуда угодно, как к global переменной. Это известный антипаттерн и плохая практика.

Так что же вам делать?

Это зависит от того, что именно вы делаете, ваш вопрос очень слабо детализирован.

Если вы хотите знать, заходил ли пользователь на сайт ранее:

  • установите куки, если куки не установлены
  • если куки не установлены, значит, они никогда не были здесь раньше
  • если куки были установлены, значит, это не первый раз, когда они посещают сайт

Ничего из этого не относится к WordPress, тот же ответ будет и для всех CMS и языков.

Имейте в виду, что это не надежно, любой может:

  • посетить в инкогнито режиме
  • отключить куки в своем браузере
  • отправить запрос по GDPR с требованием удалить все данные о них
  • использовать устройство другого человека
  • использовать другой браузер

Что касается выполнения удаленного API запроса:

  • Не делайте это на PHP на фронтэнде, это сделает ваш сайт очень медленным, так как ему нужно ждать удаленного сервера, прежде чем он сможет ответить пользователю со страницей
    • ожидайте значительного ухудшения SEO в результате
  • Делайте это на JavaScript. Так работает Google Analytics.
    • Это открывает дополнительные возможности для проверки, был ли пользователь на сайте раньше, например, проверка localStorage вместо использования куки
    • Это значительно быстрее, сервер никогда не сможет достигнуть этой скорости, если все сделано правильно
    • Фронтенд JavaScript не обязательно должен иметь какое-либо отношение к WordPress, так что вам не нужно ограничивать свои исследования или помощь только WP

Ответ или решение

Вопрос:

Как реализовать единовременный вызов внешнего API и создание глобальной переменной для посетителей страниц (например, для page-home, single и других) в WordPress?

Ответ:

Добрый день!

Понимаю, что вы только начинаете свои шаги в мир WordPress, и ваш вопрос связан с вызовом внешнего API и сохранением его данных для дальнейшего использования. Давайте разберем ваши вопросы подробно.

1. Почему файл functions.php загружается несколько раз?

Файл functions.php загружается только один раз на каждый HTTP-запрос. Если ваш сайт делает несколько запросов (например, для AJAX, изображений или стилей), то каждый из этих запросов может инициировать новый процесс PHP, что приведет к тому, что функции будут загружены повторно.

Если у вас есть add_action() в functions.php, этот код будет выполняться каждый раз, когда происходит инициирование.

Способы устранения проблемы:

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

2. Как правильно реализовать внешний вызов API и использование глобальных или сессионных переменных?

Рекомендации:
  1. Создание переменной на основе куки:

    • Используйте куки, чтобы определить, посещал ли посетитель ваш сайт ранее. Вы можете установить cookie при первом посещении страницы, а затем использовать его для определения, стоит ли делать API запрос.
    • Пример кода:
    add_action('init', 'check_api_call');
    
    function check_api_call() {
       global $data;
       if (!isset($_COOKIE['api_called'])) {
           // Вызов внешнего API
           $data_api = external_api_call(); // Замените на вашу функцию вызова API
           setcookie('api_called', '1', time() + 3600); // Устанавливаем куку на 1 час
    
           // Сохраняем данные
           $data = $data_api; 
       }
    }
    
    function external_api_call() {
       // Ваш код для обращения к API
       // Например, используйте wp_remote_get()
       return $api_response; // Полученные данные
    }
  2. Использование AJAX для нового подхода:

    • Рекомендуется реализовать вызов API через AJAX. Это позволяет избежать блокировки загрузки страницы и повысит скорость, так как запрос будет выполняться асинхронно.

    Пример использования AJAX:

    jQuery(document).ready(function($) {
       if (!document.cookie.split(';').some((item) => item.trim().startsWith('api_called='))) {
           $.post(myajax.ajaxurl, { action: 'fetch_api_data' }, function(data) {
               console.log(data); // Ответ от сервера
               document.cookie = "api_called=1; path=/"; // Устанавливаем куку
           });
       }
    });

    В вашем functions.php добавьте обработчик:

    add_action('wp_ajax_fetch_api_data', 'handle_api_request');
    add_action('wp_ajax_nopriv_fetch_api_data', 'handle_api_request');
    
    function handle_api_request() {
       // Ваш код для обращения к API
       $response = external_api_call(); // Вызов API
       wp_send_json_success($response); // Отправляем успешный ответ
       wp_die(); // Завершаем обработку
    }

Заключение:

Используя куки или AJAX, вы сможете эффективно управлять вызовами API на вашем сайте WordPress. Это позволит значительно уменьшить количество вызовов API, оптимизировать работу вашего сайта и минимизировать потребление ваших тарифов. Также, помните об этических аспектах использования данных, особенно учитывая требования законодательства о защите данных. Если у вас есть дополнительные вопросы или необходимо более детальное объяснение какого-либо момента, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...