【php5.3的新增、改進】匿名函數
也叫閉包(closures), 經常被用來臨時性地建立一個無名函數,用于回調函數等用途。
$func = function ($arg) {
print $arg;
};
$func("hello world");
匿名函數還可以用 use 關鍵字來捕捉外部變量:
function arrayplus($array, $num)
{
array_walk($array, function (&$v) use ($num) {
$v += $num;
});
}
上面的代碼定義了一個 arrayplus() 函數(這不是匿名函數), 它會将一個數組($array)中的每一項,加上一個指定的數字($num).在 arrayplus() 的實作中,我們使用了 array_walk() 函數,它會為一個數組的每一項執行一個回調函數,即我們定義的匿名函數。在匿名函數的參數清單後,我們用 use 關鍵字将匿名函數外的 $num 捕捉到了函數内,以便知道到底應該加上多少。
後期靜态綁定php的繼承模型中有一個存在已久的問題,那就是在父類中引用擴充類的最終狀态比較困難。
<?php
class parentbase
static $property = 'parent value';
public static function render()
{
return self::$property;
}
class descendant extends parentbase
static $property = 'descendant value';
//output: parent value
echo descendant::render();
在這個例子中,render()方法中使用了self關鍵字,這是指parentbase類而不是指descendant類。在 parentbase::render()方法中沒法通路$property的最終值。為了解決這個問題,需要在子類中重寫render()方法。通過引入延遲靜态綁定功能,可以使用static作用域關鍵字通路類的屬性或者方法的最終值
return static::$property;
public static function status()
static::getstatus();
protected static function getstatus()
echo "person is alive";
//output: descendant value
php的面向對象體系中,提供了若幹“魔術方法”,用于實作類似其他語言中的“重載”,如在通路不存在的屬性、方法時觸發某個魔術方法。
__call($funcname, $arguments)
__callstatic($funcname, $arguments)
參數說明:
$funcname string 調用的不存在的方法名稱。
$arguments array 調用方法時所帶的參數。
__invoke魔術方法會在将一個對象作為函數調用時被調用:
class a
public function __invoke($args)
print "a::__invoke(): {$args}";
$a = new a;
//output: a::__invoke(): hello world
$a("hello world");
__callstatic則會在調用一個不存在的靜态方法時被調用,有了__callstatic,可以省不少代碼了。而且這個方法支援在子類中調用,配合上get_called_class,子類也一起魔術了
class activerecordbase
/** as of php 5.3.0 */
public static function __callstatic($func, $arguments)
if ($func == 'getbyid') {
$id = $arguments[0];
return get_called_class() . '(' . $id . ')';
}
throw new exception('invalid method : ' . $name);
class person extends activerecordbase
// output: person(123)
echo person::getbyid(123);
__call 當要調用的方法不存在或權限不足時,會自動調用__call 方法。
class db
private $sql = array(
"field" => "",
"where" => "",
"order" => "",
"limit" => "",
"group" => "",
"having" => "",
);
// 連貫操作調用field() where() order() limit() group() having()方法,組合sql語句
function __call($methodname, $args)
// 将第一個參數(代表不存在方法的方法名稱),全部轉成小寫方式,擷取方法名稱
$methodname = strtolower($methodname);
// 如果調用的方法名和成員屬性數組$sql下标對應上,則将第二個參數給數組中下标對應的元素
if (array_key_exists($methodname, $this->sql)) {
$this->sql[$methodname] = $args[0];
} else {
echo '調用類' . get_class($this) . '中的方法' . $methodname . '()不存在';
// 傳回自己對象,則可以繼續調用本對象中的方法,形成連貫操作
return $this;
// 輸出連貫操作後組合的一個sql語句,是連貫操作最後的一個方法
function select()
echo "select {$this->sql['field']} from user {$this->sql['where']} {$this->sql['order']} {$this->sql['limit']} {$this->sql['group']}
{$this->sql['having']}";
$db = new db();
// 連貫操作
$db->field('sex, count(sex)')
->where('where sex in ("男","女")')
->group('group by sex')
->having('having avg(age) > 25')
->select();
?>
命名空間一個最明确的目的就是解決重名問題,php中不允許兩個函數或者類出現相同的名字,否則會産生一個緻命的錯誤。這種情況下隻要避免命名重複就可以解決,最常見的一種做法是約定一個字首。
//建立空間blog
namespace blog;
class comment
//非限定名稱,表示目前blog空間
//這個調用将被解析成 blog\comment();
$blog_comment = new comment();
//限定名稱,表示相對于blog空間
//這個調用将被解析成 blog\article\comment();
$article_comment = new article\comment(); //類前面沒有反斜杆\
//完全限定名稱,表示絕對于blog空間
$article_comment = new \blog\comment(); //類前面有反斜杆\
$article_comment = new \blog\article\comment(); //類前面有反斜杆\
//建立blog的子空間article
namespace blog\article;
别名和導入可以看作是調用命名空間元素的一種快捷方式。php并不支援導入函數或常量。 它們都是通過使用use操作符來實作:
//建立一個bbs空間(我有打算開個論壇)
namespace bbs;
//導入一個命名空間
use blog\article;
//導入命名空間後可使用限定名稱調用元素
$article_comment = new article\comment();
//為命名空間使用别名
use blog\article as arte;
//使用别名代替空間名
$article_comment = new arte\comment();
//導入一個類
use blog\article\comment;
//導入類後可使用非限定名稱調用元素
$article_comment = new comment();
//為類使用别名
use blog\article\comment as comt;
$article_comment = new comt();
php5.4
數組簡寫形式
//原來的數組寫法
$arr = array("key" => "value", "key2" => "value2");
// 簡寫形式
$arr = ["key" => "value", "key2" => "value2"];
traits
所謂traits就是“構件”,是用來替代繼承的一種機制。trait和類相似,但不能被執行個體化php中無法進行多重繼承,但一個類可以包含多個traits.
trait sayworld
public $var = 'test';
public function sayhello()
echo 'world!';
class myhelloworld
// 将sayworld中的成員包含進來
use sayworld;
$xxoo = new myhelloworld();
// sayhello()函數是來自sayworld構件的 $xxoo->var
$xxoo->sayhello();
traits還有很多神奇的功能,比如包含多個traits, 解決沖突,修改通路權限,為函數設定别名等等。
新增在執行個體化時通路類成員的特征:
(new myclass)->xxoo();
新增支援對函數傳回數組的成員通路解析
print [1, 2, 3][0];
php5.5
yield的一個功能就是能有效的降低疊代的記憶體開銷,yield關鍵字用于當函數需要傳回一個疊代器的時候, 逐個傳回值.也就是說, 每當産生一個數組元素, 就通過yield關鍵字傳回成一個, 并且函數執行暫停, 當傳回的疊代器的next方法被調用的時候, 會恢複剛才函數的執行, 從上一次被yield暫停的位置開始繼續執行, 到下一次遇到yield的時候, 再次傳回.
function generators()
for ($i = 1; $i <= 10; $i += 1) {
yield $i;
foreach (generators() as $v) {
echo $v;
可以用 list() 在 foreach 中解析嵌套的數組:
$array = [
[1, 2, 3],
[4, 5, 6],
];
foreach ($array as list($a, $b, $c))
echo "{$a} {$b} {$c}\n";
aaa