Поддержка массивов в шорткодах

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

Таким образом, я начал с создания шорткода и настройки атрибутов, для которых мне нужно было собрать данные. Мой шорткод имел следующий вид:

function chain_select_shortcode( $atts ) {
	extract( shortcode_atts( array( 'tax' => 'category', 'level' => 1, 'titles' => array( 'Please select…' ), 'labels' => '', 'btn_text' => 'Submit', 'exclude' => '', 'count' => 1 ), $atts ) );
}

add_shortcode( 'ajax_chain_select', 'chain_select_shortcode' );

Здесь я установил шорткод и задал стандартные настройки (для тех случаев, когда атрибуты не объявлены в шорткоде).

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

Я реализовал это так: просто разделил значения в атрибутах с помощью запятой и пробела. Мой шорткод стал выглядеть следующим образом:

[ajax_chain_select tax="competitor" level=2, titles="Select Manufacturer, Select Product" labels="Manufacturer, Product" count=0]

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

При передаче этих данных в функцию мы можем использовать explode() для создания массива. Вот, как это будет выглядеть в окончательном варианте:

function chain_select_shortcode( $atts ) {
	extract( shortcode_atts( array( 'tax' => 'category', 'level' => 1, 'titles' => array( 'Please select…' ), 'labels' => '', 'btn_text' => 'Submit', 'exclude' => '', 'count' => 1 ), $atts ) );

	return chainselect_getcategories( $tax, $level, explode( ', ', $titles ), explode( ', ', $labels ), $btn_text, $exclude, $count );
}

add_shortcode( 'ajax_chain_select', 'chain_select_shortcode' );

Обратите внимание на функцию chainselect_categories — в ней содержится функция explode, необходимая для создания массива, которая требует, чтобы значения были разделены пробелом и запятой.

Теперь функция получает данные в виде массива и может работать, как положено.

