Создание дополнительных Meta Boxes по необходимости

13 июн. 2011 г., 02:22:28
Просмотры: 24.6K
Голосов: 49

Я хочу, чтобы пользователи могли создавать и удалять дополнительные поля meta box по мере необходимости.

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

В идеале это должно быть реализовано без использования плагина, а закодировано в файле functions.php.

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

вы описываете встроенный метабокс произвольных полей!

Bainternet Bainternet
13 июн. 2011 г. 02:42:36

Полагаю, в сущности так оно и работает, но он настроен только для работы с одним полем за раз и не очень удобен для конечного пользователя.

Picard102 Picard102
13 июн. 2011 г. 03:11:58
Все ответы на вопрос 2
15
56

Значит, вы имеете в виду что-то вроде этого?

Описание изображения

И когда вы нажимаете "Добавить треки", это превращается в:

Описание изображения

Если это то, что вам нужно, это реализуется через создание метабокса с простой jQuery-функцией для добавления и удаления полей, а данные сохраняются как массив в одной строке метаданных. Вот решение:

  add_action( 'add_meta_boxes', 'dynamic_add_custom_box' );
    
    /* Обрабатываем введенные данные */
    add_action( 'save_post', 'dynamic_save_postdata' );
    
    /* Добавляем блок в основную колонку на страницах редактирования постов и страниц */
    function dynamic_add_custom_box() {
        add_meta_box(
            'dynamic_sectionid',
            __( 'Мои треки', 'myplugin_textdomain' ),
            'dynamic_inner_custom_box',
            'post');
    }
    
    /* Выводим содержимое блока */
    function dynamic_inner_custom_box() {
        global $post;
        // Используем nonce для верификации
        wp_nonce_field( plugin_basename( __FILE__ ), 'dynamicMeta_noncename' );
        ?>
        <div id="meta_inner">
        <?php
    
        // Получаем сохраненные метаданные как массив
        $songs = get_post_meta($post->ID,'songs',false);
        
        $c = 0;
        if ( count( $songs ) > 0 ) {
            foreach( $songs as $track ) {
                if ( isset( $track['title'] ) || isset( $track['track'] ) ) {
                    printf( '<p>Название песни <input type="text" name="songs[%1$s][title]" value="%2$s" /> -- Номер трека : <input type="text" name="songs[%1$s][track]" value="%3$s" /><span class="remove">%4$s</span></p>', $c, $track['title'], $track['track'], __( 'Удалить трек' ) );
                    $c = $c +1;
                }
            }
        }
    
        ?>
    <span id="here"></span>
    <span class="add"><?php _e('Добавить треки'); ?></span>
    <script>
        var $ =jQuery.noConflict();
        $(document).ready(function() {
            var count = <?php echo $c; ?>;
            $(".add").click(function() {
                count = count + 1;
    
                $('#here').append('<p> Название песни <input type="text" name="songs['+count+'][title]" value="" /> -- Номер трека : <input type="text" name="songs['+count+'][track]" value="" /><span class="remove">Удалить трек</span></p>' );
                return false;
            });
// Метод live() устарел в jQuery версии 1.7 и удален в версии 1.9. Вместо него используйте метод on().
            $(".remove").live('click', function() {
                $(this).parent().remove();
            });
        });
        </script>
    </div><?php
    
    }
    
    /* Сохраняем наши данные при сохранении поста */
    function dynamic_save_postdata( $post_id ) {
        // Проверяем автосохранение
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
            return;
    
        // Проверяем права доступа
        if ( !isset( $_POST['dynamicMeta_noncename'] ) )
            return;

        if ( !wp_verify_nonce( $_POST['dynamicMeta_noncename'], plugin_basename( __FILE__ ) ) )
            return;
    
        // Все проверки пройдены - сохраняем данные
    
        $songs = $_POST['songs'];
    
        update_post_meta($post_id,'songs',$songs);
    }
13 июн. 2011 г. 10:41:06
Комментарии

Похоже, что при использовании этого кода отображается только "array(0) { } Add Tracks".

Picard102 Picard102
14 июн. 2011 г. 05:06:47

Да, просто удали var_dump($songs);

Bainternet Bainternet
14 июн. 2011 г. 10:44:17

Круто, это исправило проблему, но теперь данные, кажется, не сохраняются при обновлении. Или, по крайней мере, они не отображаются как поля под "My Track", ни в "Custom Fields". Однако, если я верну var_dump обратно, он выводит "array(1) { [0]=> array(1) { [1]=> array(2) { ["title"]=> string(4) "test" ["track"]=> string(5) "teste" } } } Add Tracks"

