Вопрос или проблема
Я создал meta-box
, который предоставляет функцию загрузки через стандартный загрузчик медиа из WordPress.
Это работает хорошо, пока у меня есть один вариант загрузки.
Но угадайте что? Я хочу еще один.
Если я это сделаю, то медиабокс открывается, и я могу выбрать изображение. Проблема в том, что оба input
-поля заполнены URL-адресом изображения.
Я хотел бы иметь возможность добавлять несколько вариантов выбора для загрузки изображений и, предпочтительно, использовать один скрипт.
Вот скрипт (вывод):
function dynamic_meta_callback( $post ) {
wp_nonce_field( basename( __FILE__ ), 'dynamic_nonce' );
$dsm = get_post_meta( $post->ID );
$post = get_post($post_id, ARRAY_A);
$pn = $post['post_name'];
$a="_".$pn.'_1';
$b = '_'.$pn.'_2';
?>
<div class="image_large" style="background-image: url(<?php echo $dsm['dynamic-image'.$a.''][0] ?>); background-repeat: no-repeat;">
<p><strong>Изображение 1</strong></p>
<p>
<label for="dynamic-image" class="dynamic-row-title"><?php _e( 'Изображение 1', 'dynamic-textdomain' )?></label>
<input type="text" name="dynamic-image<?php echo $a; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$a.''] ) ) echo $dsm['dynamic-image'.$a.''][0]; ?>" />
<input type="button" class="dynamic-image-button" class="button" value="<?php _e( 'Выбрать или Загрузить', 'dynamic-textdomain' )?>" />
</p>
</div>
<div class="image_large" style="background-image: url(<?php echo $dsm['dynamic-image'.$b.''][0] ?>); background-repeat: no-repeat;">
<p><strong>Изображение 2</strong></p>
<p>
<label for="dynamic-image" class="dynamic-row-title"><?php _e( 'Изображение 2', 'dynamic-textdomain' )?></label>
<input type="text" name="dynamic-image<?php echo $b; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$b.''] ) ) echo $dsm['dynamic-image'.$b.''][0]; ?>" />
<input type="button" class="dynamic-image-button" class="button" value="<?php _e( 'Выбрать или Загрузить', 'dynamic-textdomain' )?>" />
</p>
</div>
<?php
}
Вот функция сохранения
function dynamic_meta_save( $post_id ) {
$post = get_post($post_id, ARRAY_A);
$pn = $post['post_name'];
$a="_".$pn.'_1';
$b = '_'.$pn.'_2';
// Проверяет статус сохранения
$is_autosave = wp_is_post_autosave( $post_id );
$is_revision = wp_is_post_revision( $post_id );
$is_valid_nonce = ( isset( $_POST[ 'dynamic_nonce' ] ) && wp_verify_nonce( $_POST[ 'dynamic_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false';
// Выходит из скрипта в зависимости от статуса сохранения
if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
return;
}
// Проверяет ввод и очищает/сохраняет при необходимости
// Проверяет ввод и сохраняет при необходимости
if( isset( $_POST[ 'dynamic-image'.$a.'' ] ) ) { update_post_meta( $post_id, 'dynamic-image'.$a.'', $_POST[ 'dynamic-image'.$a.'' ] );}
if( isset( $_POST[ 'dynamic-image'.$b.'' ] ) ) { update_post_meta( $post_id, 'dynamic-image'.$b.'', $_POST[ 'dynamic-image'.$b.'' ] );}
}
add_action( 'save_post', 'dynamic_meta_save' );
А вот функция, которая вызывает внешний js
и передает данные
function dynamic_image_enqueue() { global $typenow;
$post = get_post($post_id, ARRAY_A);
if( $typenow == 'page' ) { wp_enqueue_media();
wp_register_script( 'dynamic-box-image', plugin_dir_url( __FILE__ ) . 'dynamic-box-image.js', array( 'jquery' ) );
wp_localize_script( 'dynamic-box-image', 'meta_image',
array('title' => __( 'Выбрать или Загрузить', 'dynamic-textdomain' ),
'button' => __( 'Использовать это изображение', 'dynamic-textdomain' ),
));
wp_enqueue_script( 'dynamic-box-image' ); }}
add_action( 'admin_enqueue_scripts', 'dynamic_image_enqueue' );
}
Вот как выглядит внешний js
jQuery(document).ready(function($){
// Инициализирует переменную, которая хранит кадр медиабиблиотеки.
var meta_image_frame;
// Запускается, когда нажата кнопка изображения.
$('.dynamic-image-button').click(function(e){
// Предотвращает выполнение действия по умолчанию.
e.preventDefault();
// Если кадр уже существует, переоткройте его.
if ( meta_image_frame ) { meta_image_frame.open(); return;}
// Настраивает кадр библиотеки медиа
meta_image_frame = wp.media.frames.meta_image_frame = wp.media({title: meta_image.title,button: { text: meta_image.button },library: { type: 'image' }});
// Запускается, когда изображение выбрано.
meta_image_frame.on('select', function(){ var media_attachment = meta_image_frame.state().get('selection').first().toJSON();
$('.dynamic-image').val(media_attachment.url); });
// Открывает кадр библиотеки медиа.
meta_image_frame.open();
});
});
Надеюсь, кто-то сможет мне помочь!
———— ОБНОВЛЕНИЕ ————
Я пытался дать кнопке ввода уникальное значение и передать это значение во внешний .js
. Выяснил, что мне нужно сохранять значение в базе данных каждый раз, когда я выбираю изображение. Если я этого не сделаю, каждое поле ввода будет иметь значение последнего выбранного изображения!
Все еще борюсь с этим!
Вы можете использовать что-то вроде этого, чтобы добавить столько изображений, сколько хотите, с помощью кнопки, например, добавляя логотипы или рекламные материалы и т. д.
jQuery(document).ready(function($){
var mediaUploader;
/* функция для добавления логотипа партнера */
function display_ad( button, title, btnTxt, inputFieldId, outputDivId,formClass, e){
e.preventDefault();
if (mediaUploader) {
mediaUploader.open();
return;
}
mediaUploader = wp.media.frames.file_frame =wp.media({
title: title,
button:{
text: btnTxt,
},
multiple:false,
});
mediaUploader.on('select',function(){
attachment = mediaUploader.state().get('selection').first().toJSON();
$( inputFieldId ).val(attachment.url);
$( outputDivId ).css('background-image','url(' + attachment.url +')' );
$(formClass).submit();
});
mediaUploader.open();
}
function remove_ad(inputFieldId, formClass,e){
e.preventDefault();
var answer = confirm("Вы уверены, что хотите удалить этот логотип?");
if ( answer == true ) {
$(inputFieldId).val('');
$(formClass).submit();
}
return;
}
/** Разные нажатия кнопок **/
$('#logo-one').on('click',function(e){
//display_ad( button, title, btnTxt, inputFieldId, outputDivId, e)
display_ad('#logo-one', 'Выбрать логотип один','Выбрать логотип','#sunshine-partner-one','#sunshine-partner-one-preview','.sunshine-admin-form',e);
});
$('#logo-two').on('click',function(e){
display_ad('#logo-two', 'Выбрать логотип два','Выбрать логотип','#sunshine-partner-two','#sunshine-partner-two-preview','.sunshine-admin-form',e);
});
$('#logo-three').on('click',function(e){
display_ad('#logo-three', 'Выбрать логотип три','Выбрать логотип','#sunshine-partner-three','#sunshine-partner-three-preview','.sunshine-admin-form',e);
});
$('#logo-four').on('click',function(e){
display_ad('#logo-four', 'Выбрать логотип четыре','Выбрать логотип','#sunshine-partner-four','#sunshine-partner-four-preview','.sunshine-admin-form',e);
});
$('#logo-five').on('click',function(e){
display_ad('#logo-five', 'Выбрать логотип пять','Выбрать логотип','#sunshine-partner-five','#sunshine-partner-five-preview','.sunshine-admin-form',e);
});
$('#logo-six').on('click',function(e){
display_ad('#logo-six', 'Выбрать логотип шесть','Выбрать логотип','#sunshine-partner-six','#sunshine-partner-six-preview','.sunshine-admin-form',e);
});
/*Нажатие кнопки удаления*/
$('#remove-logo-one').on('click',function(e){
remove_ad('#sunshine-partner-one','.sunshine-admin-form',e);
});
$('#remove-logo-two').on('click',function(e){
remove_ad('#sunshine-partner-two','.sunshine-admin-form',e);
});
$('#remove-logo-three').on('click',function(e){
remove_ad('#sunshine-partner-three','.sunshine-admin-form',e);
});
$('#remove-logo-four').on('click',function(e){
remove_ad('#sunshine-partner-four','.sunshine-admin-form',e);
});
$('#remove-logo-five').on('click',function(e){
remove_ad('#sunshine-partner-five','.sunshine-admin-form',e);
});
$('#remove-logo-six').on('click',function(e){
remove_ad('#sunshine-partner-six','.sunshine-admin-form',e);
});
});
Я не уверена, что это окончательно, но, вероятно, это играет роль. У вас есть 2 ввода, оба с классом dynamic-image
:
<input type="text" name="dynamic-image<?php echo $a; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$a.''] ) ) echo $dsm['dynamic-image'.$a.''][0]; ?>" />
и
<input type="text" name="dynamic-image<?php echo $b; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$b.''] ) ) echo $dsm['dynamic-image'.$b.''][0]; ?>" />
В вашем JS-скрипте вы затем делаете это:
meta_image_frame.on('select', function() {
var media_attachment = ...
$('.dynamic-image').val(media_attachment.url);
...
});
Когда вы выбираете файл в вашем медиа-кадре, строка $('.dynamic-image').val(media_attachment.url);
заполнит оба ввода одним и тем же URL-адресом вложения.
Вы можете добавить data-
атрибут к вашим кнопкам загрузки вместо этого, вот так:
<input type="button" ... data-target="dynamic-image<?php echo $a; ?>" />
затем прочитать его в вашем JS-скрипте, вот так:
meta_image_frame.on('select', function(){
var media_attachment = ... meta_image_frame.state().get('selection').first().toJSON();
$('[name="' + $( e.target ).attr( 'data-target' ) + '"]').val(media_attachment.url); });
Это должно обновить только соответствующий ввод, в зависимости от того, какую кнопку загрузки вы нажимаете.
Попробуйте нацелиться на идентификаторы полей ввода, а не на классы. Это сработает отлично. И в функции сохранения убедитесь, что каждое изображение сохраняется отдельно и его URL доступен.
Ответ или решение
Для эффективного управления загрузкой нескольких медиафайлов в пользовательском интерфейсе WordPress с использованием метабоксов, необходимо внести изменения в текущий скрипт. Давайте подробно разберем, как можно адаптировать ваш код для поддержки нескольких полей загрузки, гарантируя, что каждое поле будет получать корректный URL загрузки.
Шаг 1: Изменение HTML Разметки
Для начала, необходимо добавить уникальные атрибуты к кнопкам, чтобы можно было легко связать каждую кнопку со своим соответствующим полем ввода.
<div class="image_large" style="background-image: url(<?php echo $dsm['dynamic-image'.$a.''][0]; ?>); background-repeat: no-repeat;">
<p><strong>Image 1</strong></p>
<p>
<label for="dynamic-image" class="dynamic-row-title"><?php _e( 'Image 1', 'dynamic-textdomain' ); ?></label>
<input type="text" name="dynamic-image<?php echo $a; ?>" class="dynamic-image" value="<?php if ( isset( $dsm['dynamic-image'.$a.''] ) ) echo $dsm['dynamic-image'.$a.''][0]; ?>" />
<input type="button" class="dynamic-image-button" data-target="dynamic-image<?php echo $a; ?>" value="<?php _e( 'Choose or Upload', 'dynamic-textdomain' ); ?>" />
</p>
</div>
<div class="image_large" style="background-image: url(<?php echo $dsm['dynamic-image'.$b.''][0]; ?>); background-repeat: no-repeat;">
<p><strong>Image 2</strong></p>
<p>
<label for="dynamic-image" class="dynamic-row-title"><?php _e( 'Image 2', 'dynamic-textdomain' ); ?></label>
<input type="text" name="dynamic-image<?php echo $b; ?>" class="dynamic-image" value="<?php if ( isset( $dsm['dynamic-image'.$b.''] ) ) echo $dsm['dynamic-image'.$b.''][0]; ?>" />
<input type="button" class="dynamic-image-button" data-target="dynamic-image<?php echo $b; ?>" value="<?php _e( 'Choose or Upload', 'dynamic-textdomain' ); ?>" />
</p>
</div>
Шаг 2: Модификация JS Скрипта
Теперь, когда у нас есть атрибут data-target
, который содержит имя соответствующего поля, нам нужно изменить JavaScript, чтобы он обновлял только то поле, на которое нажали.
jQuery(document).ready(function($){
var meta_image_frame;
$('.dynamic-image-button').click(function(e){
e.preventDefault();
var button = $(this); // Сохраняем ссылку на нажатую кнопку
var inputFieldId = button.attr('data-target');
if (meta_image_frame) {
meta_image_frame.open();
return;
}
meta_image_frame = wp.media.frames.meta_image_frame = wp.media({
title: meta_image.title,
button: {
text: meta_image.button
},
multiple: false
});
meta_image_frame.on('select', function(){
var media_attachment = meta_image_frame.state().get('selection').first().toJSON();
$('[name="' + inputFieldId + '"]').val(media_attachment.url); // Установим URL только в соответствующее поле
button.closest('.image_large').css('background-image', 'url(' + media_attachment.url + ')'); // Изменим фон
});
meta_image_frame.open();
});
});
Шаг 3: Сохранение мета-полей
Ваш код для сохранения мета-полей уже корректен, но убедитесь, что название каждого поля соответствует введённому ранее имени. Это гарантирует, что данные будут правильно сохранены.
function dynamic_meta_save( $post_id ) {
$post = get_post($post_id, ARRAY_A);
$pn = $post['post_name'];
$a = "_" . $pn . '_1';
$b = "_" . $pn . '_2';
// Проверка состояния сохранения
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id) || !isset($_POST['dynamic_nonce']) || !wp_verify_nonce($_POST['dynamic_nonce'], basename(__FILE__))) {
return;
}
// Сохранение изображений
if (isset($_POST['dynamic-image' . $a])) {
update_post_meta($post_id, 'dynamic-image' . $a, sanitize_text_field($_POST['dynamic-image' . $a]));
}
if (isset($_POST['dynamic-image' . $b])) {
update_post_meta($post_id, 'dynamic-image' . $b, sanitize_text_field($_POST['dynamic-image' . $b]));
}
}
add_action('save_post', 'dynamic_meta_save');
Итоги
Теперь у вас есть полное решение для управления несколькими полями загрузки изображений в метабоксах WordPress. Каждый раз, когда вы выбираете изображение, только соответствующее поле будет обновляться, предотвращая перезапись данных. Обязательно протестируйте функциональность, чтобы убедиться, что она соответствует вашим требованиям. Этот подход не только упрощает процесс, но и улучшает пользовательский опыт.