Вопрос или проблема
Я следовал и создал метабокс, используя весь код из этого вопроса:
Создавать больше метабоксов по мере необходимости
По сути, только два поля создаются, когда вы нажимаете кнопку «Добавить трек»:
Поле названия песни – Поле номера трека
Но мне нужно что-то вроде этого:
Кнопка добавления названия альбома – добавляет поле для названия альбома;
Кнопка добавления номера трека – добавляет поле для номера трека;
Это мой код на данный момент:
add_action( 'add_meta_boxes', array( $this, 'dynamic_add_custom_box' ) );
/* Делает что-то с введенными данными */
add_action( 'save_post', array( $this, 'dynamic_save_postdata' ) );
Второй блок:
/* Добавляет боковое меню на экранах редактирования сообщений и страниц */
function dynamic_add_custom_box() {
add_meta_box(
'dynamic_sectionid',
__( 'Мои Альбомы', 'myplugin_textdomain' ),
array( $this,'dynamic_inner_custom_box'),
'post',
'normal',
'high');
}
Третий блок:
/* Печатает содержимое бокса */
function dynamic_inner_custom_box() {
global $post;
// Используйте nonce для проверки
wp_nonce_field( plugin_basename( __FILE__ ), 'dynamicMeta_noncename' );
?>
<div id="meta_inner">
<?php
// получаем сохранённые метаданные в виде массива
$albums = get_post_meta( $post->ID, 'album', true );
$c = 0;
if ( count( $albums ) > 0 ) {
foreach( $albums as $album ) {
if ( isset( $album['title'] ) || isset( $album['track'] ) ) {
printf( '<p>Название альбома <input type="text" name="album[%1$s]Create Meta boxes dynamically
" value="%2$s" /> -- Номер трека: <input type="text" name="album[%1$s][track]" value="%3$s" /><span class="removealbum">%4$s</span></p>', $c, $album['title'], $album['track'], __( 'Удалить Альбом' ) );
$c = $c +1;
}
}
}
?>
<span id="here"></span>
<span class="button addalbum"><?php _e('Добавить Альбом'); ?></span>
<span class="button addtracks"><?php _e('Добавить Треки'); ?></span>
<script>
var $ =jQuery.noConflict();
$(document).ready(function() {
var count = <?php echo $c; ?>;
$(".addalbum").click(function() {
count = count + 1;
$('#here').append('<p> Название альбома <input type="text" name="album['+count+']Create Meta boxes dynamically
" value="" /><span class="removealbum">Удалить Альбом</span></p>' );
return false;
});
$(".addtracks").click(function() {
count = count + 1;
$('#here').append('<p> Номер трека: <input type="text" name="album['+count+'][track]" value="" /><span class="removetrack">Удалить Трек</span></p>' );
return false;
});
$(".removealbum").live('click', function() {
$(this).parent().remove();
});
$(".removetrack").live('click', function() {
$(this).parent().remove();
});
});
</script>
</div>
<?php }
Последний блок:
/* Когда сообщение сохраняется, сохраняет наши пользовательские данные */
function dynamic_save_postdata( $post_id ) {
// проверить, является ли это рутинной автоматической сохранения.
// Если это так, наша форма не была отправлена, поэтому нам ничего не нужно делать
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
// проверить, что это пришло с нашего экрана и с правильной авторизацией,
// потому что save_post может быть вызван и в другие моменты
if ( !isset( $_POST['dynamicMeta_noncename'] ) )
return;
if ( !wp_verify_nonce( $_POST['dynamicMeta_noncename'], plugin_basename( __FILE__ ) ) )
return;
// ОК, мы аутентифицированы: нам нужно найти и сохранить данные
$songs = $_POST['album'];
update_post_meta( $post_id, 'album', $songs );
}
Перед сохранением чего-либо:
album NULL
Ключ метаданных & значение метаданных в порядке;
После сохранения чего-либо:
Значение метаданных – они в другой группе массива. Невозможно соотнести, какой альбом связан с каждым номером трека.
album 'a:2:{i:2;a:1:{s:5:"title";s:22:"Anjunabeats Volume Six";}i:3;a:1:{s:5:"track";s:1:"5";}}'
Что мне нужно, так это это:
Album[0]
Track number [0]
Track number [1]
Album[1]
Track number [0]
Track number [1]
Track number [2]
Album[2]
Track number [0]
Я пробовал много способов, но я застрял 🙁
Любая идея будет полезной.
Как насчет использования подходящего фреймворка метабоксов для вашего проекта? Я уверен, что это не единственный метабокс, который вы будете использовать.
Я рекомендую вам https://metabox.io/meta-box/ – я использовал его во многих своих проектах, и у него есть функции для динамических полей.
С Новым годом!
Ответ или решение
Чтобы динамически создавать метабоксы в WordPress, которые будут соответствовать вашим требованиям (возможность добавления нескольких альбомов с треками для каждого альбома), вам нужно изменить вашу текущую реализацию. Ваша проблема заключается в том, что вы сохраняете данные неправильно, и поэтому они не связываются должным образом. Давайте разберем это по шагам и исправим код.
-
Создание структуры метабокса: Ваша функция
dynamic_inner_custom_box
должна позволять вам добавлять как имя альбома, так и треки, которые к нему относятся. -
Сохранение данных: Вам нужно будет изменить способ, которым данные сохраняются, чтобы каждый альбом имел свой массив треков.
Вот исправленный код:
Шаг 1: Изменение метабокса
function dynamic_inner_custom_box() {
global $post;
wp_nonce_field(plugin_basename(__FILE__), 'dynamicMeta_noncename');
// Получаем сохраненные данные
$albums = get_post_meta($post->ID, 'albums', true);
$c = 0;
if ( !is_array($albums) ) {
$albums = [];
}
echo '<div id="meta_inner">';
foreach ($albums as $album) {
printf('<p>Album name <input type="text" name="albums[%1$s]Create Meta boxes dynamically" value="%2$s" /> -- Track numbers: <span class="track_numbers" data-album-index="%1$s">', $c, esc_attr($album['title']));
if (isset($album['tracks']) && is_array($album['tracks'])) {
foreach ($album['tracks'] as $track) {
printf('<input type="text" name="albums[%1$s][tracks][]" value="%2$s" />', $c, esc_attr($track));
}
}
echo '<span class="removealbum">Remove Album</span></p>';
$c++;
}
echo '<span id="here"></span>';
echo '<span class="button addalbum">Add Album</span>';
echo '</div>';
// Добавление JavaScript
?>
<script>
var $ = jQuery.noConflict();
$(document).ready(function() {
var count = <?php echo $c; ?>;
$(".addalbum").click(function() {
var albumHtml = '<p>Album name <input type="text" name="albums[' + count + ']Create Meta boxes dynamically" value="" /> -- Track numbers: <span class="track_numbers" data-album-index="' + count + '">';
albumHtml += '<input type="text" name="albums[' + count + '][tracks][]" value="" />';
albumHtml += '<span class="removetrack">Remove Track</span></span>';
albumHtml += '<span class="removealbum">Remove Album</span></p>';
$('#here').append(albumHtml);
count++;
return false;
});
$(document).on('click', '.removealbum', function() {
$(this).parent().remove();
});
$(document).on('click', '.removetrack', function() {
$(this).parent().remove();
});
});
</script>
<?php
}
Шаг 2: Сохранение данных
Измените метод dynamic_save_postdata
, чтобы он корректно сохранял данные в нужной структуре:
function dynamic_save_postdata($post_id) {
// Проверка на автосохранение
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
// Проверка nonce
if (!isset($_POST['dynamicMeta_noncename']) || !wp_verify_nonce($_POST['dynamicMeta_noncename'], plugin_basename(__FILE__))) return;
// Сохранение данных
if (isset($_POST['albums'])) {
update_post_meta($post_id, 'albums', $_POST['albums']);
}
}
Итог
Теперь структура данных сохранится в том виде, который вам нужен:
Album[0]
Track number [0]
Track number [1]
Album[1]
Track number [0]
Track number [1]
Track number [2]
Album[2]
Track number [0]
Проверьте, чтобы JavaScript и обработка событий были правильно интегрированы в WordPress, чтобы не возникло конфликтов с другими библиотеками или плагинами. Убедитесь, что все используемые функции, такие как wp_nonce_field
и add_action
, правильно подключены к вашим методам.
Этот подход обеспечит вам динамическое добавление альбомов и треков в WordPress метабоксах, при этом все связи будут корректно сохраняться.