Как в массив добавить функцию для загрузки элементов через ajax?
Работаю с WP, возникла необходимость подгружать карточки игр при нажатии кнопки "показать все". Данные передаю стандартные и из ACF полей. Проблема возникла с передачей данных из галереи ACF. Я написал функцию, которая отлично работает и выдает нужные данные для data-gallery. Но не получается вывести в массив $json['results'][] = array эту функцию, точнее не пойму какой должен быть синтаксис и куда саму функцию в коде поставить. Пробовал разные варианты вывода в $json['results'][] = array, к примеру так:
'gameGallery' => gameGallery(),
и как вариант пробовал запихнуть функцию в переменную и добавить ее в массив. Подскажите вообщем:)
Функция которая выводит галерею, которую нужно добавить в $json['results'][] = array :
function gameGallery() { $images = get_field('gallery_game_img'); $i = 0; if($images) { foreach( $images as $image ) { $numItems = count($images); if(++$i === $numItems) { echo """ . esc_url($image['url']) . """; } else { echo """ . esc_url($image['url']) . "","; } } } } |
function gameGallery() { $images = get_field('gallery_game_img'); $i = 0; if($images) { foreach( $images as $image ) { $numItems = count($images); if(++$i === $numItems) { echo """ . esc_url($image['url']) . """; } else { echo """ . esc_url($image['url']) . "","; } } } }
Функция основная в function.php
function get_games() { $meta_q[] = array( 'key' => 'zakrep', 'value' => 'Да' ); $limit = 8111111111111111111; $exclude = array(); if(isset($_POST['exclude'])) { $exclude = explode(',',$_POST['exclude']); } // параметры по умолчанию $posts_reviews = new WP_Query( array( 'posts_per_page' => $limit, 'category' => 0, 'orderby' => 'title', 'order' => 'ASC', 'include' => array(), 'post__not_in' => $exclude, 'meta_key' => '', 'meta_value' =>'', 'post_type' => 'game-list', 'suppress_filters' => true, 'meta_query' => array( 'relation' => 'AND', $meta_q ) ) ); $posts_reviews = $posts_reviews->posts; if(count($posts_reviews)<$limit) { foreach( $posts_reviews as $post ){ $exclude[] = $post->ID; } } else { } $new_limit = $limit - count($posts_reviews); $posts_reviews_others = new WP_Query( array( 'posts_per_page' => $new_limit, 'category' => 0, 'orderby' => 'title', 'order' => 'ASC', 'include' => array(), 'post__not_in' => $exclude, 'meta_key' => '', 'meta_value' =>'', 'post_type' => 'game-list', 'suppress_filters' => true, // подавление работы фильтров изменения SQL запроса ) ); $posts_reviews_others = $posts_reviews_others->posts; $posts_reviews = array_merge($posts_reviews,$posts_reviews_others); global $post; $json = array(); $front_id = get_option('page_on_front'); $price_box = get_field('array_price', $front_id); foreach( $posts_reviews as $post ) { setup_postdata($post); $json['results'][] = array( 'post_id'=>$post->ID, 'title'=>get_the_title(), 'permalink' => get_permalink(), 'zakrep' => get_field('zakrep'), 'game_desc' => get_field('game_desc'), 'versus_game' => get_field('versus_game'), 'platform_os' => get_field('platform_os'), 'status_game' => get_field('status_game'), 'youtube_link' => get_field('youtube_link'), 'txt_basic' => $price_box['txt_basic'], 'txt_standart' => $price_box['txt_standart'], 'txt_premium' => $price_box['txt_premium'], 'txt_btn_basic' => $price_box['txt_btn_basic'], 'txt_btn_standart' => $price_box['txt_btn_standart'], 'txt_btn_premium' => $price_box['txt_btn_premium'], 'gallery_game_img' => get_field('gallery_game_img'), 'game_img_main' => get_field('game_img_main') ); } echo json_encode($json,true); die(); } |
function get_games() { $meta_q[] = array( 'key' => 'zakrep', 'value' => 'Да' ); $limit = 8111111111111111111; $exclude = array(); if(isset($_POST['exclude'])) { $exclude = explode(',',$_POST['exclude']); } // параметры по умолчанию $posts_reviews = new WP_Query( array( 'posts_per_page' => $limit, 'category' => 0, 'orderby' => 'title', 'order' => 'ASC', 'include' => array(), 'post__not_in' => $exclude, 'meta_key' => '', 'meta_value' =>'', 'post_type' => 'game-list', 'suppress_filters' => true, 'meta_query' => array( 'relation' => 'AND', $meta_q ) ) ); $posts_reviews = $posts_reviews->posts; if(count($posts_reviews)<$limit) { foreach( $posts_reviews as $post ){ $exclude[] = $post->ID; } } else { } $new_limit = $limit - count($posts_reviews); $posts_reviews_others = new WP_Query( array( 'posts_per_page' => $new_limit, 'category' => 0, 'orderby' => 'title', 'order' => 'ASC', 'include' => array(), 'post__not_in' => $exclude, 'meta_key' => '', 'meta_value' =>'', 'post_type' => 'game-list', 'suppress_filters' => true, // подавление работы фильтров изменения SQL запроса ) ); $posts_reviews_others = $posts_reviews_others->posts; $posts_reviews = array_merge($posts_reviews,$posts_reviews_others); global $post; $json = array(); $front_id = get_option('page_on_front'); $price_box = get_field('array_price', $front_id); foreach( $posts_reviews as $post ) { setup_postdata($post); $json['results'][] = array( 'post_id'=>$post->ID, 'title'=>get_the_title(), 'permalink' => get_permalink(), 'zakrep' => get_field('zakrep'), 'game_desc' => get_field('game_desc'), 'versus_game' => get_field('versus_game'), 'platform_os' => get_field('platform_os'), 'status_game' => get_field('status_game'), 'youtube_link' => get_field('youtube_link'), 'txt_basic' => $price_box['txt_basic'], 'txt_standart' => $price_box['txt_standart'], 'txt_premium' => $price_box['txt_premium'], 'txt_btn_basic' => $price_box['txt_btn_basic'], 'txt_btn_standart' => $price_box['txt_btn_standart'], 'txt_btn_premium' => $price_box['txt_btn_premium'], 'gallery_game_img' => get_field('gallery_game_img'), 'game_img_main' => get_field('game_img_main') ); } echo json_encode($json,true); die(); }
Вывожу через JS:
$.ajax({ url: '/wp-admin/admin-ajax.php', method: 'post', dataType: 'json', data: { action: 'get_games', exclude: ids }, success: function (data) { if (data['results']) { html = ''; for (i = 0; i < data['results'].length; i++) { html +=' <div data-slides="[&quot;&quot;]" id="post_id_'+data['results'][i]['post_id']+'" data-post_id="'+data['results'][i]['post_id']+'" class="games__card game" data-name="'+data['results'][i]['title']+'" data-link="'+data['results'][i]['permalink']+'" data-description="'+data['results'][i]['game_desc']+'" ' + 'data-version="'+data['results'][i]['versus_game']+'" ' + 'data-device="'+data['results'][i]['platform_os']+'" ' + 'data-assembly="'+data['results'][i]['status_game']+'"' + 'data-slides="'+data['results'][i]['gallery_game_img']+'" ' + 'data-video="'+data['results'][i]['youtube_link']+'" ' + 'data-basic_txt="'+data['results'][i]['txt_basic']+'" ' + 'data-standart_txt="'+data['results'][i]['txt_standart']+'" ' + 'data-premium_txt="'+data['results'][i]['txt_premium']+'" ' + 'data-btn_basic="'+data['results'][i]['txt_btn_basic']+'" ' + 'data-btn_standart="'+data['results'][i]['txt_btn_standart']+'" ' + 'data-btn_premium="'+data['results'][i]['txt_btn_premium']+'" ' + 'data-img="'+data['results'][i]['game_img_main']+'">n' + ' <img class="game__img" src="'+data['results'][i]['game_img_main']+'">n' + ' <h4 class="game__title">'+data['results'][i]['title']+'</h4>n' + ' <p class="game__subtitle">3 чита от 99 ₽</p>n' + ' </div>'; } $('.games__cards').append(html) //$('#games_card_ends').removeClass('load_progress') $('#get_more_games').remove() open_game_popup() } } }) } |
$.ajax({ url: '/wp-admin/admin-ajax.php', method: 'post', dataType: 'json', data: { action: 'get_games', exclude: ids }, success: function (data) { if (data['results']) { html = ''; for (i = 0; i < data['results'].length; i++) { html +=' <div data-slides="[&quot;&quot;]" id="post_id_'+data['results'][i]['post_id']+'" data-post_id="'+data['results'][i]['post_id']+'" class="games__card game" data-name="'+data['results'][i]['title']+'" data-link="'+data['results'][i]['permalink']+'" data-description="'+data['results'][i]['game_desc']+'" ' + 'data-version="'+data['results'][i]['versus_game']+'" ' + 'data-device="'+data['results'][i]['platform_os']+'" ' + 'data-assembly="'+data['results'][i]['status_game']+'"' + 'data-slides="'+data['results'][i]['gallery_game_img']+'" ' + 'data-video="'+data['results'][i]['youtube_link']+'" ' + 'data-basic_txt="'+data['results'][i]['txt_basic']+'" ' + 'data-standart_txt="'+data['results'][i]['txt_standart']+'" ' + 'data-premium_txt="'+data['results'][i]['txt_premium']+'" ' + 'data-btn_basic="'+data['results'][i]['txt_btn_basic']+'" ' + 'data-btn_standart="'+data['results'][i]['txt_btn_standart']+'" ' + 'data-btn_premium="'+data['results'][i]['txt_btn_premium']+'" ' + 'data-img="'+data['results'][i]['game_img_main']+'">n' + ' <img class="game__img" src="'+data['results'][i]['game_img_main']+'">n' + ' <h4 class="game__title">'+data['results'][i]['title']+'</h4>n' + ' <p class="game__subtitle">3 чита от 99 ₽</p>n' + ' </div>'; } $('.games__cards').append(html) //$('#games_card_ends').removeClass('load_progress') $('#get_more_games').remove() open_game_popup() } } }) }
Дополнительно:
Ответы:
Решение оказалось совсем другим
в function.php добавил
$images = array(); foreach ( get_field('gallery_game_img') as $image) { $images[] = $image['url']; } |
$images = array(); foreach ( get_field('gallery_game_img') as $image) { $images[] = $image['url']; }
Вывел в массиве стандартным образом:
'game_img_main' => get_field('game_img_main')
в JS:
html = ''; for (i = 0; i < data['results'].length; i++) { html_img = ''; if(data['results'][i]['gallery_game_img']) { //html_img = JSON.parse(data['results'][i]['gallery_game_img']); html_img = '[&quot;'+data['results'][i]['gallery_game_img'].join('&quot;,&quot;')+'&quot;]'; console.log(html_img) } |
html = ''; for (i = 0; i < data['results'].length; i++) { html_img = ''; if(data['results'][i]['gallery_game_img']) { //html_img = JSON.parse(data['results'][i]['gallery_game_img']); html_img = '[&quot;'+data['results'][i]['gallery_game_img'].join('&quot;,&quot;')+'&quot;]'; console.log(html_img) }
Вывод:
data-slides="'+html_img+'"
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Если нужно через AJAX подгружать элементы и “добавить функцию в массив”, в WordPress лучше разделить задачу на две части: PHP-обработчик возвращает HTML/JSON, а JavaScript отправляет запрос и вставляет результат в DOM. Не смешивайте SQL, HTML и JS в одном куске кода.
PHP-обработчик:
add_action('wp_ajax_load_more_items', 'wt_load_more_items'); add_action('wp_ajax_nopriv_load_more_items', 'wt_load_more_items'); function wt_load_more_items() { check_ajax_referer('load_more_items', 'nonce'); $page = max(1, (int) ($_POST['page'] ?? 1)); $query = new WP_Query([ 'post_type' => 'post', 'post_status' => 'publish', 'paged' => $page, 'posts_per_page' => 6, ]); ob_start(); while ($query->have_posts()) { $query->the_post(); get_template_part('template-parts/card'); } wp_reset_postdata(); wp_send_json_success([ 'html' => ob_get_clean(), 'has_more' => $page < $query->max_num_pages, ]); }
Передайте данные в JS:
wp_localize_script('theme-main', 'LoadMoreData', [ 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('load_more_items'), ]);
JS:
let page = 1; document.querySelector('.js-load-more').addEventListener('click', async function () { page++; const formData = new FormData(); formData.append('action', 'load_more_items'); formData.append('nonce', LoadMoreData.nonce); formData.append('page', page); const response = await fetch(LoadMoreData.ajaxUrl, { method: 'POST', body: formData }); const result = await response.json(); if (result.success) { document.querySelector('.items-list').insertAdjacentHTML('beforeend', result.data.html); if (!result.data.has_more) { this.remove(); } } });let page = 1; document.querySelector('.js-load-more').addEventListener('click', async function () { page++; const formData = new FormData(); formData.append('action', 'load_more_items'); formData.append('nonce', LoadMoreData.nonce); formData.append('page', page); const response = await fetch(LoadMoreData.ajaxUrl, { method: 'POST', body: formData }); const result = await response.json(); if (result.success) { document.querySelector('.items-list').insertAdjacentHTML('beforeend', result.data.html); if (!result.data.has_more) { this.remove(); } } });
Если под “массивом” Вы имеете в виду массив callback-функций, то в PHP можно хранить имена функций и вызывать их через
call_user_func(), но для AJAX-загрузки это обычно не нужно. В WordPress нормальная точка входа — action handler.Не пишите прямой SQL, если можно использовать
WP_Query. Так Вы получите корректные статусы, кэш, фильтры, таксономии и совместимость с плагинами.Если подгружаются видео YouTube или другие внешние элементы, не передавайте в JSON весь произвольный HTML от пользователя без очистки. На сервере формируйте карточку через шаблон, а в JSON отдавайте уже готовый безопасный HTML. Если всё-таки отдаёте массив данных, экранируйте значения при вставке в DOM и не используйте
innerHTMLдля непроверенных строк.Также добавьте обработку ошибок: блокировку кнопки на время запроса, сообщение при пустом ответе и проверку
result.success. Иначе пользователь сможет нажать кнопку несколько раз подряд, получить дубли карточек или не понять, почему загрузка остановилась. Для пагинации храните текущую страницу в JS, а на сервере возвращайте флагhas_more.