Codex

Interested in functions, hooks, classes, or methods? Check out the new WordPress Code Reference!

ru:Shortcode API

Эта страница помечена как незавершённая. Вы можете помочь проекту, дополнив её.

Shortcode API

Введенный в WordPress 2.5, Shortcode API является простым набором функций для создания макро-кодов используемых в содержимом записей. Для примера, следующий короткий код(shortcode) (в содержимом записи/страницы) добавил бы фотогалерею на странице:

[gallery]

Это позволяет разработчикам плагинов создавать специальные виды контента (например формы, генераторы контента) которые пользователи могут прикрепить к определённым страницам добавив соответствующий короткий код в тексте страницы.

Shortcode API упрощает создание коротких кодов которые поддерживают атрибуты вроде этих:

[gallery id="123" size="medium"]

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

Пример для Быстрого Старта

В качестве быстрого старта для тех, кто спешит, вот минимальный пример PHP кода, необходимого для создания короткого кода:

//[foobar]
function foobar_func( $atts ){
 return "foo and bar";
}
add_shortcode( 'foobar', 'foobar_func' );

Будет создан короткий код "[foobar]" который возвращается как: foo and bar

С атрибутами:

// [bartag foo="foo-value"]
function bartag_func( $atts ) {
	extract( shortcode_atts( array(
		'foo' => 'что-то',
		'bar' => 'что-то ещё',
	), $atts ) );

	return "foo = {$foo}";
}
add_shortcode( 'bartag', 'bartag_func' );

Будет создан короткий код "[bartag]" который поддерживает два атрибута: ["foo" и "bar"]. Оба атрибута являются необязательными и примут стандартное значение [foo="что-то" bar="что-то ещё"] если они не будут предоставлены. Короткий код возвращается как foo = {значение атрибута foo}

Общие Сведения

Shortcodes are written by providing a handler function. Shortcode handlers are broadly similar to WordPress filters: they accept parameters (attributes) and return a result (the shortcode output).

Shortcode names should be all lowercase and use all letters, but numbers and underscores should work fine too. Be wary of using hyphens (dashes), you'll be better off not using them.

The `add_shortcode()` function is used to register a shortcode handler. It takes two parameters: the shortcode name (the string used in a post body), and the callback function name.

Three parameters are passed to the shortcode callback function. You can choose to use any number of them including none of them.

  • $atts, an associative array of attributes, or an empty string if no attributes are given
  • $content, the enclosed content (if the shortcode is used in its enclosing form)
  • $tag, the shortcode tag, useful for shared callback functions

The API call to register the shortcode handler would look something like this:

add_shortcode( 'myshortcode', 'my_shortcode_handler' );

When the_content is displayed, the shortcode API will parse any registered shortcodes such as "[myshortcode]", separate and parse the attributes and content, if any, and pass them the corresponding shortcode handler function. Any string returned (not echoed) by the shortcode handler will be inserted into the post body in place of the shortcode itself.

Shortcode attributes are entered like this:

[myshortcode foo="bar" bar="bing"]

These attributes will be converted into an associative array like the following, passed to the handler function as its $atts parameter:

array( 'foo' => 'bar', 'bar' => 'bing' )

The array keys are the attribute names; array values are the corresponding attribute values. In addition, the zeroeth entry ($atts[0]) will hold the string that matched the shortcode regex, but ONLY IF that is different from the callback name. See the discussion of attributes, below.

Атрибуты

The raw $atts array may include any arbitrary attributes that are specified by the user. (In addition, the zeroeth entry of the array may contain the string that was recognized by the regex; see the note below.)

In order to help set default values for missing attributes, and eliminate any attributes that are not recognized by your shortcode, the API provides a shortcode_atts() function.

shortcode_atts() resembles the wp_parse_args() function, but has some important differences. Its parameters are:

shortcode_atts( $defaults_array, $atts );

Both parameters are required. $defaults_array is an associative array that specifies the recognized attribute names and their default values. $atts is the raw attributes array as passed into your shortcode handler. shortcode_atts() will return a normalized array containing all of the keys from the $defaults_array, filled in with values from the $atts array if present. For example:

$a = shortcode_atts( array(
   'title' => 'My Title',
   'foo' => 123,
   ), $atts );

If $atts were to contain array( 'foo' => 456, 'bar' => 'something' ), the resulting $a would be array( 'title' => 'My Title', 'foo' => 456 ). The value of $atts['foo'] overrides the default of 123. $atts['title'] is not set, so the default 'My Title' is used. And there is no 'bar' item in the defaults array, so it is not included in the result.

Attribute names are always converted to lowercase before they are passed into the handler function. Values are untouched. [myshortcode FOO="BAR"] produces $atts = array( 'foo' => 'BAR' ).

A suggested code idiom for declaring defaults and parsing attributes in a shortcode handler is as follows:

function my_shortcode_handler( $atts, $content = null ) {
   extract( shortcode_atts( array(
      'attr_1' => 'attribute 1 default',
      'attr_2' => 'attribute 2 default',
      // ...etc
      ), $atts ) );
}

