Записуйте сценарії / стилі, коли присутній короткий код


54

Який ідеальний спосіб зареєструвати / задати сценарії та / або стилі для використання у плагінах?

Нещодавно я створив простий плагін, щоб додати аватар / граватар користувача з коротким кодом. У мене є різні варіанти стилю відображення аватара (квадрат, круглий і т. Д.) І вирішив помістити css безпосередньо в самий короткий код.

Однак я усвідомлюю, що зараз це не дуже вдалий підхід, оскільки він повторюватиме css щоразу, коли короткий код використовується на сторінці. Я бачив кілька інших підходів на цьому сайті, і wp codex навіть має два власні приклади, тому важко дізнатися, який підхід є найбільш послідовним і швидким.

Ось методи, про які я зараз знаю:

Спосіб 1: Включити безпосередньо в короткий код - Це те, що я зараз роблю в плагіні, але не здається гарним, оскільки він повторює код.

class My_Shortcode {
function handle_shortcode( $atts, $content="" ) {
/* simply enqueue or print the scripts/styles in the shortcode itself */
?>
<style type="text/css">

</style>
<?php
    return "$content";
     }
}
add_shortcode( 'myshortcode', array( 'My_Shortcode', 'handle_shortcode' ) );

Спосіб 2: Використовуйте клас для додавання сценаріїв або стилів умовно

class My_Shortcode {
    static $add_script;
    static function init() {
        add_shortcode('myshortcode', array(__CLASS__, 'handle_shortcode'));
        add_action('init', array(__CLASS__, 'register_script'));
        add_action('wp_footer', array(__CLASS__, 'print_script'));
    }
    static function handle_shortcode($atts) {
        self::$add_script = true;
        // shortcode handling here
    }
    static function register_script() {
        wp_register_script('my-script', plugins_url('my-script.js', __FILE__), array('jquery'), '1.0', true);
    }
    static function print_script() {
        if ( ! self::$add_script )
            return;
        wp_print_scripts('my-script');
    }
}
My_Shortcode::init();

Спосіб 3: Використання get_shortcode_regex();

function your_prefix_detect_shortcode() {

    global $wp_query;   
    $posts = $wp_query->posts;
    $pattern = get_shortcode_regex();

    foreach ($posts as $post){
        if (   preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches )
            && array_key_exists( 2, $matches )
            && in_array( 'myshortcode', $matches[2] ) )
        {
            // css/js 
            break;  
        }    
    }
}
add_action( 'wp', 'your_prefix_detect_shortcode' );

Метод 4: Використання has_shortcode();

function custom_shortcode_scripts() {
    global $post;
    if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'myshortcode') ) {
        wp_enqueue_script( 'my-script');
    }
}
add_action( 'wp_enqueue_scripts', 'custom_shortcode_scripts');

Я вважаю Method 4: Using has_shortcode();, що найкраще, тому що це гарантуватиме, що сценарії та стилі завантажуватимуться один раз, якщо вміст публікації має короткий код незалежно від багаторазового використання короткого коду. Хоча це може не працювати для використання коротких кодів у віджетах або на бічній панелі, проте не впевнений. Якщо це плагін, я б не рекомендував зв’язувати сценарії з коротким кодом, оскільки деякі можуть зателефонувати вашій функції замість короткого коду, щоб отримати потрібний вихід.
Роберт відтінок

Відповіді:


45

Я знайшов інший спосіб, який добре працює для мене:

  • Під час ініціалізації плагіна не додайте до скриптів та стилів, а зареєструйте їх за допомогою wp_register_styleта та wp_register_script.

  • Далі ви можете завантажити сценарій / стиль на вимогу. Наприклад, коли ви надаєте короткий код за допомогою wp_enqueue_style("your_style")та wp_enqueue_script("your_script").

Ось приклад плагіна за допомогою цього методу, який дозволяє використовувати get_avatar в якості короткого коду. Таблиця стилів запускається лише за наявності короткого коду.

