延續上一張沒有講完的,filter其實與action大同小異,但是filter在使用的時候,是會有值經過filtered,這也讓所有的filter在使用時,會將處理過的值回傳,而九成的filter使用方式與action大同小異,甚至是array那些的都是差不多的,所以我們就跳過apply_filter
與add_filter
,我們用一段示範如何使用add_filter來當快速的概論。
function wporg_filter_title( $title ) {
return 'The ' . $title . ' was filtered';
}
add_filter( 'the_title', 'wporg_filter_title' );
這個函式是可以回傳當下執行的filter名稱,如果你有遇到一個hook有掛上非常多的filter的話,這個很適合來確定現在的處理狀況,假設你想學學阿共把一些字眼消失掉的話,我們也可以使用使用這個功能來做到。
add_filter('the_content','ccp_like_nofrex');
add_filter('the_title','ccp_like_nofrex');
function ccp_like_nofrex( $text ) {
$words = [];
if ( 'the_content' === current_filter() ) {
$words = ['free'];
}else if( current_filter() === ' the_title')$words = ['ccp'];
if ( $words ) {
$text = str_replace( $words, 'none', $text );
}
return $text;
}
wordpress提供了這幾種的語法糖,不只是向其他能夠使用FIOE,他提供的是假設你今天是要清空預設的資料,像是非使用者要來要資料,你可以利用以下清單的來中家做回傳,而不在需要再多註冊一個新的function,讓程式碼看了更冗長,而下面的的選項你會發現有兩個底線,這是個wordpress的簡潔回傳的特別記號,很好讓去辨識,你也可以看到在core中有很多這種使用方式!
__return_true(): 回傳 bool true
__return_false(): 回傳 bool false
__return_zero(): 回傳Integer 0
__return_empty_array(): 回傳空陣列
__return_null(): 回傳null
__return_empty_string(): 回傳一個空字串 ""
add_filter( 'the_content', '__return_empty_string' );
看了我們上面的範例,可以看到這個對--思想控制--過濾內容是特別好用的,想想看那些x週刊說要加入會員才能看見,不就可以藉由這個來製作,再搭配transients來確保他們沒有偷輕快取,做到一週只能看幾次,跟某xxxxtube一樣的高度呀!我們可以做一個簡單的應用,火傳媒的訂閱功能,不過沒有要鎖別人的內容就只是求訂閱而已,如果再加上cookie的設定,就可以變成會員限定了,至於email的部分,自己動手做一下就可以啦!
add_filter( 'the_content', 'gogo_power_ranger_content_subscription_form', PHP_INT_MAX );
function gogo_power_ranger_content_subscription_form( $content ) {
if ( is_singular( 'post' ) && in_the_loop() ) {
$content .= '<div class="subscription">
<p>感謝閱讀火傳媒的文章,你的訂閱,讓新聞像火依樣,照耀著你的霧氣.</p>
<form method="post" action="自己寫">
<p>
<label>
Email:
<input type="email" value=""/>
</label>
</p>
<p>
<input type="submit" value="Submit"/>
</p>
</form>
</div>';
}
return $content;
}
這一個是能偵測模板是否已經被呼叫了,而且在registed了,怎麼用?看下來,我們假設有一個新的模板叫做protfolio
,並且假設他已經被註冊了。
add_filter( 'template_include', 'portfolio_page_template', 99 );
function portfolio_page_template( $template ) {
if ( is_page( 'portfolio' ) ) {
$new_template = locate_template( array( 'portfolio-page-template.php' ) );
if ( '' != $new_template ) {
return $new_template ;
}
}
return $template;
}
當你想要增加filter與action到你的class之中,與原本你只需要reference到你自己的function不同,你所需要使用的語法就不同,我們使用的參數會需要我們以下的帶入方式,來確保我們class中的method被執行,並且reference到你的class,而我們的規則就是用個陣列將其包起,這邊把add_action換成add_filter也是同理,而如果你有更多的參數,就是以[$class,$method]
的方式繼續增加。
add_action($tag , [$class,$method]);
此例提示拿之前的boot來當例題,並且將class的method加入進filter裡頭,而就算你要在class中增加filter,也是一樣的方式,只是把class改成$this,讓在存取的當下指到正確的reference。
<?php
namespace gogo_power_ranger;
class Gym {
public static function init(){
add_filter('the_content',array($this,'gogo_power_ranger_content_subscription_form'))
}
public static function randomize( $query ) {
if ( $query->is_main_query() && $query->is_home() ) {
$query->set( 'orderby', 'rand' );
}
}
public function gogo_power_ranger_content_subscription_form( $content ) {
if ( is_singular( 'post' ) && in_the_loop() ) {
$content .= '<div class="subscription">
<p>感謝閱讀火傳媒的文章,你的訂閱,讓新聞像火依樣,照耀著你的霧氣.</p>
<form method="post" action="自己寫">
<p>
<label>
Email:
<input type="email" value=""/>
</label>
</p>
<p>
<input type="submit" value="Submit"/>
</p>
</form>
</div>';
}
return $content;
}
}
add_action( 'pre_get_posts', [ 'gogo_power_ranger\Gym', 'randomize' ] );
Wordpress中並沒有限制增加多少hooks,也沒有限制一個hook能夠接上多少個function,我們從上述的主要兩個之中,我們可以使用do_action
或apply_filters
來放入我們相對應的位置,就像core提供給我們一樣,我們也提供給其他要修改我們外掛的人更大的彈性,使用自己的hook好處多多,最大的好處是在hook這種外掛的生態系上,別人的開發邏輯都是掛上適當的hook來讓自己的外掛保有可變性,假如你是個開源軟體,你希望自己的外掛能夠讓更多的開發者去做開源,進而讓你的外掛像是以一灘活水的方式繼續在生態圈流淌,那麼你需要的是好好坐下來看看,評估哪一段程式碼該加入hook,讓其餘人直接使用就可以加上。
而適當的使用filter來做一些值得回傳,更可以讓使用者更容易地去理解,你的功能是否有很好的匹配性,去與其他的程式碼做支援,而這個議題也是個很重要的開源想法,你在開發自己的外掛時,哪些資料是可以被允許add_filter的,又有哪些是的算寫在action只有提取,避開讓人直接去修改的,是個大哉問!我們拿Wp的範例來說說,我們自己加了這一個filter。
add_action( 'init', 'hook_init' );
function hook_init() {
do_action( 'gogo_power_ranger_init_before' );
// Run setup code.
do_action( 'gogo_power_ranger_init_after' );
}
do_action('gogo_power_ranger_init_before');
do_action('gogo_power_ranger_init_after');
我們有上面的基礎,現在我們要自己掛一個hook來使用,設定你要使用的位置,再來設計你該怎麼實作以及註冊,可以看見下方的用法,我們還要確保我們的獨一性加上自己的前綴。
function shown_text() {
$text = apply_filters(
'ranger_example_text',
'ppap',
);
echo $text;
}
add_filter( 'ranger_example_text', 'gogo_power_ranger_replace_text',10,1);
function gogo_power_ranger_replace_text($text){
return $text." powered by gogo power ranger";
}
變數hook,這是個比較有趣也比較有效能的使用,但是加入的方式可能,這個範例使用了post_type來做到每個type有不同的hook,而這個其實對於reuse有很大的好處就可以由此可知,wordpress在core中也是有很多的varirable hook,這些可以讓使用在相對應的情況之下,使用到正確的hook,就如同我們下方的post來當作練手,可以針對不同的形態來做,而在不同的型別中,執行不同的hook與相對應的的資料做處理,也是一個在效能調校上,如果current_filter有太多太多的選擇項的最好替代方案。
do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
Plugin Api 相信是最重要也是最容易的環節了,也是大家比較熟悉的部分,想想試著要去建立的pluigin不管內容複雜與否總是有hook牽扯上非常多的關係,不過既是最容易也就是難去精深的,多看多懂才是王道,source code這種東西,一定是重複看的次數多了,心得才多,就跟當時張無忌在悟得乾坤大挪移的時候,霹哩啪拉一頭熱的練功。
本來預計明天開始來講前端的資源要怎麼匯入到我們的外掛之中,那還有作用域之類的概念與polyfills,並且提到該怎麽處理前端頁面舊資料快取的問題,不過我思索了一下想先講一下Privacy
在處理一些個人資料與訪客資料的利用,感覺更可以讓剛學玩hook有更好的發揮,此外,我在這邊也推薦找到了一個youtube 也是在講解程式的頻道,裡頭有一個playlist是講了60幾章,開發wordpress外掛的教學影片,有興趣可以點擊這裡觀看。
wordpress - template_include
wordpress - API/Action Reference
鐵人賽 - 艾瑞克講解 filter
Julio Potier
Using add_filter inside another class
WordPress Actions, Filters, and Hooks : A guide for non-developers