PHPからGrowlをたたく

デバッグに超便利!

かどうかは不明だけど


require_once 'class.growl.php';

// Setup
$growl = new Growl();
$growl->setAddress('127.0.0.1');
$growl->addNotification("Test");
$growl->register();

// Send Notification
$growl->notify('Test', 'Test Alert', 'The body of the test alert!');

class.growl.phpはhttp://www.sitecrafting.com/blog/php-growl/のDownloadから。

残念ながら日本語使うと文字化けする。
Growlの仕組みがよくわからないのでPHPのソース読んでもよくわからんけど、utf8_encodeとかいう関数使ってる。
知らなかった関数で調べたら「ISO-8859-1 文字列を UTF-8 にエンコードする」ってマニュアルに書いてあったからたぶんそのせい?

最初うまくいかなくて色々いじってたら、Growlの設定でリモートアプリケーションを許可してやらないとダメだった。

Growl

via http://www.sitecrafting.com/blog/php-growl/

ZendFramework::Zend_Loader

ZendFramework::Zend_Loader を読む

Zend_Controllerを読もうとしたけど色々他のコンポーネントを読み込んでるみたいなのでそっちからとりあえず読んでいく。
でもすぐにver1.5が公開されそう。すでにver1.5RC1が出てるし。

RCを読む気しないので1.0.4。出たら出たでマニュアルに変更点が書かれるだろうから諦める。

loadClass()

public static function loadClass($class, $dirs = null)
{

$classが探すクラス名、$dirsが探すディレクトリのパス

if (class_exists($class, false) || interface_exists($class, false)) {
    return;
}

if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
    require_once 'Zend/Exception.php';
    throw new Zend_Exception('Directory argument must be a string or an array');
}

$classが存在するclassやinterfaceで定義済みなら終了
$dirsがnullか、文字列か配列のどれでもないと終了

if (null === $dirs) {
    $dirs = array();
}
if (is_string($dirs)) {
    $dirs = (array) $dirs;
}

// autodiscover the path from the class name
$path = str_replace('_', DIRECTORY_SEPARATOR, $class);
if ($path != $class) {
    // use the autodiscovered path
    $dirPath = dirname($path);
    if (0 == count($dirs)) {
        $dirs = array($dirPath);
    } else {
        foreach ($dirs as $key => $dir) {
            if ($dir == '.') {
                $dirs[$key] = $dirPath;
            } else {
                $dir = rtrim($dir, '\\/');
                $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
            }
        }
    }
    $file = basename($path) . '.php';
} else {
    $file = $class . '.php';
}

最初の5行ぐらいはどうでもいい。

DIRECTORY_SEPARATORを「_」で置き換える。Zend_Hoge.phpだとZend/Hoge.php
$pathが$classと同じでないなら(つまり、$classにHogeClassとかが渡ると $path == $class になる。この場合$fileにHogeClass.phpが格納される)条件文の中に突入。

$dirPathにはZend_Hogeだとすると、dirname('Zend/Hoge')でZend。
foreachの部分は$dirsが配列の場合。

説明しにくい。要するに

$dirs = array(
	'/home/hoge1',
	'/home/hoge2',
	'.'
);

こういうのが渡ると、

Array
(
    [0] => /home/hoge1/Zned
    [1] => /home/hoge2/Zned
    [2] => Zned
)

こういうふうに返ってくる。(ちょっと上に書いた$dirPathの場合)

で、あとは拡張子を一緒にしてloadFile()に渡す。

loadFile()

/**
 * @param  string        $filename
 * @param  string|array  $dirs - OPTIONAL either a path or array of paths
 *                       to search.
 * @param  boolean       $once
 * @return boolean
 * @throws Zend_Exception
 */
public static function loadFile($filename, $dirs = null, $once = false)
{

$filenameに拡張子までを含めたファイル名、$dirsに文字列か配列でパスを渡す、$onceがtrueだとincludeがinclude_onceになる

if (preg_match('/[^a-z0-9\-_.]/i', $filename)) {
    require_once 'Zend/Exception.php';
    throw new Zend_Exception('Security check: Illegal character in filename');
}

ファイル名のチェック。セキュリティチェック。
ファイル名に、a-z0-9\-_. 以外の文字が含まれているとZend_Exceptionに投げられて終了。

if (is_null($dirs)) {
    $dirs = array();
} elseif (is_string($dirs))  {
    $dirs = explode(PATH_SEPARATOR, $dirs);
}
foreach ($dirs as $dir) {
    $filespec = rtrim($dir, '\\/') . DIRECTORY_SEPARATOR . $filename;
    if (self::isReadable($filespec)) {
        return self::_includeFile($filespec, $once);
    }
}

$dirsの中身探す。

30分ぐらい

$dirs = explode(PATH_SEPARATOR, $dirs);

の部分の存在理由がわからなかった。
$dirsの中にどうやったら「;」とか入るんだよって思ってたけど、$dirsがnullだとinclude_pathを読み込むからか。

で、パスとファイル名を合体させてからパスごとにisReadableに渡してtrueが返ってきたらinclude

if (self::isReadable($filename)) {
    return self::_includeFile($filename, $once);
}

上のループでファイルが見つからなかった場合、あるいは$dirsに何も渡さなかった場合にinclude_pathから探してくる。
それでも見つからなかったらZend_Exceptionさんに助けてもらう

_includeFile()

protected static function _includeFile($filespec, $once = false)
{
    if ($once) {
        return include_once $filespec;
    } else {
        return include $filespec ;
    }
}

特に何もない。
$filespecがZend/Hoge/hoge.php、$once = trueだと、require_once 'Zend/Hoge/hoge.php'が返される。

isReadable()

public static function isReadable($filename)
{
    if (!$fh = @fopen($filename, 'r', true)) {
        return false;
    }

    return true;
}

ファイルをオープンできなければfalse

autoLoad() registerAutoload()

SPLがどうのこうのって書いてあるけど、SPLわかんないのでよくわからん。
飛ばす。

それにしても書くのに時間がすげぇかかる。
Zend_Loaderなんて250行ぐらいしかないのに。Controllerとかどうするべ。
続くのかどうか不明。