Блог про WordPress
Комментарии: 11
  1. Koxae

    Доброе время суток!

    Подскажите, пожалуйста, как ввернуть в тело шоткода проверку на пустой аттрибут?

    Например, есть аттрибуты: name1, name2, name3

    Вывод:

    Раз: ‘ . $name1 . ‘, Два: ‘ . $name2 . ‘, Три: ‘ . $name3 . ‘

    Как сделать проверку, что, если name1 пустой, то «Раз: ‘ . $name1 . ‘, » не выводить, если name2 пустой, то «Два: ‘ . $name2 . ‘, » не выводить и т.д?

    Заранее спасибо!

    1. Дмитрий (автор)

      Прочитайте следующую статью (на английском): http://richjenks.com/wp-shortcode-attributes-without-values/

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

  2. Koxae

    Я её находила и уже пыталась там что-то понять, но, увы, не смогла: я чайник в скриптах. Тем более, насколько я поняла, там выводится результат целиком, в зависимости от условия, а мне нужно несколько условий внутри самого вывода. И я совершенно не понимаю, как это организовать. :(

    1. Дмитрий (автор)

      Да, вам нужно свою базовую функцию редактировать, которая и отвечает за создание и вывод шорткода.

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

      Вот пример из кодекса:

      function bartag_func( $atts ) {
          $a = shortcode_atts( array(
              'foo' => 'something',
              'bar' => 'something else',
          ), $atts );
      
          return "foo = {$a['foo']}";
      }
      add_shortcode( 'bartag', 'bartag_func' );

      Здесь вы можете до вывода return использовать условие if для проверки на пустоту атрибута.

      К примеру,

      if ( $a['foo']=='' ) {выводим нужную строку}
      

      Если первый атрибут пустой (в данном случае foo, у вас он будет name1, то выводим нужную строку. И так далее, по аналогии.

  3. Koxae

    Спасибо огромное, что не отказываете в ответе!
    Но, всё равно, не поняла. :( Извините.
    У меня нет базовых значений, все они изначально пустые. И мне, наоборот, надо, чтоб пустое не выводилось, а не пустое выводилось.
    По-человечески я могу это написать, но язык пхп ставит меня в тупик.

    Допустим, есть такой шоткод:

    function func_one($atts) {
    extract(shortcode_atts(array(
    ‘att1’ => »,
    ‘att2’ => »,
    ‘att3’ => »,
    ), $atts));
    return ‘что-точто-точто-то
    ‘;
    }
    add_shortcode(‘func’, ‘func_one’);

    Вот return нужно привести к виду:
    если att1=0
    то ничего не выводить
    в остальных случаях вывести что-то
    если att2=0
    то ничего не выводить
    в остальных случаях вывести что-то
    если att3=0
    то ничего не выводить
    в остальных случаях вывести что-то

    То есть, цепочкой надо, потому что атрибутов несколько и они по разному будут заполняться. Общее условие для них делать никак.

  4. Koxae

    Ох ты ж… Я код не умею вставлять красиво как Вы.
    Попробую так:

    Допустим, есть такой шоткод:

    function func_one($atts) {
    extract(shortcode_atts(array(
    ‘att1’ => »,
    ‘att2’ => »,
    ‘att3’ => »,
    ), $atts));
    return ‘<div class=»‘. $att1 . ‘»>что-то</div><div class=»‘. $att2 . ‘»>что-то</div><div class=»‘. $att3 . ‘»>что-то</div>
    ‘;
    }
    add_shortcode(‘func’, ‘func_one’);

    Вот return нужно привести к виду:
    если att1=0
    то ничего не выводить
    в остальных случаях вывести <div class=»‘. $att1 . ‘»>что-то</div>
    если att2=0
    то ничего не выводить
    в остальных случаях вывести <div class=»‘. $att2 . ‘»>что-то</div>
    если att3=0
    то ничего не выводить
    в остальных случаях вывести <div class=»‘. $att3 . ‘»>что-то</div>

  5. Дмитрий (автор)
    function func_one($atts) {
     $a = extract(shortcode_atts(array(
    ‘att1? =>'',
    ‘att2? =>'',
    ‘att3? =>'',
    ), $atts));
    if ( $a['att1']=='' ) { return '<div class=". $att2 . ">что-то</div><div class=". $att3 . ">что-то</div>'
    }
    elseif ( $a['att2']=='' ) { return '<div class=". $att1 . ">что-то</div><div class=". $att3 . ">что-то</div>'
    }
    elseif ( $a['att3']=='' ) { return '<div class=". $att1 . ">что-то</div><div class=". $att2 . ">что-то</div>'
    }
    else {
    return '<div class=". $att1 . ">что-то</div><div class=". $att2 . ">что-то</div><div class=". $att3 . ">что-то</div>'
    }
    

    Как-то так, если я правильно вас понял.

  6. Koxae

    Почти. :) Только у меня этих атрибутов штук 10, и неизвестно какой из них будет пустым, поэтому нужно именно цепочкой выводить, ставя условие каждому атрибуту, чтоб он не влиял на вывод остального кода. А не формировать код целиком под каждый пустой атрибут.
    Вот в этом то и загвоздка. Иначе код будет километровым.

    1. Дмитрий (автор)

      Ну если их всего 10 и расширять не планируете, то можно и так оставить. Качество кода уже будет на втором месте :) Главное — хоть как-то реализовать. Пока пришла в голову только такая идея, если что-то еще надумаю, то отпишусь.

  7. Koxae

    Будьте так добры! Поскольку, даже имея 3 атрибута, нужно код повторять 8 раз. А у меня и так functions.php монструозный. :)
    И безусловное Вам спасибо за то, что отвечаете!

  8. Koxae

    А можно как-нибудь кусок кода сделать переменной и передавать в готовый код уже её?
    Например:
    если arr1=0, то var1=ничего
    в остальных случаях var1=(что-то att1 что-то)

    И в конечный код вставлять не att1, а var1, в которой будет код со значением атрибута.

    Сама с трудом понимаю, что написала. :)

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

Получать новые комментарии по электронной почте.