問題描述

我發佈了一個創建一個短代碼的插件,需要一個 JavaScript 文件和一個 CSS 文件來加載到包含該短代碼的任何頁面上。我可以使所有頁面上的腳本/樣式加載,但這不是最佳做法。我只想在調用短代碼的頁面上加載文件。我發現了兩種做法,但都有問題。

 Method 1 在短代碼處理函數內設置一個標誌為 true,然後檢查 wp_footer 回調中的值。如果是這樣,它使用 wp_print_scripts()加載 JavaScript 。這樣做的問題是它只適用於 JavaScript 而不是 CSS,因為 CSS 應該在<head> 中聲明,<head> 只能在 initwp_head 之類的早期掛鈎中進行。

 Method 2 早點觸發,「前進」,看看當前頁面內容是否存在短碼。我喜歡這種方法比第一個好多了,但是它的問題是它不會檢測到模板是否調用 do_shortcode()

所以,我傾向於使用第二種方法,然後嘗試檢測是否分配一個模板,如果是,則解析它的短碼。在我這樣做之前,我想檢查一下有沒有人知道一個更好的方法。

更新:我將解決方案集成到我的插件中。如果任何人好奇看到它在現場環境中充滿活力,可以使用 download itbrowse it

更新 2:從 WordPress 3.3 開始,現在可以直接在短碼回調中調用 wp_enqueue_script(),並在文檔的頁腳中調用 JavaScript 文件。這在 CSS 文件上也是可行的,但是由於在<head> 標籤之外輸出 CSS 違反了 W3C 規範,因此可能會導致瀏覽器出現 re-render 頁面。

最佳解決方案

根據我自己的經驗,我使用了方法 1 和 2 – 1 的架構和腳註腳本,以及 2 的’look-ahead’ 技術。

對於 look-ahead,我使用正則表達式代替 stripos; 個人喜好,速度更快,可以檢查’malformed’ 短碼;

preg_match( '#[ *shortcode([^]])*]#i', $content );

如果您擔心手動使用 do_shortcode 的作者,我會選擇指示他們使用動作調用手動排列您的 pre-registered 樣式。

更新:對於從來沒有 RTFM 的懶惰作者,輸出一個消息來突出顯示他們的方式的錯誤;)

function my_shortcode()
{
    static $enqueued;
    if ( ! isset( $enqueued ) )
        $enqueued = wp_style_is( 'my_style', 'done' ); // cache it so we don't repeat if called over and over

    // do shortcode
    $output = '';

    if ( ! $enqueued )
        // you can output the message on first occurence only by wrapping it in the previous if
        $output .= <<<HTML
<p>Attention! You must enqueue the shortcode stylesheet yourself if calling <code>do_shortcode()</code> directly!</p>
<p>Use <code>wp_enqueue_style( 'my_style' );</code> before your <code>get_header()</code> call inside your template.</p>
HTML;

    return $output;
}

次佳解決方案

我遲早會回答這個問題,但是由於 Ian 在 wp-hackers 列表上啓動了 this thread,所以讓我覺得值得回答,特別是考慮到我一直在計劃為我一直在開發的一些插件添加一個這樣的功能。

一種考慮的方法是檢查第一頁加載,以查看是否實際使用了短碼,然後將短碼使用狀態保存到後期元鍵。就是這樣:

Step-by-Step How-To

  1. $shortcode_used 標誌設置為'no'
  2. 在短碼功能本身,將 $shortcode_used 標誌設置為'yes'
  3. 設置一個'the_content'鈎子優先級 12,這是在 WordPress 處理了短碼之後,並使用"_has_{$shortcode_name}_shortcode"鍵檢查''的後期元數據。 (當帖子 ID 不存在後期元鍵時,返回''的值) 。
  4. 使用'save_post'鈎子刪除後期元素清除該帖子的持久標誌,以防用户更改短代碼使用情況。
  5. 另外在'save_post'鈎子中使用 wp_remote_request()發送一個 non-blocking HTTP GET 到自己的固定鏈接,以觸發到第一頁加載和持久標誌的設置。
  6. 最後設置'wp_print_styles',並使用"_has_{$shortcode_name}_shortcode"鍵檢查'yes''no'''的後期元數據。如果值為'no'不服務於外部。如果值為'yes''',則提供服務。

那應該這樣做。我已經編寫和測試了一個示例插件,以顯示這一切如何工作。

示例插件代碼

該插件在 [trigger-css]短代碼上喚醒,該代碼將頁面上的<h2> 元素設置為 white-on-red,以便您可以輕鬆看到它的工作。它假定 css 子目錄中包含 style.css 文件,其中包含此 CSS:

