Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

PHPTypeSafeで目から鱗が落ちた

PHP5から導入されたタイプヒンティングを、とある方法で拡張してstringやint、boolなどのスカラー値に対しても使えるようにしたライブラリです。


Today I released the first public version of my new library PHPTypeSafe. It provides the ability to use PHPs Type Hinting feature for scalar values.

PHP5.3以降対応で、phar形式で提供されています。つーか、PHP本体に入れば楽なんだけどなぁ。。。
どのように書けるかというと、こんな感じ。barメソッドに注目。

<?php
require 'com.maxhorvath.phptypesafe.phar';

class Foo
{
    public static function bar(string $msg, int $counter)
    {
        echo $counter . '. run: ' . $msg . "\n\n";
    }
}

$obj = new Foo();
$obj->bar('test', 1);
Foo::bar(false, 2);    // 引数の型が合っていない

PHP5.3.0α2で実行すると。。。なんかechoの部分がうまく出なかったんですが、

$ php -n sample.php
????????????????????????????????????????????????????????????????????????????????????
Fatal error: Uncaught exception 'ErrorException' with message 'Argument 1 passed to Foo::bar must be of type string, boolean given, called in ...
$

な感じで例外(ErrorException)が投げられます。ちゃんと「Argument 1 passed to Foo::bar must be of type string, boolean given」となっているのが分かりますかね。


で、このライブラリが面白いのは、pharで提供されているところじゃなくて、これを実現している方法。PHP5で上記のFooクラスのように書くと「string」や「int」がオブジェクト型として認識されるので、

Catchable fatal error: Argument 1 passed to Foo::bar() must be an instance of string, string given, called in ...

となりますが、PHPTypeSafeではこのCatchable fatal error(E_RECOVERABLE_ERROR)を独自のエラー処理関数で処理しています。この部分の大まかな流れを抜き出すとこんな感じ。

<?php
set_error_handler('errorHandler');
function errorHandler($code, $message, $file = '', $line = 0, array $context = array()) {
    if ($code === E_RECOVERABLE_ERROR) {
        printf("message:%s\n", $message);
    }
    return call_user_func(...)
}

詳細は、ErrorHandlerクラスを参照。これに気づいたときは目から鱗。感動しました。


また、

をガッツリ使っているので、非常に良いサンプルになりそうです。


ちなみに、com.maxhorvath.phptypesafe.pharを

<?php
try {
    $p = new Phar(dirname(__FILE__) . '/com.maxhorvath.phptypesafe.phar');
} catch (Exception $e) {
    die($e->getMessage() . PHP_EOL);
}

な感じで読み込もうとしたんですが、

$ php -v
PHP 5.3.0alpha2 (cli) (built: Sep  2 2008 11:52:39)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2008 Zend Technologies
    with Xdebug v2.0.3, Copyright (c) 2002-2007, by Derick Rethans
$ cat -n construct.php
     1  <?php
     2  try {
     3      $p = new Phar(dirname(__FILE__) . '/com.maxhorvath.phptypesafe.phar');
     4  } catch (Exception $e) {
     5      die($e->getMessage() . PHP_EOL);
     6  }
$ ls com.maxhorvath.phptypesafe.phar
com.maxhorvath.phptypesafe.phar
$ php -n construct.php
phar "/path/to/com.maxhorvath.phptypesafe.phar" SHA1 signature could not be verified: broken signature
$

と怒られてしまいました。。。むーん。