/ PHP

[php tech.] PHP 5 工作筆記

雖然寫這種東西點閱率應該很低,不過,可以充很大的版面(沒有誤),也算是功德一件。

這次要筆記的東西,是 PHP 5 的一些新東西,還有順便是從 TextCube Night build 中找到的一些新玩意。俗話說得好,拷貝是學習的不二法門 (肯定的),但是單純的拷貝並不會進步,我作筆記總可以吧 (哈哈哈)。

首先是 Abstract Class (抽象類別)Interface (介面) 的介紹,在 php.net 裡面對於 Interface 的介紹少之又少,所以跑去問問估狗大神,還不少資料,繁簡體都有。

我這邊整理一下。

Interface 只是定義一個介面,這個介面裡面可以放 private, public, protected 三種類型的函式、變數。當然,除了 public 之外,除非必要,我想大概不會想放其它兩種。都要用來 implements 了,不 public 的話要怎麼 implements 呢 (笑)。

implements (實作) 跟 extends (繼承或衍生,因程序而異) 這兩者應該不難見,只是 extends 好像比較常見就是。

以下整理自出處:http://ronnywang.pixnet.net/blog/post/19130725

我在這邊另外附上實作範例,幫助了解。

interface Iterator {
    public function rewind();
   public function current();
   public function key();
   public function next();
   public function valid();
}

interface IteratorAggregate {
    public function getIterator();
}

IteratorIteratorAggregate 兩者,是一種迴圈介面,可以被 foreach 或是 for 迴圈使用。後者是指定迴圈最大值 (總值),並傳回給前者,當然,這樣的回傳動作需要 implements Class 去做,以下給各位一個實作範例比較清楚。另外,這兩種 (甚至接下來回提到的 Interface 都是 PHP 5 已經內建的,不需要再定義了)。

<?php
class CI implements Iterator {
    private $obj;
    private $num;

    public function __construct($obj) {
        $this->obj = $obj;
    }
    public function rewind() {
        $this->num = 0;
    }
    public function valid() {
        return $this->num < $this->obj->max;
    }
    public function key() {
        return $this->num;
    }
    public function current() {
        switch($this->num) {
           case 0: return "1st";
           case 1: return "2nd";
           case 2: return "3rd";
           default: return $this->num."th";
        }
    }
    public function next() {
        $this->num++;
    }
}

class CIA implements IteratorAggregate {
   public $max = 1;
   public function getIterator() {
       return new CI($this);
   }
}
// class CI 與 CIA 是自己取的名稱(這是廢話吧)
$obj = new CIA;
// 指定這個 IteratorAggregate 的最大值(在 Class CIA 裏面我預設給 1 而已)
$obj->max = 10;

// 使用 foreach 
echo '使用 foreach...<br /> ';
foreach($obj as $key => $val) {
   echo $key,' = ',$val,'<br />';
}

// 相當於使用 for 迴圈的用法
echo '相當於使用 for 迴圈的用法...<br /> ';
$it = $obj->getIterator();
for($it->rewind(); $it->valid(); $it->next()) {
   $val = $it->current();
   $key = $it->key();
   echo $key,' = ',$val,'<br />';
}
unset($it);

/* 顯示結果

使用 foreach...
0 = 1st
1 = 2nd
2 = 3rd
3 = 3th
4 = 4th
5 = 5th
6 = 6th
7 = 7th
8 = 8th
9 = 9th
相當於使用 for 迴圈的用法...
0 = 1st
1 = 2nd
2 = 3rd
3 = 3th
4 = 4th
5 = 5th
6 = 6th
7 = 7th
8 = 8th
9 = 9th
*/

Countable 可以將 implements class 做 count 使用。

interface Countable {
   public function count();
}
<?php
class CI implements Countable {
    private $intCount = null;
    public function __construct($intCount){
        $this->intCount = $intCount;
    }
    public function count(){
        return $this->intCount;
    }
}

$obj = new CI(15);
echo count($obj).'<br />';
echo $obj->count().'<br />';

/* 顯示結果
15
15
*/

有人大概會問說,為什麼不用 $obj[$pos] 去取結果值,這樣是不行的,因為陣列的方式必須使用另一個 interface ArrayAccess 的方式去做。

interface SeekableIterator {
   public function rewind();
   public function current();
   public function key();
   public function next();
   public function valid();
   public function seek($pos);
}
<?php
class CI implements SeekableIterator {
    private $obj;
    private $num;

