web-dev-qa-db-ja.com

ショートコードが存在する場合はスクリプト/スタイルをエンキューする

プラグインで使用するためのスクリプトやスタイルを登録/エンキューするためのアイデアの方法は何ですか?

私は最近プラグインを作成しました - 単純なプラグイン ショートコードを使用してユーザーのアバター/グラバターを追加します。私はアバターを表示するためのさまざまなスタイルのオプション(正方形、円形など)を持っていて、ショートコード自体に直接CSSを入れることにしました。

しかし、ショートコードがページで使用されるたびにCSSが繰り返されるため、これは良い方法ではないことがわかりました。私はこのサイトで他のいくつかのアプローチを見ました、そして、wpコーデックスはそれら自身の2つの例さえ持っています、それでどのアプローチが最も一貫していて最も速いかを知るのは難しいです。

私が現在知っている方法は次のとおりです。

方法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');
51
Bryan Willis

私は私のためにうまくいく他の方法を見つけました:

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' );
}
42
jblanche

回答を始める前に、このトピックに関してcssとjsは同じではないと言わなければなりません。

理由は簡単です:ページの本文(フッター)にjsを追加するのが一般的で有効な方法ですが、cssはページの<head>セクションに配置する必要があります。ページ本文に適切なレンダリングcss、それは有効なHTMLコードではありません。

ショートコードがレンダリングされる場合、<head>セクションはすでに印刷されています。つまり、フッターに問題なくjsを追加できますが、cssを追加する必要がありますbeforeショートコードがレンダリングされます。

スクリプト

ショートコードに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回だけ追加されます。

スタイル

コードにスタイルが必要な場合は、行動する必要がありますbeforeショートコードが実際にレンダリングされます。

これを行うにはさまざまな方法があります。

  1. 現在のクエリのすべての投稿を見て、必要に応じてショートコードスタイルを追加します。これは、OPのメソッド#3と#4の両方で行います。実際、2つのメソッドは両方とも同じことを行いますが、WP 3.6でhas_shortcodeが追加されましたが、get_shortcode_regexはバージョン2.5以降で使用できるため、get_shortcode_regexプラグインを古いバージョンと互換性のあるものにしたい。

  2. すべてのページに常にショートコードスタイルを追加する

課題

#1の問題はパフォーマンスです。正規表現は非常に遅い操作であり、すべての投稿のループで正規表現を起動すると、一貫してページが遅くなる場合があります。さらに、アーカイブでは投稿の抜粋のみを表示し、ショートコードを含む完全なコンテンツを単一のビューでのみ表示することは、テーマではかなり一般的なタスクです。その場合、アーカイブが表示されると、プラグインは使用されないスタイルを追加することを目的として、ループ内で正規表現マッチングを起動します:不要な二重パフォーマンスへの影響:ページ生成が遅くなり、不要なHTTPリクエストが追加されます

#2の問題はパフォーマンスです。すべてのページにスタイルを追加すると、不要な場合でも、すべてのページに追加のHTTPリクエストが追加されます。サーバー側のページ生成時間が影響を受けない場合でも、合計ページレンダリング時間はすべてのサイトページに影響します。

それでは、プラグイン開発者は何をすべきでしょうか?

最適なことは、オプションページをプラグインに追加することです。ユーザーは、ショートコードを単一ビューのみで処理するか、アーカイブで処理するかを選択できます。どちらの場合も、ショートポストを有効にする投稿タイプを選択する別のオプションを提供する方が適切です。

その方法で、"template_redirect"をフックして、現在のクエリが要件を満たしているかどうかを確認し、その場合はスタイルを追加できます。

ユーザーが単一の投稿ビューでのみショートコードを使用することを選択した場合、投稿にショートコードがあるかどうかを確認することをお勧めします。一度正規表現が1つだけ必要な場合は、ページをそれほど遅くしないでください。

ユーザーがアーカイブでもショートコードを使用することを選択した場合、投稿数がhighの場合、すべての投稿に対して正規表現を実行することを避け、クエリが要件に適合する場合はスタイルをキューに入れます。

この点で「高い」と見なすものは、いくつかのパフォーマンステストを使用するか、代わりに別のオプションを追加してユーザーに選択肢を与えることです。

25
gmazzap

私のプラグインのために私は時々 ポストメタデータに保存されているショートコードを持っているテーマビルダーを持っていることを発見しました 。これが私のプラグインのショートコードが現在の postまたはpost meta data にあるかどうかを検出するために使っているものです。

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' );
5
zdenekca

私はそうします:

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);
2

ショートコードがテキストウィジェットに存在する場合、私は自分のプラグインを見つけました。

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
Gino

WordPressには、特定のShortcode表示ステータスに基づいて何かをするための組み込み関数があります。関数名は 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' );
}
1
Arif Rahman

has_shortcode()zndencka に与えられたWordpressのページのサンプルコードの組み合わせを作りました。 has_shortcode関数がWordpress 3.6に追加されていることに気づいたので、最初にその関数が存在するかどうかを確認します。 wordpress自身の統計によると、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
Vasco