Picard102 Picard102
15 июн. 2011 г. 09:16:09

@Picard102 : я исправил код и обновил свой ответ, дай знать.

Bainternet Bainternet
15 июн. 2011 г. 23:14:09

Итак, я попробовал новый код, и теперь он правильно отображает сохраненные данные. Однако теперь я получаю ошибку на любом посте без сохраненных песен: "Invalid argument supplied for foreach()" на строке "foreach($songs as $track ){". Также, когда я удаляю песни из поста, в блоке произвольных полей появляется пустое поле "Song".

Picard102 Picard102
17 июн. 2011 г. 03:25:27

Есть идеи? Я готов заплатить кому-то, чтобы эта функциональность заработала, кажется, что осталось не так уж много работы для завершения.

Picard102 Picard102
26 июн. 2011 г. 22:02:00

Не совсем уверен, в чем проблема, это не точный код, а пример, и у меня он работает нормально. Попробуйте заменить if (count($songs) > 0){ на if(is_array($songs)){

Bainternet Bainternet
27 июн. 2011 г. 11:01:55

Спасибо! Сработало отлично. Я смог использовать этот код для создания более динамичных полей, но осталась проблема с созданием пустых мета-ключей. Если я добавляю песню, но не добавляю ссылку на шоу или заметку к шоу, в итоге создаются пустые мета-ключи для них. Или если я удаляю все элементы в группе, пустой мета-ключ все равно остается. Полагаю, это не такая уж большая проблема — иметь пустые ключи в базе данных?

Picard102 Picard102
2 июл. 2011 г. 20:30:23

@Picard102 и @Bainternet - Я попробовал ваш код, и он работает нормально по одному, но у меня не получается сохранить данные метабоксов, если я добавляю второй, не связанный метабокс. Я изменил nonce-поля и все ID и классы. Не понимаю, что я делаю не так?

gillespieza gillespieza
18 июл. 2011 г. 17:50:11

@Amanda Мне нужно увидеть ваш код, чтобы понять, в чем проблема.

Bainternet Bainternet
18 июл. 2011 г. 23:58:23

@Bainternet: http://wordpress.stackexchange.com/questions/23344/why-wont-my-metabox-data-save/

gillespieza gillespieza
19 июл. 2011 г. 10:31:50

Привет, я планирую добавить такую же функцию для своего пользовательского типа записи, но на этот раз поле для фотографий, при этом фотографии должны загружаться или выбираться из медиатеки. Какой код мне нужно отредактировать? Спасибо.

markyeoj markyeoj
31 авг. 2013 г. 15:08:17

Метод live() был объявлен устаревшим в jQuery версии 1.7 и удален в версии 1.9. Вместо него используйте метод on().

inrsaurabh inrsaurabh
21 авг. 2018 г. 09:53:49

если используется обновленная версия jquery

inrsaurabh inrsaurabh
21 авг. 2018 г. 09:59:22
Показать остальные 10 комментариев
4

Это делается через пользовательские поля, НО вам никогда не следует использовать что-либо, что позволяет пользователям добавлять создавать или удалять метабоксы. Такие записи напрямую попадают в базу данных, поэтому вы потенциально можете создать множество проблем для своего сайта, если предоставите пользователям такой уровень контроля. Гораздо безопаснее создать максимальное количество пользовательских полей, которые могут понадобиться, и позволить оставлять некоторые из них пустыми, если они не нужны.

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

Некоторые рекомендации:

http://wordpress.org/extend/plugins/verve-meta-boxes/

http://wordpress.org/extend/plugins/more-fields/

13 июн. 2011 г. 03:20:18
Комментарии

НО вам никогда не следует использовать что-либо, что позволяет пользователям добавлять или удалять метабоксы

Почему?

Travis Northcutt Travis Northcutt
13 июн. 2011 г. 15:34:01

Моя единственная озабоченность в том, что с любым плагином существует вероятность, что его поддержка может прекратиться в будущем. Я чувствую, что скорее всего смогу разобраться, как починить простое добавление в файл functions, чем разобраться, как починить плагин.

Picard102 Picard102
14 июн. 2011 г. 05:08:23

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

Elpie Elpie
14 июн. 2011 г. 05:14:09

Хорошо знать. Я попробовал два плагина, которые вы предложили, но ни один из них не позволил мне сделать то, что мне было нужно, чего я не мог бы сделать без плагина. Тем не менее, спасибо за предложения.

Picard102 Picard102
14 июн. 2011 г. 05:26:05