    public function __construct($obj) {
        $this->obj = $obj;
    }
    public function rewind() {
        $this->num = 0;
    }
    public function valid() {
        return $this->num < $this->obj->max;
    }
    public function key() {
        return $this->num;
    }
    public function current() {
        switch($this->num) {
           case 0: return "1st";
           case 1: return "2nd";
           case 2: return "3rd";
           default: return $this->num."th";
        }
    }
    public function next() {
        $this->num++;
    }
    public function seek($pos) {
        $__tmp = $this->num;
        $this->num = $pos;
        $pos = $this->current();
        $this->num = $__tmp;
        return $pos;
    }
}

class CIA implements IteratorAggregate {
    public $max = 1;
    function getIterator() {
        return new CI($this);
    }
}

$obj = new CIA;
// 指定這個 IteratorAggregate 的最大值(在 Class CIA 裏面我預設給 1 而已)
$obj->max = 10;

// 這裡僅介紹 seek 的用法,其它迴圈用法與 Iterator, IteratorAggregate 相同
$it = $obj->getIterator();
echo $it->seek(5);

/* 顯示結果
5th
*/

底下來介紹 ArrayAccess,這是 ArrayAccess 在 PHP 裡面的定義。

interface ArrayAccess {
   offsetExists ($offset) // boolean
   offsetGet ($offset)  // mixed
   offsetSet ($offset, $value)  // void
   offsetUnset ($offset)  // void
}

簡單的範例如下。

class CI implements ArrayAccess {
    private $configarray; 

    public function __construct() {
        $this->configarray = array("John"=>"Male", "May"=>"Female"); 
    }
    public function offsetExists($index) {
        return isset($this->configarray[$index]); 
    }
    public function offsetGet($index) { 
        return $this->configarray[$index]; 
    }
    public function offsetSet($index, $newvalue) { 
        $this->configarray[$index] = $newvalue; 
    }
    public function offsetUnset($index) { 
        unset($this->configarray[$index]); 
    } 
}

$obj = new CI();
echo '原有陣列為:array("John"=>"Male", "May"=>"Female")<br />';
echo 'offsetGet("May") => '.($obj->offsetGet("May")).'<br />';
echo 'offsetExists("May") => ';
echo ($obj->offsetExists("May")) ? 'yes' : 'no';
echo '<br />';
$obj->offsetSet("May", "John's wife.");
// 使用 offsetSet 修改原有陣列內的值
echo '使用 offsetSet 修改原有陣列內的值<br />';
echo 'offsetGet("May") => '.($obj->offsetGet("May")).'<br />';
// 使用 offsetSet 新增原有陣列內的值
echo '使用 offsetSet 新增原有陣列內的值<br />';
$obj->offsetSet("Jasmin", "John's sister.");
echo 'offsetGet("Jasmin") => '.($obj->offsetGet("Jasmin")).'<br />';
echo '目前陣列內容為:array("John"=>"Male", "May"=>"John\'s wife.", "Jasmin", "John\'s sister.")<br />';
// 使用 offsetUnset 刪除原有陣列內的值
$obj->offsetUnset("May");
echo 'offsetExists("May") => ';
echo ($obj->offsetExists("May")) ? 'yes' : 'no';
echo '<br />';
echo '目前陣列內容為:array("John"=>"Male", "Jasmin", "John\'s sister.")<br />';

/* 顯示結果
原有陣列為:array("John"=>"Male", "May"=>"Female")
offsetGet("May") => Female
offsetExists("May") => yes
使用 offsetSet 修改原有陣列內的值
offsetGet("May") => John's wife.
使用 offsetSet 新增原有陣列內的值
offsetGet("Jasmin") => John's sister.
目前陣列內容為:array("John"=>"Male", "May"=>"John's wife.", "Jasmin", "John's sister.")
offsetExists("May") => no
目前陣列內容為:array("John"=>"Male", "Jasmin", "John's sister.")
*/

這個就應該比較容易理解,其實跟 serialize 差不多。這裡有一篇文章有非常詳盡的說明,值得一看:PHP 序列化(serialize)格式详解

interface Serializable {
   public function serialize();
   public function unserialize($serialized)
}

至於範例,我不想舉了,因為這牽扯到一些傳值傳址的問題,強烈建議閱讀我上面所提供的那篇文章。

誒... Abstract Class 呢?

我好懶啊... 請自行翻閱:

先告一段落,以後想到什麼在補上吧。

附帶一提,TextCube 從 1.8 以後的程式結構又改了,不知道對往後修改有無影響?目前縱觀而言,似乎是沒有 (遠目)。