Використання (за замовчуванням id поточному користувачеві):

[get_avatar id="" size="32" default="mystery" alt="Profile Photo" class="round"]

function wpse_165754_avatar_shortcode_wp_enqueue_scripts() {
    wp_register_style( 'get-avatar-style', plugins_url( '/css/style.css', __FILE__ ), array(), '1.0.0', 'all' );
}

add_action( 'wp_enqueue_scripts', 'wpse_165754_avatar_shortcode_wp_enqueue_scripts' );
if ( function_exists( 'get_avatar' ) ) {
    function wpse_165754_user_avatar_shortcode( $attributes ) {

        global $current_user;
        get_currentuserinfo();

        extract( shortcode_atts(
                     array(
                         "id"      => $current_user->ID,
                         "size"    => 32,
                         "default" => 'mystery',
                         "alt"     => '',
                         "class"   => '',
                     ), $attributes, 'get_avatar' ) );

        $get_avatar = get_avatar( $id, $size, $default, $alt );

        wp_enqueue_style( 'get-avatar-style' );

        return '<span class="get_avatar ' . $class . '">' . $get_avatar . '</span>';
    }

    add_shortcode( 'get_avatar', wpse_165754_user_avatar_shortcode' );
}

Забув: я поставив це питання минулого року, але я фактично почав це робити так само, як і у багатьох випадках. Це схоже на поєднання методу 1 і 2.
Брайан Вілліс

4
Цей метод завантажує CSS у нижній колонтитул, який, безумовно, має обмеження?
Яків Раккуя

1
Це абсолютно правильний спосіб зробити це. Використовуйте цей метод будь-коли, коли вам потрібно умовно завантажити сценарій або таблицю стилів, коли wp_enqueue_scriptsгак уже відбувся. (Шорт-коди розбираються, під час the_contentяких є частиною the_postгачка. Це означає, що затримка, коли вона розбирається, занадто пізно, якщо ви вже не зареєстрували сценарій)
JRad Bad Bad

26

Перш ніж розпочати відповідь, я повинен сказати, що щодо цієї теми css та js не однакові.

Причина проста: хоча додавання js до тіла сторінки (у нижньому колонтитулі) - це поширений і дійсний спосіб перейти, css потрібно розмістити в <head>розділі сторінки: навіть якщо більшість браузерів може належним чином відобразити css на сторінці body, це недійсний HTML-код.

Коли виведений короткий код, <head>розділ вже був надрукований, це означає, що js можна додавати без проблем у нижній колонтитул, але css повинен бути доданий до того, як короткий код буде наданий.

Сценарії

Якщо ваш короткий код потребує лише js, вам пощастить, і ви можете просто використовувати wp_enqueue_scriptв тілі зворотного дзвінка короткий код:

add_shortcode( 'myshortcode', 'my_handle_shortcode' );

function my_handle_shortcode() {
  wp_enqueue_script( 'myshortcodejs', '/path/to/js/file.js' );
  // rest of code here...
}

При цьому ваш сценарій додається у колонтитул і лише один раз, навіть якщо короткий код використовується на сторінці більше одного разу.

Стилі

Якщо вам потрібні стилі коду, вам потрібно діяти, перш ніж короткий код буде фактично наданий.

Існують різні способи зробити це:

  1. перегляньте всі повідомлення в поточному запиті та додайте стилі короткого коду, якщо потрібно. Це ви робите і в методі №3 та №4 в ОП. Насправді обидва способи роблять те саме, але він has_shortcodeбув доданий у WP 3.6, хоча get_shortcode_regexвін доступний з версії 2.5, тому використовуйте get_shortcode_regexлише, якщо ви хочете зробити свій плагін сумісним із старими версіями.

  2. завжди додайте стиль короткого коду на всіх сторінках

Випуски

Випуск №1 - це продуктивність. Regex є досить повільними операціями, і запуск регулярного виразу в циклі всіх публікацій може сповільнювати сторінку послідовно. Більше того, в темах є досить поширеним завданням показувати лише архів публікацій в архівах та показувати повний вміст із штрих-кодами лише в єдиних поданнях. Якщо це станеться, коли відображається архів, ваш плагін запустить збіг регулярних виразів у циклі з метою додати стиль, який ніколи не буде використаний: непотрібний подвійний вплив на продуктивність: уповільнення генерації сторінки + додатковий непотрібний запит HTTP

Проблема з №2 - знову ж таки продуктивність. Додавання стилю до всіх сторінок означає додавання додаткового запиту HTTP для всіх сторінок, навіть коли це не потрібно. Навіть якщо час генерації сторінок на сервері не впливає, загальний час візуалізації сторінок буде, і для всіх сторінок сайту.

Отже, що повинен робити розробник плагінів?

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

Таким чином можна підключити, "template_redirect"щоб перевірити, чи відповідає поточний запит вимогам, і в цьому випадку додати стиль.

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

Якщо користувач вирішить використовувати короткий код навіть в архівах, я б уникав виконувати регулярні вирази для всіх дописів, якщо кількість публікацій велике і просто додаватимуть стиль, якщо запит відповідає вимогам.

Що слід вважати "високим" у цьому плані, слід отримати деякі тести на ефективність або, як альтернативу, додати інший варіант та дати вибір користувачам.


2
Тут варто зазначити, що <style>теги в документі документа тепер дійсні відповідно до специфікації W3C. w3.org/TR/html52/document-metadata.html#the-style-element
Ісаак Любов

5

Для мого плагіна я виявив, що інколи користувачі мають конструктор тем, який містить короткий код, який зберігається у метаданих пост . Ось що я використовую, щоб визначити, чи присутній мій короткий код плагіна в поточних або публікаціях метаданих :

function abcd_load_my_shorcode_resources() {
       global $post, $wpdb;

       // determine whether this page contains "my_shortcode" shortcode
       $shortcode_found = false;
       if ( has_shortcode($post->post_content, 'my_shortcode') ) {
          $shortcode_found = true;
       } else if ( isset($post->ID) ) {
          $result = $wpdb->get_var( $wpdb->prepare(
            "SELECT count(*) FROM $wpdb->postmeta " .
            "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'", $post->ID ) );
          $shortcode_found = ! empty( $result );
       }

       if ( $shortcode_found ) {
          wp_enqueue_script(...);
          wp_enqueue_style(...);
       }
}
add_action( 'wp_enqueue_scripts', 'abcd_load_my_shorcode_resources' );

2

Я роблю так:

class My_Shortcode {

    function __construct() {
        do_action('my_start_shortcode'); // call
....

і зачепити гачок в інші функції (або інші плагіни):

function wpse_3232_load_script(){
    wp_enqueue_script('js-myjs');
}
add_action('my_start_shortcode','wpse_3232_load_script',10);

1

Я дізнався для власного плагіна, якщо короткий код присутній у текстовому віджеті.

function check_shortcode($text) {

  $pattern = get_shortcode_regex();

   if (   preg_match_all( '/'. $pattern .'/s', $text, $matches )
        && array_key_exists( 2, $matches )
        && in_array( 'myshortcode', $matches[2] ) )
    {
        // myshortcode is being used

        // enque my css and js
        /****** Enqueu RFNB  ******/
        wp_enqueue_style('css-mycss');
        wp_enqueue_script('js-myjs');

        // OPTIONAL ALLOW SHORTCODE TO WORK IN TEXT WIDGET
        add_filter( 'widget_text', 'shortcode_unautop');
        add_filter( 'widget_text', 'do_shortcode'); 

    }

  return $text;

}
add_filter('widget_text', 'check_shortcode');

1

WordPress має вбудовану функцію, щоб зробити щось на основі конкретного стану подання короткого коду. Назва функції - has_shortcode(). Ви можете використовувати наступний код, щоб додати свій стиль та сценарії.

Тут я використав is_a( $post, 'WP_Post' )для перевірки, чи є $postоб'єкт WP_Postкласу, і я $post->post_contentперевірив вміст публікації.

if ( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'shortcode_tag') ) {
    wp_enqueue_style( 'handle', get_template_directory_uri() . '/your_file_filename.css' );
}

0

Я зробив комбінацію прикладу коду зі сторінки Wordpress для has_shortcode () і відповідь дала zndencka . Я помітив, що функція has_shortcode додана в Wordpress 3.6, тому я спочатку перевіряю, чи функція існує. Можливо, ця перевірка трохи застаріла, оскільки вже не так багато користувачів знизу Wordpress 3.6, відповідно до їх власних статистичних даних.

// This makes sure the styling is already enqueued in the header, so before the shortcode loads in the page/post
function enqueue_shortcode_header_script() {
    global $post;
    if ( function_exists( 'has_shortcode' ) ){  // is added in wordpress 3.6
        // Source: https://codex.wordpress.org/Function_Reference/has_shortcode
        if( is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, 'my_shortcode') ) {
            wp_enqueue_style( 'shortcode-css' );
        }
    }
    else if ( isset($post->ID) ) { // Small percentage wordpress users are below 3.6 https://wordpress.org/about/stats/
        global $wpdb;
        $result = $wpdb->get_var(
          $wpdb->prepare(
              "SELECT count(*) FROM $wpdb->postmeta " .
              "WHERE post_id = %d and meta_value LIKE '%%my_shortcode%%'",
               $post->ID )
        );
        if (!empty( $result )) { wp_enqueue_style( 'shortcode-css' ); }
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_shortcode_header_script');

0

Ми дійсно можемо умовно завантажувати файли CSS та JS за допомогою короткого коду, не використовуючи надмірно складних функцій:

По-перше, припустимо, що ми зареєстрували всі наші CSS / JS файли раніше (можливо, коли було wp_enqueue_scriptsзапущено)

function prep_css_and_js() {
     wp_register_style('my-css', $_css_url);
     wp_register_script('my-js', $_js_url);
}
add_action( 'wp_enqueue_scripts', 'prep_css_and_js', 5 );

Далі давайте вивчимо нашу функцію короткого коду:

function my_shortcode_func( $atts, $content = null ) {
  if( ! wp_style_is( "my-css", $list = 'enqueued' ) ) { wp_enqueue_style('my-css'); }
  if( ! wp_script_is( "my-js", $list = 'enqueued' ) ) { wp_enqueue_script('my-js'); }
  ...
}

Простий. Зроблено. Ergo: ми можемо "умовно завантажувати" файли css / js (лише тоді, коли працює [shortcode]).

Розглянемо наступну ідеологію:

  • Ми хочемо завантажити певні файли CSS / JS (але тільки коли спрацьовує короткий код)
  • Можливо, ми не хочемо, щоб ці файли завантажувалися на кожній сторінці, або взагалі, якщо короткий код не використовується на сторінці / публікації. (невелика вага)
  • Ми можемо досягти цього, переконавшись, що WP реєструє ВСІ файли css / js до виклику короткого коду та до початку запиту.
  • IE: Можливо, під час prep_css_and_js()роботи я завантажую ВСІ .css / .js файли, які знаходяться в певних папках ...

Тепер, коли WP розглядає їх як зареєстровані сценарії, ми їх дійсно можемо назвати, умовно, виходячи з правдивості ситуацій, включаючи, але не обмежуючись ними, my_shortcode_func()

Переваги: ​​(немає MySQL, не потрібні додаткові функції та не потрібні фільтри)

  • це "WP orthodix", елегантний, швидкий завантаження, легкий і простий
  • дозволяє компіляторам / мініфіксаторам виявляти такі сценарії
  • використовує функції WP (wp_register_style / wp_register_script)
  • сумісний з більшою кількістю тем / плагінів, які, можливо, захочуть скасувати реєстрацію цих сценаріїв з поважної причини.
  • не буде спрацьовувати кілька разів
  • дуже мало обробки або коду

Список літератури:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.