This will parse the attributes, set default values, eliminate any unsupported attributes, and (using extract()) store the results in local variables named for the attribute keys - $attr_1, $attr_2 and so on. In other words, the array of defaults approximates a list of local variable declarations. (extract() is safe to use in this context without special flags to handle collisions because shortcode_atts() will strip out any keys not included in the defaults array).


IMPORTANT TIP - Don't use camelCase or UPPER-CASE for your $atts attribute names
$atts values are lower-cased during shortcode_atts( array( 'attr_1' => 'attr_1 default', // ...etc ), $atts ) processing, so you might want to just use lower-case.


NOTE on confusing regex/callback name reference
The zeroeth entry of the attributes array ($atts[0]) will contain the string that matched the shortcode regex, but ONLY if that differs from the callback name, which otherwise appears as the third argument to the callback function.
(Appears to always appear as third argument as of 2.9.2.)
 add_shortcode('foo','foo'); // two shortcodes referencing the same callback
 add_shortcode('bar','foo');
    produces this behavior:
 [foo a='b'] ==> callback to: foo(array('a'=>'b'),NULL,"foo");
 [bar a='c'] ==> callback to: foo(array(0 => 'bar', 'a'=>'c'),NULL,"");

This is confusing and perhaps reflects an underlying bug, but an overloaded callback routine can correctly determine what shortcode was used to call it, by checking BOTH the third argument to the callback and the zeroeth attribute. (It is NOT an error to have two shortcodes reference the same callback routine, which allows for common code.)

Вывод

Возвращаемое значение функции обработчика короткого кода вставляется в вывод содержимого записи на месте макроса короткого кода. Используйте 'return', а не 'echo' - иначе содержимое будет выводится в браузер, но не будет отображаться в нужном месте на странице.

Короткие коды обрабатываются после того как wpautop и wptexturize форматирование сообщений было применено (но смотрите примечание ниже о различиях 2.5.0 и 2.5.1). Это означает, что к HTML выводу вашего короткого кода не будут автоматически применяться кавычки, добавляться теги p и br, и тому подобное. Если вы хотите чтобы вывод вашего короткого кода форматировался, вы должны вызвать wpautop() или wptexturize() напрямую когда вы делаете вывод из обработчика вашего короткого кода.

wpautop распознаёт синтаксис коротких кодов и не будет пытаться заключить в p или br теги одиночные короткие коды стоящие на строке сами по себе. Короткие коды, предназначенные для использования таким образом, должны гарантировать, что вывод заключён в соответствующий блок тегов, таких как <p> или <div>.

Примечание: в WordPress 2.5.0 короткие коды обрабатывались после применения к ним форматирования, так что иногда HTML вывод короткого кода заключался в теги p или br. Это было некорректное поведение, которое было исправлено в версии 2.5.1.

Если короткий код образует много HTML кода, то можно использовать ob_start() для записи выходных данных и преобразования их в строку следующим образом:-

function myShortCode() {
  ob_start();
  ?> <HTML> <here> ... <?PHP
  $output_string = ob_get_contents();
  ob_end_clean();
  return $output_string;
}

Enclosing vs self-closing shortcodes

The examples above show self-closing shortcode macros such as [myshortcode]. The API also supports enclosing shortcodes such as [myshortcode]content[/myshortcode].

If a shortcode macro is used to enclose content, its handler function will receive a second parameter containing that content. Users might write shortcodes in either form, so it is necessary to allow for either case by providing a default value for the second parameter to your handler function:

function my_shortcode_handler( $atts, $content = null )

is_null( $content ) can be used to distinguish between the self-closing and enclosing cases.

When content is enclosed, the complete shortcode macro including its content will be replaced with the function output. It is the responsibility of the handler function to provide any necessary escaping or encoding of the raw content string, and include it in the output.

Here's a trivial example of an enclosing shortcode:

function caption_shortcode( $atts, $content = null ) {
   return '<span class="caption">' . $content . '</span>';
}
add_shortcode( 'caption', 'caption_shortcode' );

When used like this:

[caption]My Caption[/caption]

The output would be:

<span class="caption">My Caption</span>

Since $content is included in the return value without any escaping or encoding, the user can include raw HTML:

[caption]<a href="http://example.com/">My Caption</a>[/caption]

Which would produce:

<span class="caption"><a href="http://example.com/">My Caption</a></span>

This may or may not be intended behaviour - if the shortcode should not permit raw HTML in its output, it should use an escaping or filtering function to deal with it before returning the result.

The shortcode parser uses a single pass on the post content. This means that if the $content parameter of a shortcode handler contains another shortcode, it won't be parsed:

[caption]Caption: [myshortcode][/caption]

This would produce:

<span class="caption">Caption: [myshortcode]</span>

If the enclosing shortcode is intended to permit other shortcodes in its output, the handler function can call do_shortcode() recursively:

function caption_shortcode( $atts, $content = null ) {
   return '<span class="caption">' . do_shortcode($content) . '</span>';
}

In the previous example, this would ensure the "[myshortcode]" macro in the enclosed content is parsed, and its output enclosed by the caption span:

<span class="caption">Caption: The result of myshortcode's handler function</span>

The parser does not handle mixing of enclosing and non-enclosing forms of the same shortcode as you would want it to. For example, if you have:

[myshortcode example='non-enclosing' /] non-enclosed content [myshortcode] enclosed content [/myshortcode]

Instead of being treated as two shortcodes separated by the text " non-enclosed content ", the parser treats this as a single shortcode enclosing " non-enclosed content [myshortcode] enclosed content".

Enclosing shortcodes support attributes in the same way as self-closing shortcodes. Here's an example of the caption_shortcode() improved to support a 'class' attribute:

function caption_shortcode( $atts, $content = null ) {
   extract( shortcode_atts( array(
      'class' => 'caption',
      ), $atts ) );
 
   return '<span class="' . esc_attr($class) . '">' . $content . '</span>';
}
[caption class="headline"]My Caption[/caption]
<span class="headline">My Caption</span>

Other features in brief

  • The parser supports xhtml-style closing shortcodes like "[myshortcode /]", but this is optional.
  • Shortcode macros may use single or double quotes for attribute values, or omit them entirely if the attribute value does not contain spaces. [myshortcode foo='123' bar=456] is equivalent to [myshortcode foo="123" bar="456"].
  • For backwards compatibility with older ad-hoc shortcodes, attribute names may be omitted. If an attribute has no name it will be given a positional numeric key in the $atts array. For example, [myshortcode 123] will produce $atts = array( 0 => 123 ). Positional attributes may be mixed with named ones, and quotes may be used if the values contain spaces or other significant characters.

Function reference

The following Shortcode API functions are available:

function add_shortcode($tag, $func)

Registers a new shortcode handler function. $tag is the shortcode string as written by the user (without braces), such as "myshortcode". $func is the handler function name.

Only one handler function may exist for a given shortcode. Calling add_shortcode() again with the same $tag name will overwrite the previous handler.

function remove_shortcode($tag)

Deregisters an existing shortcode. $tag is the shortcode name as used in add_shortcode().

function remove_all_shortcodes()

Deregisters all shortcodes.

function shortcode_atts($pairs, $atts)

Process a raw array of attributes $atts against the set of defaults specified in $pairs. Returns an array. The result will contain every key from $pairs, merged with values from $atts. Any keys in $atts that do not exist in $pairs are ignored.

function do_shortcode($content)

Parse any known shortcode macros in the $content string. Returns a string containing the original content with shortcode macros replaced by their handler functions' output.

do_shortcode() is registered as a default filter on 'the_content' with a priority of 11.

Limitations

Nested Shortcodes

The shortcode parser correctly deals with nested shortcode macros, provided their handler functions support it by recursively calling do_shortcode():

[tag-a]
   [tab-b]
      [tag-c]
   [/tag-b]
[/tag-a]

However the parser will fail if a shortcode macro is used to enclose another macro of the same name:

[tag-a]
   [tag-a]
   [/tag-a]
[/tag-a]

This is a limitation of the context-free regexp parser used by do_shortcode() - it is very fast but does not count levels of nesting, so it can't match each opening tag with its correct closing tag in these cases.

Unclosed Shortcodes

In certain cases the shortcode parser cannot correctly deal with the use of both closed and unclosed shortcodes. For instance in this case the parser will only correctly identify the second instance of the shortcode:

[tag]
[tag]
   CONTENT
[/tag]

However in this case the parser will identify both:

[tag]
   CONTENT
[/tag]
[tag]

Hyphens

Note: The behavior described below involving shortcodes with hyphens ('-') still applies in WordPress 3+. This could be due to a bug in do_shortcode() or get_shortcode_regex().

Take caution when using hyphens in the name of your shortcodes. In the following instance WordPress may see the second opening shortcode as equivalent to the first (basically WordPress sees the first part before the hyphen):

[tag]
[tag-a]

It all depends on which shortcode is defined first. If you are going to use hyphens then define the shortest shortcode first.

To avoid this, use an underscore or simply no separator:

[tag]
[tag_a]

[tag]
[taga]

If the first part of the shortcode is different from one another, you can get away with using hyphens:

[tag]
[tagfoo-a]

Important: Using hyphens can have implications that you may not be aware of; such as if other installed shortcodes also are use hyphens, the use of generic words with hyphens may cause collisions (if shortcodes are used together within the same request):

// plugin-A
[is-logged-in]

// plugin-B
[is-admin]

Square Brackets

The shortcode parser does not accept square brackets within attributes. Thus the following will fail:

[tag attribute="[Some value]"]


Note: these limitations may change in future versions of WordPress, you should test to be absolutely sure.

External Resources

Related

Shortcode API