Image030
3 - 1
2016 - 1 (1)
2016 - 1
2016 - 1 (2)
1 - 1
IMG_20140308_204144
IMG_20140118_192943
15 - 1
15 - 1 (1)
13 - 1
11 - 1
IMG_0216
5 - 1
IMG_20140104_200337
IMG_20131229_125956
IMG_20131229_125543
namespace app\index\controller; // 引入Traits类(PHP5.5以上版本可以不需要) T('controller/View'); T('controller/Jump'); class Index { use \traits\controller\View; use \traits\controller\Jump; public function index(){ if(!IS_AJAX){ $this->error('非法操作'); }else{ $this->assign('name','thinkphp'); return $this->fetch('hello'); } } }
Trait是從PHP 5.4加入的一種細粒度代碼復用的語法。以下是官方手冊對Trait的描述:
Trait 是為類似PHP 的單繼承語言而準備的一種代碼復用機制。Trait 為了減少單繼承語言的限制,使開發人員能夠自由地在不同層次結構內獨立的類中復用method。Trait 和Class 組合的語義定義了一種減少複雜性的方式,避免傳統多繼承和Mixin 類相關典型問題。
Trait 和Class 相似,但僅僅旨在用細粒度和一致的方式來組合功能。無法通過trait 自身來實例化。它為傳統繼承增加了水平特性的組合;也就是說,應用的幾個Class 之間不需要繼承。
其實說通俗一點,就是能把重複的方法拆分到一個文件,通過use
引入以達到代碼復用的目的。
那麼,我們應該怎麼樣去拆分我們的代碼才是合適的呢?我的看法是這樣的:
Trait,譯作“特性”、“特徵”、“特點”。那麼問題就來了:什麼才是特性?
一個銷售公司有很多種產品:電視,電腦與鼠標墊,卡通手辦等。其中鼠標墊與卡通手辦是非賣品,只用於贈送。
那麼這裡的“可賣性” 就是一個特性,非賣品是沒有價格的。我們便可以抽像出“可賣性” 這個Trait 來:
trait Sellable
{
protected $price = 0;
public function getPrice()
{
return $this->price;
}
public function setPrice(int $price)
{
$this->price = $price;
}
}
當然我們所有的產品都會有品牌與其它基本屬性,所以我們通常會定義一個產品類:
class Pruduct
{
protected $brand;
//...
public function __construct($brand)
{
$this->brand = $brand;
}
public function getBrand()
{
return $this->brand;
}
//...
}
我們的電視與電腦類:
class TV extends Pruduct
{
use Sellable;
//...
public function play()
{
echo "一台 {$this->brand} 电视在播放中...";
}
//...
}
class Computer extends Pruduct
{
use Sellable;
protected $cores = 8;
//...
public function getNumberOfCores()
{
return $this->cores;
}
//...
}
而鼠標墊與手辦等禮品是不可賣的:
class Gift extends Pruduct
{
protected $name;
function __construct($brand, $name)
{
parent::__construct($brand);
$this->name = $name;
}
//...
}
上面的這個例子中,“可賣性” 便是部分商品的一個特性,也可以理解為商品的一個歸類。你也許會說,我也可以再添加一個Goods 類來完成上面的例子啊,Goods 繼承Product,再讓所有可賣的商品繼承於Goods 類,把價格屬性與方法寫到Goods 裡,同樣可以代碼复用啊。的確,這沒啥問題。但是你會發現:你有多個需要區別的特性時,由於PHP 只有單繼承的原因,你不得不組合很多個基類出來,將他們層疊,最終得到的樹狀結構是很複雜的。這也是Trait 所帶來的優勢:隨意組合,代碼清晰。
其實還有很多例子,比如可飛行的,那麼把飛行這個特性所具有的屬性(如:高度,距離)與方法(如:起飛,降落)放到一個trait就是一個合理的拆分。
trait 有什麼優勢?來看一段代碼:
class User extends Model
{
use Authenticate, SoftDeletes, Arrayable, Cacheable;
...
}
這個用戶模型類,我們引入了四個特性:註冊與授權、軟刪除、數組式操作、可緩存。
我們看到代碼的時候一眼便知道當前支持了哪些個特性。再看下面另外一種寫法:
abstract AdvansedUser {
// ... 实现了 Authenticate, SoftDeletes, Arrayable, Cacheable 的所有方法
}
class User extends AdvansedUser
{
...
}
你不得不再去閱讀AdvansedUser
的代碼才能理解。你想說沒有可讀性是因為我基類的名稱沒起好?可是,這種各種特性組合的一個基類是根本無法起一個見名知義的名稱的,不信你可以試一下。
就算你真的起了一個見名知義的名稱:AuthenticateCacheableAndArrayableSoftDeletesUser
,可是當需求變更,要求在FooUser
(同樣繼承了這個基類)中去除緩存特性,而User
類保留這個特性,怎麼辦?再創建一個基類麼?
這就是我理解的Trait:
它不僅僅是可複用代碼段的集合,它應該是一組描述了某個特性的的屬性與方法的集合。它的優點在於隨意組合,耦合性低,可讀性高。
平常寫代碼的時候也許怎麼拆分才是大家的痛點,分享以下幾個技巧:
總之一定要記住:不要為了讓兩段相同的代碼提到一起這樣簡單粗暴的方式來拆分。
轉載自:
http://overtrue.me/articles/2016/04/about-php-trait.html
稍有接觸過WordPress佈景或外掛客製修改的朋友,對WordPress的Hook機制應該不陌生,但通常剛接觸WordPress Hook的新手,對其運作原理可能會有點混亂或糢糊。本文針對WordPress Hook運作大致做個簡單的說明,而預設讀者是理解基本的PHP function語法及運作,但對WordPress Hook機制不是很明白。
先從「登場角色」的個別說明開始:
指的是WordPress內建的程式碼架構,提供WordPress主要的基本功能。
也許你早已聽說,Hook本身雖是鈎子的意思,但直譯又有點奇怪,所以一般通常都不直譯它,而是直接稱它Hook。WordPress的Hook也可以想像成「鈎子」,這些「鈎子」會埋在WordPress網站中特定幾處的程式碼中,埋進去時使用的語法,其「標示位置」的意義比較大,沒有實質運作的內容。當程式執行到有埋Hook的地方時,它會找出所有對應到自己的Hook Function (也就是所有「鈎到」該Hook的hook function),並一一執行。
因此若沒有針對此Hook去「加入」要鈎上去的Hook Function,執行到此什麼也不會做。因此,它等於是WordPress核心預留一個執行的機會給未來想要加入客製功能的開發者。
Hook Function裡會有實質運作的內容,即是實作了一些客製功能,可能是存取DB、增加HTML code、執行其他函式…等。我們在Hook Function裡寫好所需的功能後,就可以利用「加入至對應Hook」的語法,把Hook Function自已鈎到該Hook上,使得該Hook被執行到時,也會連帶執行自己。
舉個例子,我們拿wp_head及wp_footer這兩個內建的hook來說明,wp_head這個hook就是用來埋在負責輸出標籤的程式碼中,而wp_footer就是用來埋在輸出頁尾的程式碼中 (定義於wp-includes/general-template.php,用wp_head()及wp_footer()包裝起來)。這兩個hook,主要都是在佈景檔案中使用的,常見會出現在header.php及footer.php中。
請看下面的情境示例圖,我們把wp_head及wp_footer看成是「鈎子」,而別的hook functions就能來鈎住它:
我們馬上來寫一個簡單的例子。我們要寫一個hook function,就叫它print_sth(),然後把它鈎上wp_head這個hook。因為wp_head()的內容實際上就只有do_action(‘wp_head’); 這一行內容,而wp_footer()的內容也只有 do_action(‘wp_footer’);,所以我們直接把do_action的語法換到圖上去,比較容易做說明,因此示意圖變成:
如此,只要執行到輸出header.php時,就會執行到wp_head(),就如同執行到do_action(‘wp_head’),此時WP核心會去找所有「鈎上」wp_head這個hook的hook function,於是就找到我們寫的print_sth(),然後就執行它,所以結果它做的事就會出現在網站上,也完成了「客製」的動作:
簡單的說,Hook機制就是:WP核心或其他plugin、theme提供想客製功能的人一個置入客製程式碼(Hook Function)到特定的執行時間點(Hook)的機會。
WordPress中的Hook有兩種,分別是「Action Hook」及「Filter Hook」,我們剛才舉例的wp_head及wp_footer都是屬於Action Hook。不過,一開始你可以先把這兩種Hook看成是一樣的東西,只是Filter多了一點點不同的特色,接著說明。
WP核心 (或佈景、外掛)在做它們該做的事時,如果執行到有埋action hook的程式碼 (即是do_action語法) 時,會去找尋對應到的hook functions,進而執行這些hook functions(即那些透過add_action()來加入的hook functions),藉此完成客製功能。WP核心並不期待Action Hook functions會有回傳值,所以這裡的hook function只被視為一個「獨立切出來運作的功能」。
WP核心做它該做的事,你做你想做的事,做完就各自結束。
跟Action Hook一樣,WP核心 (或佈景、外掛)在做它們該做的事時,如果執行到有埋filter hook的程式碼 (即是apply_filters語法) 時,就會去找尋對應的hook functions,進而執行這些hook functions(即那些透過add_filter()來加入的hook functions),藉此完成客製功能。與Action Hook不同之處是,所有「鈎上」Filter Hook的hook functions通常都會接收到參數,而WP核心會期待你拿到它提供的參數,並做完你想做的事後,要回傳(return)一個值,讓WP核心再利用你回傳的值來接著完成它該做的事。
透過你的干涉,修改了WP核心丟給你的參數,WP核心再接著拿你改過的參數,繼續完成它該做的事,此動作就像「過濾」的動作,因而得名filter。
比較一下兩種Hook在埋進某處程式碼時所用的語法,假設我們在某處 (可能是在輸出頁首的程式碼處,或輸出文章標題、文章內容、側邊欄…等地方,要「出現客製效果」的地方)埋下這兩種hook:
/*--------------- Action Hook ---------------*/ // 埋下一個名叫'do_more'的action hook do_action('do_more'); /*--------------- Filter Hook ---------------*/ // 埋下一個名叫'get_special'的filter hook,注意它會有回傳值 $c = apply_filters('get_special',$a, $b);
然後我們可以在某處 (可能是其他外掛、functions.php等處,要「實作客製功能」的地方) 實作對應的hook function:
/*--------------- Action Hook Function---------------*/
// 增加要鈎上'do_more'這個hook的hook function,
// 並為此hook function取名叫more_func。
// 第一個參數是hook名稱、第二個是hook function名稱
add_action('do_more', 'more_func');
// 實作more_func的內容,不需回傳值
function more_func()
{
echo 'do more thing...';
}
/*--------------- Filter Hook Function ---------------*/
// 增加要鈎上'get_special' hook的hook function,
// 並為此hook function取名叫special_func。
// 參數1是hook名稱、參數2是hook function名稱
// 參數3是Priority(優先序)、參數4是hook function參數的數目
add_filter('get_special', 'special_func', 10, 2);
// 實作special_func的內容,需要給它回傳值
function special($a, $b)
{
$c = $a.' & '.$b; //做一些事,例如把兩個參數連接起來
return $c; //回傳值
}
所以其實兩種Hook的運作方式幾乎一樣,只差在增加Action Hook函式不需回傳值,而增加Filter Hook function時,你必須要回傳一個值。所以Filter Hook函式通常都有提供參數,讓想客製的人可以取得它,處理後再回傳。
但如果有一個Filter Hook,它沒有任何hook function有去鈎它,它該怎麼取得回傳值?答案是,直接拿第一個它給的參數,以上面的例子來說,它會直接拿$a丟進$c。另外,其實我們也可以把filter寫的跟action一樣,只要不回傳值就行,但action hook就沒辦法「模仿」filter hook,因為無法取得回傳值。
如果有很多地方(plugin或者佈景functions.php)都add同一個hook,會怎麼決定出現順序?等案很顯然是可以透過Hook Function的Priority參數來作優先序的設定:
就像我們剛才說明的例子中,我們使用add_filter加入special_func時設定的優先序是10,這也是Priority參數的預設值。如果你希望它能優先被執行,就設定小於10的數字,反之,就設個100、500之類的,讓它延後被執行。
但其實這裡有個隱含的衝突問題。
以wp_head這個hook為例,如果我寫了一個外掛,希望透過wp_head來輸出「增加a.css檔案」的HTML語法,而a.css會重新設定body元素的樣式,所以我希望它可以最後才被匯入,不要被其他css檔干擾,於是我將Priority設為900,但我怎麼知道Priority 900夠不夠大?若某個WP網站,它除了安裝我的外掛,也安裝了其他外掛,而其他外掛剛好也重新設定body元素的樣式,然後把Priority設為950,此時我寫的外掛在處理body樣式時就出事了,於是就跟其他外掛衝突了。
所以此時我們需要了解的是:我的WP網站可能裝了很多外掛,我怎麼知道同一個Hook被加了多少Hook Function,而每個Hook Function的Priority被設定為多少?
答案是,我們可以透過$wp_filters這個global變數來取得所有hook的資訊,像是如下的function:
// 列出所有的hook function及其priority
function list_hooked_functions($tag=false)
{
global $wp_filter;
if ($tag)
{
$hook[$tag]=$wp_filter[$tag];
if (!is_array($hook[$tag]))
{
trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
return;
}
}
else
{
$hook=$wp_filter;
ksort($hook);
}
echo '
<pre>';
foreach($hook as $tag => $priority)
{
echo "
>>>>>t<strong>$tag</strong>
";
ksort($priority);
foreach($priority as $priority => $function)
{
echo $priority;
foreach($function as $name => $properties) echo "t$name
";
}
}
echo '</pre>
';
return;
}
當我們呼叫 list_hooked_functions(‘wp_head’); 時,就會列出wp_head這個Hook所鈎住的所有hook function,可以看到priority 10之後有好幾個都沒有數字,因為它們都沒有特別指定priority,所以都是10,包括我們剛才寫的print_sth也在其中:
>>>>> wp_head
1 wp_enqueue_scripts
2 feed_links
3 feed_links_extra
8 wp_print_styles
9 wp_print_head_scripts
10 rsd_link
wlwmanifest_link
index_rel_link
parent_post_rel_link
start_post_rel_link
adjacent_posts_rel_link_wp_head
locale_stylesheet
wp_generator
rel_canonical
wp_shortlink_wp_head
print_sth
wp_admin_bar_header
_admin_bar_bump_cb
所以,衝突很難提早避免,但發生衝突時,可以預先思考有沒有可能是因為priority的設定,導致結果跟預期不符合。
轉自http://www.mrmu.com.tw/2011/10/10/wordpress-hook/
以下文章來自 Ptt實業坊
作者: megabio (LifeIsKuso) 看板: PHP
標題: [心得] php 的 session 運作流程,實驗觀察心得
時間: Sun Nov 15 13:02:45 2009
一切是從這段話開始的 :
“為什麼我修改了 gc_maxlifetime,還是沒有因為閒置而登出呢?”
隨便 google 一下就有很多討論區問過類似的問題
我自己本人對於 PHP 的 session 機制也是一知半解
所以打算以所學到的知識 + 動手實驗的方式
找出自己不清楚,疑惑的地方
作業環境是 Windows XP + Xampp 整合包 (http://tinyurl.com/lv287y)
★★★ 實驗開始 ★★★
首先新增一個 php 程式,以 session_start() 啟動 session
client browser 會寫入一個 cookie 叫做 “PHPSESSID” 內容是一長串亂碼
代表此 session 獨一無二的編號
server 端會在 “/tmp” (此數值設定在 php.ini 的 session.save_path) 這個目錄下寫
入 sess_* 的檔案
sess_* 後面的亂碼就是剛才 cookie 的編號,打開這個檔案,發現裡面沒有東西
再來我們在 php 程式中建立一個 session 變數,$_SESSION[‘user’] = ‘guest’
打開 sess_* 這個檔案,發現裡面多了以下內容 : user|s:5:”guest”;
現在我們了解,PHP 藉由 sess_* 來儲存我們建立的 $_SESSION 變數
並且跨網頁傳遞這些變數
★★★ 實驗二 : 觀察 session 垃圾回收機制 ★★★
為了方便觀察,修改 php.ini 的以下設定
session.gc_probability = 100 session.gc_divisor = 100 session.gc_maxlifetime = 30
按照上面的設定。每次有人瀏覽網站時,PHP 就會檢查 “/tmp” 底下的 sess_* 檔案
如果有 “閒置” 超過 30 秒的 session,server 有 100% 的機率會將它刪除
有趣的部份在於 PHP 判斷 “閒置” 的條件是什麼呢? 我做了以下的實驗
第一步 : 寫兩個 php 程式
(1) login.php
(2) refresh.php
開啟 login.php 註冊一個 $_SESSION 變數,然後導向到 refresh.php
我們用 refresh.php 觀察 $_SESSION 變數是否逾期
第二步 :
先用一種 browser 開啟 login.php,此時會直接導向到 refresh.php
30 秒後我們按 F5 重整頁面,發現 session 依然還在
第三步 :
我們在同一台電腦上,開啟三種不同的 browser,並且都開啟 login.php
30 秒後,我們先重整第一個 browser 的頁面,session 一樣還在,和第二步的結果相同
但是當我們換到第二個和第三個 browser 的時候,按 F5 重整頁面發現 session 已經消
失了,”/tmp” 底下,這兩個 browser 的 sess_* 也不見了
從這裡我們可以得到結論,session.gc_maxlifetime 的確是用來清除閒置 session 的機
制,只不過和一般人所想的有些不同,它是用來清除 “別人” 的閒置 session
★★★ 我們可以想像一下 PHP 的處理過程 ★★★
(1) browser A,B,C 都連上 server 開啟 session
並且在 server 的 “/tmp” 當中留下 sess_* 檔案
(2) 30 過後,browser A 先重整頁面,對 server 提出連線要求
(3) server 檢查 “/tmp” 底下的 sess_* 發現有 browser A 的 session id
於是判定這個 sess_* 不是垃圾
(4) 至於其他的 sess_*,由於都已經超過 gc_maxlifetime 沒上來連線
所以這些 sess_* 有 100% 的機率被當成垃圾處理
* 那個 100% 的機率是我們在 php.ini 修改的設定 :
session.gc_probability = 100 (分子) session.gc_divisor = 100 (分母)
★★★ 結論 ★★★
PHP 踢除閒置 session 的機制就是 “先搶先贏”
超過閒置時間誰先上來連線,就判定 safe
其餘的,就看 PHP 的心情 (機率) 而定,心情不好時 (100%) 就通通踢除
經過實驗我清楚的了解到,PHP 預設的 session 垃圾回收機制其實是蠻合理的
24 分鐘後,有 1% 的機率刪除沒來連線的 sess_* 這的確符合大部分網站的流量負荷
★★★ 參考連結 ★★★
http://www.jollen.org/php/216_session_cookies/ (中文)
http://blog.wu-boy.com/2008/11/18/608/ (中文)
http://tinyurl.com/4fleql (中文)
http://chensh.loxa.edu.tw/php/X_17.php (中文)
http://www.captain.at/howto-php-sessions.php (英文)
http://tinyurl.com/yk53ndb (英文)
第一次用電腦畫素描,感覺線條有點生硬,手寫筆較細,難用.玻璃平面太滑
—–
工具:
Thinkpad X1 Yoga 2048 壓感
軟件:
Autodesk SketchBook
為 #澳門醉龍 畫的海報~~
科普:
舞醉龍,又稱醉龍舞或舞木龍,是流行於古香山縣(今中山、珠海、澳門)一帶的活動。一般於每年農曆四月初八,即佛誕節舉行。2006年被廣東省人民政府列為省級第一批非物質文化遺產代表作名錄。
澳門的舞醉龍是由魚商舉辦的,魚行在四月初八、初九休息。參加者首先在三街會館舉行開光典禮。舞者一邊飲用米酒,使自己醉倒,一邊手持木製的龍頭和龍尾舞動,在各區巡遊。
《再見,地球。》 — 因去年看了橫琴長隆的白鯨表演,雖然早有耳聞鯨類通曉人性,但親身觀看後才會更加深刻,因而對日本以科研理由重啟鯨類捕食行為更為憤概。 這幅畫的構思便是基於人類活動對鯨魚的死亡的慚悔和祈禱,愿它們的靈魂能獲得自由,並且能”飛”出地球去尋找更美好的歸屬地。 畫中的女子為地球化身,以安撫它們的靈魂和離開時不舍的心情。全畫以冷色調為主,襯托淡淡的憂傷。亦以平行線方式上色, 愿逝者靈魂得以安息的渴望。