ごもちゃ箱BLOG

自作の PHP クラスライブラリ PEACH の開発日記です。

オレオレPHPライブラリ紹介(Map編)

先日 GitHub にオレオレ PHP クラスライブラリを公開しました。ぼちぼちと内容紹介していきたいと思います。ダウンロードはこちらから。

trashtoy/PEACH

概要とか

対象ユーザーは、PHP でそれなりにオブジェクト指向な開発をするユーザーです。 静的ページにちょこっとロジックを埋め込む程度だったり、 自分でクラスを作ったりしないようなシステムではあまり使いどころがないと思います。

サンプルコードをいくつか挙げて、どんなことが出来るか紹介したいと思います。

Util_ArrayMap

最近知ったのですが、Symfony に含まれている sfParameterHolder というクラスと同じようなコンセプトです。 例えば配列から値を取り出す際に、キーが存在するかどうかチェックするような場合。

Before

$arr = array("key1" => "hoge", "key2" => "fuga", "key3" => "piyo");
if (isset($arr["key2"])) {
    $x = $arr["key2"];
} else {
    $x = NULL;
}
if (isset($arr["key4"])) {
    $y = $arr["key4"];
} else {
    $y = NULL;
}
var_dump($x); // "fuga"
var_dump($y); // NULL

After

$arr = array("key1" => "hoge", "key2" => "fuga", "key3" => "piyo");
$map = new Util_ArrayMap($arr);
$x   = $map->get("key2");
$y   = $map->get("key4");
var_dump($x); // "fuga"
var_dump($y); // NULL

同じ内容なのにすごくシンプルで分かりやすいですよね!

Util_HashMap

簡単に言うと PHP 版の java.util.HashMap (がちょっと高機能になったクラス) です。

class TestKey {
    private $id;
    private $name;
 
    public function __construct($id, $name) {
        $this->id   = $id;
        $this->name = $name;
    }
 
    public function getId() {
        return $this->id;
    }
 
    public function getName() {
        return $this->name;
    }
}

$map = new Util_HashMap();
$k1  = new TestKey(1, "foo");
$k2  = new TestKey(2, "bar");
$map->put($k1, 100);
$map->put($k2, 200);
 
echo $map->get(new TestKey(1, "foo"), "undef"); // 100
echo $map->get(new TestKey(2, "bar"), "undef"); // 200
echo $map->get(new TestKey(2, "xxx"), "undef"); // "undef"

みたいなことがPHPで出来ちゃいます。どのへんが「ちょっと高機能」かと言うと、キーの等価条件を自由に拡張できるところで、

class TestKeyEquator implements Util_Equator {
    /**
     * 2つの TestKey オブジェクトの id, name がそれぞれ等しい場合に TRUE を返します.
     */
    public function equate($var1, $var2) {
        return ($var1->getId()   === $var2->getId() && 
                $var1->getName() === $var2->getName());
    }
    
    public function hashCode($var) {
        return intval($var->getId());
    }
}
class TestKeyEquator2 implements Util_Equator {
    /**
     * 2つの TestKey オブジェクトの id がそれぞれ等しい場合に TRUE を返します.
     */
    public function equate($var1, $var2) {
        return ($var1->getId() === $var2->getId());
    }
    
    public function hashCode($var) {
        return intval($var->getId());
    }
}

$e1 = new TestKeyEquator();
$e2 = new TestKeyEquator2();
 
$k1 = new TestKey(1, "John Smith");
$k2 = new TestKey(2, "Emily Smith");
$k3 = new TestKey(2, "Emily Johns");
 
$map1 = new Util_HashMap(NULL, $e1); // TestKey の id と name を見て等価条件を確認
$map2 = new Util_HashMap(NULL, $e2); // TestKey の id だけ見て等価条件を確認
 
$map1->put($k1, "foo");
$map1->put($k2, "bar");
$map1->put($k3, "baz");
$map2->put($k1, "foo");
$map2->put($k2, "bar");
$map2->put($k3, "baz"); // $k2 と $k3 が同一視されるので, ここで $k2  "bar" のマッピングが "baz" に上書きされます
 
echo $map1->size(); // => 3
echo $map2->size(); // => 2
 
echo $map1->get($k2); // => "bar"
echo $map2->get($k2); // => "baz"

と、こんな感じに Map の挙動を変えることが出来るわけです。Java の equals や hashCode の制約をそのまま真似ているのでちょっと実装が面倒くさいですけど。

こんな感じで今後も色々紹介したいと思います。ところではてなブログって、手入力で section タグを使っても公開時に取れてしまうみたいなのですが、どうにかならないですかね?