/*
 * Filename: css/style.css
 */
h2 {
  color: white;
  background: red;
}

下面是一個工作插件中的代碼:

<?php
/**
 * Plugin Name: CSS on Shortcode
 * Description: Shows how to conditionally load a shortcode
 * Author: Mike Schinkel <mike@newclarity.net>
 */
class CSS_On_Shortcode {

  /**
   * @var CSS_On_Shortcode
   */
  private static $_this;

  /**
   * @var string 'yes'/'no' vs. true/false as get_post_meta() returns '' for false and not found.
   */
  var $shortcode_used = 'no';

  /**
   * @var string
   */
  var $HAS_SHORTCODE_KEY = '_has_trigger-css_shortcode';
  /**
   *
   */
  function __construct() {
    self::$_this = $this;
    add_shortcode( 'trigger-css', array( $this, 'do_shortcode' ) );
    add_filter( 'the_content', array( $this, 'the_content' ), 12 ); // AFTER WordPress' do_shortcode()
    add_action( 'save_post', array( $this, 'save_post' ) );
    add_action( 'wp_print_styles', array( $this, 'wp_print_styles' ) );
  }

  /**
   * @return CSS_On_Shortcode
   */
  function this() {
    return self::$_this;
  }

  /**
   * @param array $arguments
   * @param string $content
   * @return string
   */
  function do_shortcode( $arguments, $content ) {
    /**
     * If this shortcode is being used, capture the value so we can save to post_meta in the 'the_content' filter.
     */
    $this->shortcode_used = 'yes';
    return '<h2>THIS POST WILL ADD CSS TO MAKE H2 TAGS WHITE ON RED</h2>';
  }

  /**
   * Delete the 'has_shortcode' meta value so that it can be regenerated
   * on first page load in case shortcode use has changed.
   *
   * @param int $post_id
   */
  function save_post( $post_id ) {
    delete_post_meta( $post_id, $this->HAS_SHORTCODE_KEY );
    /**
     * Now load the post asynchronously via HTTP to pre-set the meta value for $this->HAS_SHORTCODE_KEY.
     */
    wp_remote_request( get_permalink( $post_id ), array( 'blocking' => false ) );
  }

  /**
   * @param array $args
   *
   * @return array
   */
  function wp_print_styles( $args ) {
    global $post;
    if ( 'no' != get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * Only bypass if set to 'no' as '' is unknown.
       */
      wp_enqueue_style( 'css-on-shortcode', plugins_url( 'css/style.css', __FILE__ ) );
    }
   }

  /**
   * @param string $content
   * @return string
   */
  function the_content( $content ) {
    global $post;
    if ( '' === get_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, true ) ) {
      /**
       * This is the first time the shortcode has ever been seen for this post.
       * Save a post_meta key so that next time we'll know this post uses this shortcode
       */
      update_post_meta( $post->ID, $this->HAS_SHORTCODE_KEY, $this->shortcode_used );
    }
    /**
     * Remove this filter now. We don't need it for this post again.
     */
    remove_filter( 'the_content', array( $this, 'the_content' ), 12 );
    return $content;
  }

}
new CSS_On_Shortcode();

示例截圖

這是一系列的截圖

基本帖子編輯器,沒有內容

帖子顯示,沒有內容

基本帖子編輯器與 [trigger-css]短碼

後期顯示與 [trigger-css]短碼

不確定如果是 100%

我相信上述應該在幾乎所有的情況下工作,但正如我剛寫的這個代碼,我不能 100%肯定。如果你可以找到它不工作的情況,我真的很想知道,所以我可以修復代碼在一些我剛加入的插件。提前致謝。

第三種解決方案

谷歌發現我有潛力的 answer 。我説”potential” 在它看起來不錯,應該工作,但我不是 100%説服它是最好的方法:

add_action( 'wp_print_styles', 'yourplugin_include_css' );
function yourplugin_include_css() {
    // Check if shortcode exists in page or post content
    global $post;

    // I removed the end ' ] '... so it can accept args.
    if ( strstr( $post->post_content, '[yourshortcode ' ) ) {
        echo $csslink;
    }
}

這應該能夠檢查當前的帖子是否正在使用短碼,並將樣式表適當地添加到<head> 元素。但是我不認為它將適用於索引 (即循環中的多個帖子) 頁面… 它也是從一個 2 年的舊博客帖子,所以我甚至不確定它將與 WP 3.1.X 。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。