問題描述
我釋出了一個建立一個短程式碼的外掛,需要一個 JavaScript 檔案和一個 CSS 檔案來載入到包含該短程式碼的任何頁面上。我可以使所有頁面上的指令碼/樣式載入,但這不是最佳做法。我只想在呼叫短程式碼的頁面上載入檔案。我發現了兩種做法,但都有問題。
Method 1 在短程式碼處理函式內設定一個標誌為 true,然後檢查 wp_footer 回撥中的值。如果是這樣,它使用 wp_print_scripts()載入 JavaScript 。這樣做的問題是它只適用於 JavaScript 而不是 CSS,因為 CSS 應該在<head> 中宣告,<head> 只能在 init 或 wp_head 之類的早期掛鉤中進行。
Method 2 早點觸發,「前進」,看看當前頁面內容是否存在短碼。我喜歡這種方法比第一個好多了,但是它的問題是它不會檢測到模板是否呼叫 do_shortcode()。
所以,我傾向於使用第二種方法,然後嘗試檢測是否分配一個模板,如果是,則解析它的短碼。在我這樣做之前,我想檢查一下有沒有人知道一個更好的方法。
更新:我將解決方案整合到我的外掛中。如果任何人好奇看到它在現場環境中充滿活力,可以使用 download it 或 browse 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
- 將
$shortcode_used標誌設定為'no'。 - 在短碼功能本身,將
$shortcode_used標誌設定為'yes'。 - 設定一個
'the_content'鉤子優先順序12,這是在 WordPress 處理了短碼之後,並使用"_has_{$shortcode_name}_shortcode"鍵檢查''的後期後設資料。 (當帖子 ID 不存在後期元鍵時,返回''的值) 。 - 使用
'save_post'鉤子刪除後期元素清除該帖子的持久標誌,以防使用者更改短程式碼使用情況。 - 另外在
'save_post'鉤子中使用wp_remote_request()傳送一個 non-blocking HTTP GET 到自己的固定連結,以觸發到第一頁載入和持久標誌的設定。 - 最後設定
'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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。



