まとめ ブログ ダウンロード 掲示板 メール

れぶろぐ

< 前月 翌月 > 最新


2007-02-03 (土)

Mozex 拡張機能のインストール

Firefox で Textarea の編集時に外部エディタを使えるように、 Mozex という拡張機能をインストールしてみた。 インストール後、 Mozex の設定画面を出して Textarea タブの以下の部分を設定。

  • Edit textbox in UTF-8 にチェックを入れる
  • Text editor: の項目を以下のように設定
C:\Progra~1\TeraPad\TeraPad.exe /cu8n /el %t

最初 Mozex の起動時にエラーが出て動かなかったが、 "Program Files" と書いていたのをこのように Progra~1 と書き直すことで、 動かすことができた。

このエントリの続き: 2007-03-31 (土)
Tags: Firefox | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-04 (日)

geshi.inc.php, highlighter.inc.php プラグイン Ver.0.7 をリリース

geshi.inc.php プラグイン の方の変更点は以下の通り。

  • sonots 氏のパッチ を取り込み、設定ファイルの機能を追加
  • 行番号の表示機能を一応使えるように

highlighter.inc.php プラグイン の方も、 それに合わせて行番号の表示機能を追加しておいた。

なお、今回の件では sonots さんに色々とお世話になりました。多謝。

Tags: PukiWiki | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-11 (日)

Simplate における変数表記のサポート範囲

Smarty のマニュアルを見ると、 以下のような説明が書かれている。

{$foo} <-- displaying a simple variable (non array/object)
{$foo[4]} <-- display the 5th element of a zero-indexed array
{$foo.bar} <-- display the "bar" key value of an array, similar to PHP $foo['bar']
{$foo.$bar} <-- display variable key value of an array, similar to PHP $foo[$bar]
{$foo->bar} <-- display the object property "bar"
{$foo->bar()} <-- display the return value of object method "bar"

Simplate がこれらの書き方のうち、 どこまでサポートしているのかを確認しておきたかったので、実験してみた。

まず、以下のような PHP のスクリプトを用意。

<?php

require_once 'Smarty/Smarty.class.php';

class tmpClass
{
    var $var = 'class_var';

    function method($param = '')
    {
        echo "class_method('$param')";
    }
}

$var   = 'var';
$array = array('var' => 'array_var');
$class = new tmpClass();

$smarty = new Simplate();
$smarty->assign('var',   $var);
$smarty->assign('array', $array);
$smarty->assign('class', $class);
$smarty->display('test.tpl');

?>

テンプレートの test.tpl には、以下のように書いてみる。

{$var}
{$array.var}
{$class->var}
{$class->method()}
{$class->method($var)}

これをコンパイルすると、Smarty も Simplate も以下のような HTML を出力する。

<?php echo $this->_tpl_vars['var']; ?>
<?php echo $this->_tpl_vars['array']['var']; ?>
<?php echo $this->_tpl_vars['class']->var; ?>
<?php echo $this->_tpl_vars['class']->method(); ?>
<?php echo $this->_tpl_vars['class']->method($this->_tpl_vars['var']); ?>

結果として、画面には以下のように表示される。

var
array_var
class_var
class_method('')
class_method('var')

ここまではOK。

次に、テンプレートに以下のように書いてみる。

{$array.$var}
{$class->$var}

これをコンパイルした場合の結果は、Smarty と Simplate とで異なる。 Smarty の場合、

<?php echo $this->_tpl_vars['array'][$this->_tpl_vars['var']]; ?>
<?php echo $this->_tpl_vars['class']->{(($_var=$this->_tpl_vars['var']) && substr($_var,0,2)!='__') ? $_var : $this->trigger_error("cannot access property \"$_var\"")}; ?>

Simplate の場合、

<?php echo $this->_tpl_vars["array"]["$var"]; ?>
<?php echo $this->_tpl_vars['class']->$var; ?>

つまり、$var というのが global スコープの変数でない限り、 Simplate での表示はおかしなことになる。 試していないが、{$class->$methodName()} のような書き方も恐らくダメだろう。

ということで、通常の使い方ならまず大丈夫だが、 あまり複雑なテンプレートの書き方をすると、 Simplate では使えないことがあるので注意しよう。

Tags: Simplate | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-12 (月)

geshi.inc.php, highlighter.inc.php プラグイン Ver.1.0 をリリース

geshi.inc.php プラグインhighlighter.inc.php プラグイン が ようやく形になったと思うので、バージョン番号も 1.0 に上げて正式公開する。 変更点は以下の通り。

  • プラグインの引数でオプションを指定できるように

まだ何とかしたい部分はあるが、とりあえずこれで一段落、ということにしよう。

Tags: PukiWiki | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-13 (火)

Dotdeb 版 PHP 5.2.1 の PowerPC 用パッケージ

先日 PHP 5.2.1 がリリースされたが、 Debian 本家のパッケージはまだ出ていないのに、 Dotdeb 版のパッケージはもうとっくに出ていたりする。

ということで、PowerPC 用 (玄箱用) のパッケージをいつものように作ってみた。 ファイル置き場 に置いておくので、 もし欲しい人がいたらどうぞ。

Tags: 玄箱 | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-15 (木)

PEAR::Pager を継承して使う (2)

以前書いた話 の続き。 前回の書き方でも問題なく動作はするのだが、 PHP 5 の場合に E_STRICT レベルのエラーが大量に発生してしまう。 Jumping か Sliding のどちらかのモードしか使わないという制限付きでよければ、 以下のような書き方をすることで E_STRICT 互換のライブラリのように使うことが出来る。

<?php

ini_set('display_errors', 0);
require_once 'Pager/Sliding.php';
ini_restore('display_errors');

class Pager extends Pager_Sliding
{
    public function __construct($options = array())
    {
        $defaults = array(
            'altFirst' => '最初のページ',
            'altPrev'  => '前ページ',
            'altNext'  => '次ページ',
            'altLast'  => '最後のページ',
            'altPage'  => 'Page',
        );
        return parent::__construct(array_merge($defaults, $options));
    }
}

$numItems = getNumItems();

$options = array(
    'totalItems' => $numItems,
);

$pager = new Pager($options);
$links = $pager->getLinks();
echo $links['all'];

?>

この書き方のポイントは以下の2点。

  • 直接 Pager_Sliding クラスを継承して使う
  • require_once の前後で display_errors ディレクティブの設定を一時的に変更する

Zend Framework 用に書いたコードの一部を抜き出して載せたが、 おそらくこの書き方で汎用的に使えるはず。

Tags: PHP | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-17 (土)

Piece Framework のサンプルカウンタ

Piece Framework を試してみている。 Piece_Flow のアーカイブの中にあったテスト用のファイルを少し手直しして、 ごくごく簡単なサンプルを作ってみた。 カウンタというか、へぇボタンみたいなやつだ。 ただこのサンプルは、必ず同じ state に戻って来るという点があまりよろしくない。 そのせいで「戻る」ボタンを押した時の動作がおかしいが、 あくまでも練習ということで大目に見て欲しい。

  • config/flows/Counter.yaml
firstState: DisplayForm

viewState:
  - name: DisplayForm
    view: Counter
    activity:
      method: setView
    transition:
      - event: increase
        nextState: done
        action:
          class: CounterAction
          method: increase
      - event: reset
        nextState: done
        action:
          class: CounterAction
          method: reset

actionState:
  - name: done
    transition:
      - event: succeed
        nextState: DisplayForm

initial:
  class: CounterAction
  method: initialize
  • actions/CounterAction.php
<?php

require_once 'Piece/Flow/Action.php';

class CounterAction extends Piece_Flow_Action
{
    function initialize()
    {
        $this->_flow->setAttribute('counter', 1);
    }

    function increase()
    {
        $counter = $this->_flow->getAttribute('counter');
        $this->_flow->setAttribute('counter', $counter + 1);
        return 'succeed';
    }

    function reset()
    {
        $this->initialize();
        return 'succeed';
    }

    function setView()
    {
        $counter = $this->_flow->getAttribute('counter');
        $viewElement =& $this->_payload->getViewElement();
        $viewElement->setElement('counter', $counter);
    }
}

?>
  • templates/Counter/Counter.html
<p>Counter: {counter}</p>
<form>
  <input type="hidden" name="{__flowExecutionTicketKey}" value="{__flowExecutionTicket}" id="flowExecutionTicket" />
  <input type="submit" name="{__eventNameKey}_increase" value="Increase" />
  <input type="submit" name="{__eventNameKey}_reset" value="Reset" />
</form>

あとは piece-unity-config.yaml にこのフローを追加するといった作業も必要だが、 とりあえずこれはこれでちゃんと動作する。

さて、ここからが本題。 マニュアルに書かれているアクション継続の説明を読んで、 その時は、ふーん、と思っていたのだが、 しばらく経った後で、書かれていることの意味が頭に染み渡ってきた。 フロー変数を意識する必要が無いだって? もしかして、アクション継続の機能を有効にすればこういう風に書けるのか?

<?php

require_once 'Piece/Flow/Action.php';

class CounterAction extends Piece_Flow_Action
{
    var $_counter;

    function initialize()
    {
        $this->_counter = 1;
    }

    function increase()
    {
        $this->_counter++;
        return 'succeed';
    }

    function reset()
    {
        $this->initialize();
        return 'succeed';
    }

    function setView()
    {
        $viewElement =& $this->_payload->getViewElement();
        $viewElement->setElement('counter', $this->_counter);
    }
}

?>

試してみたところ、これでちゃんと動いた。こりゃすごいや。

要するに、今までの通常の Web アプリだったら、 セッションに値を保存しておいて、 次の画面でセッションから値を取り出して、 といったことをほぼ手作業でやっていたのに、 そういった処理を何も書かなくて済む。 Piece Framework はステートフル、と書かれていたのがようやく実感できた。

Tags: Piece | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-20 (火)

イベント名を取得する部分の謎の処理

Piece Framework で $_POST (や $_GET) からイベント名を取得する部分の処理は、 以下のようなコードになっている。

class Piece_Unity_Context
{
    /**
     * Imports an event name from the submit by a submit or a image.
     *
     * @since Method available since Release 0.9.0
     */
    function _importEventNameFromSubmit()
    {
        $xFound = false;
        $yFound = false;
        foreach ($this->_request->getParameters() as $key => $value) {
            if (preg_match("/^{$this->_eventNameKey}_(.+)$/", $key, $matches)) {
                $eventName = $matches[1];
                $lastTwoBytes = substr($matches[1], -2);
                if ($lastTwoBytes == '_x') {
                    $xFound = true;
                    $xEventName = substr($matches[1], 0, -2);
                    if ($yFound) {
                        break;
                    }
                } elseif ($lastTwoBytes == '_y') {
                    $yFound = true;
                    $yEventName = substr($matches[1], 0, -2);
                    if ($xFound) {
                        break;
                    }
                } else {
                    $this->setEventName($eventName);
                    return;
                }
            }
        }

        if ($xFound || $yFound) {
            if ($xFound && $yFound && $xEventName == $yEventName) {
                $this->setEventName($xEventName);
            } else {
                $this->setEventName($eventName);
            }
        }
    }
}

この _x だの _y だのというのは何だろう? 変数名やコメントからすると、どうも x 座標、y 座標っぽい気がするんだが。 いつものように検索してみたところ、以下のページを見つけた。

要約すると、

  • <input type="image" name="foo"> のような場合は foo_x, foo_y という変数が渡される
  • それぞれ画像のクリックポイントの座標を示している

だから _x, _y を取り除いたものをイベント名としているわけか。納得。

ただ、 http://www.gac.jp/article/index.php?stats=question&category=11&id=19634&command=msg に気になる書き込みを見つけた。

ただIEではtextboxが一つしかないと EnterボタンでSubmitした時に ksearch_xが送られてこないというバグ?があるようです。 (※WindowsXPIE6で確認)

これは、ksearch_y しか送られてこない、という意味なんだろうか? だとしたら foo_x か foo_y のどちらかを見つけた時点で、 それをイベント名とする方がいいのかな?

Tags: Piece | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink
本日のコメント(全2件) [コメントを書く]

# ITEMAN [こんにちは。 この件、気になったので調査しました。 結果的には、xもyも送信されないことがわかり、トラブルシューティ..]

# revulo [はじめまして。Piece Framework 使わせて頂いております。 リンク先を拝見しましたが、やはり IE6 固..]


2007-02-21 (水)

Piece_Unity の処理の流れ

Piece Framework の継続サーバの機能を、 他のフレームワーク(というか Zend Framework)で使えるようにできないかと思い、 Piece_Unity の処理の流れを最初から追ってみた。

かなりはしょって書いてしまうが、htdocs/〜.php にアクセスした後は、 以下のような順で処理が行われていく。

  • Piece_Unity::dispatch()
  • Piece_Unity_Plugin_Root::invoke()
  • Piece_Unity_Plugin_Controller::invoke()

ここで Piece_Unity_Plugin_Controller::invoke() は、

class Piece_Unity_Plugin_Controller extends Piece_Unity_Plugin_Common
{
    function invoke()
    {
        if (is_null($this->_context->getView())) {
            $dispatcher = &$this->getExtension('dispatcher');
            $viewString = $dispatcher->invoke();
            $this->_context->setView($viewString);
        }
        $dispatcherContinuation = &Piece_Unity_Plugin_Factory::factory('Dispatcher_Continuation');
        $dispatcherContinuation->publish();
        $view = &$this->getExtension('view');
        $view->invoke();
    }
}

のようになっている。 フローの機能を使う時は dispatcher が Dispatcher_Continuation に設定されているので、 $dispatcher->invoke() の部分は、

  • Piece_Unity_Plugin_Dispatcher_Continuation::invoke()
  • Piece_Flow_Continuation::invoke()
  • ……

のように処理が進んでいく。

あれ? Piece_Flow_Continuation? そんなクラスがあるのか。

ここでひとまず上のコードの部分に戻ってみると、 $dispatcherContinuation->publish() はたいしたことはしていないし、 後はそのまま、

  • Piece_Unity_Plugin_View::invoke()
  • Piece_Unity_Plugin_Renderer_xxx::invoke()

のように画面 (や JSON) への出力の処理に進んでいく。 だから、Piece_Unity_Plugin_Dispatcher_Continuation クラスが肝のはず。 しかし Piece_Unity_Plugin_Dispatcher_Continuation クラスを眺めてみても、 フローの制御とか、イベントの実行とか、そういった処理がどこにも書かれていない。 考えてみたら、そもそもフローの設定ファイルすら読み込んでいない。

もしかして、Piece_Flow_Continuation クラスが処理の本体で、 Piece_Unity_Plugin_Dispatcher_Continuation クラスはその使用例みたいなもの? Piece_Unity_Plugin_Dispatcher_Continuation 相当の処理さえ書けば、 あとは Piece_Flow の方で全て面倒を見てくれるのか? Piece_Flow のコードをざっと見てみると、どうもそんな気がする。 それならば意外と簡単に実装できるかもしれない。

Tags: Piece | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-22 (木)

Zend Framework 0.8.0 がリリース

されている。 今回のバージョンは変更点がかなり多い。 特に影響が大きそうな点としては、ディレクトリ構造が整理されたため、

  • Zend_Controller_RewriteRouter → Zend_Controller_Router_Rewrite
  • Zend_Controller_Dispatcher → Zend_Controller_Dispatcher_Standard

のようにいくつかのクラス名が変更されている。 この辺が従来とは非互換になっているので、 気をつけないといけない。

(追記)

Zend_Session クラスも使い方が変更されている。 new Zend_Session(__CLASS__) のようにしていたのを、 new Zend_Session_Namespace(__CLASS__) に修正する必要があった (2007/02/23)。

Tags: Zend | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-23 (金)

__PHP_Incomplete_Class の対処法

Zend Framework で Piece_Flow を使おうプロジェクトのコーディング中。

1回目のアクセスには成功する。 continuation のオブジェクトも作られて、 それがセッションにちゃんと保存されている。 しかしそこから画面遷移すると、以下のようなエラーが出てしまう。

Fatal error: Revulo_Controller_Dispatcher_Flow::invoke() [<a href='function.Revulo-Controller-Dispatcher-Flow-invoke'>function.Revulo-Controller-Dispatcher-Flow-invoke</a>]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "Piece_Flow_Continuation" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /home/revulo/flowtest/library/Revulo/Controller/Dispatcher/Flow.php on line 90

セッションに保存したオブジェクトを復元する処理が上手くいっていないようだ。 セッションの中身をのぞいてみると、なにやら妙なことになっている。

Array
(
    [continuation] => __PHP_Incomplete_Class Object
        (
            [__PHP_Incomplete_Class_Name] => Piece_Flow_Continuation

__PHP_Incomplete_Class というキーワードで検索してみると、 unserialize() がどうこうとかいろいろ書かれていたが、 少し試行錯誤してみたところ、 どうも session_start() する前にクラスが定義されていないといけないらしい。 require_once 'Piece/Flow/Continuation.php'; というのを、 session_start() の直後に書いた場合は __PHP_Incomplete_Class のままだが、 session_start() の直前に書くと Incomplete の表示が消えてくれた。


そうして先に進めていったところ、 また同じようなエラーが出たので、セッションの中身を見てみると、 まだ他にも __PHP_Incomplete_Class になっているクラスがあった。

[__PHP_Incomplete_Class_Name] => Zend_Controller_Request_Http
[__PHP_Incomplete_Class_Name] => CounterAction

とりあえず以下のように片っ端から強引に追加してやるとエラーは出なくなった。

require_once 'Piece/Flow/Continuation.php';
require_once 'Zend/Controller/Request/Http.php';
require_once '../application/controllers/CounterAction.php';

ただこれだと、 最後のアクションクラスの部分が決めうちになってしまっている。 そこで、手作業で require する代わりに、

function __autoload($class)
{
    Zend::loadClass($class);
}

みたいなコードを追加してみたところ、それで動くことを確認できた。


しかし、1ライブラリが、 こうやって __autoload() を定義してしまっていいんだろうか? unserialize 関数のマニュアル を読むと、どうやら __autoload() 関数の代わりに unserialize_callback_func ディレクティブというのが使えるらしい。 ただし、

3) It does not appear to be possible to use a static member fuction of a class (for example, a your object persistence layer) as the unserialize callback function, so this will cause confusion

ということらしく、

ini_set('unserialize_callback_func', 'Zend::loadClass');

みたいな指定は不可。

ini_set('unserialize_callback_func', 'loadClass');

function loadClass($class) {
    Zend::loadClass($class);
}

のように関数を用意して指定してやることで動くようになった。

Tags: PHP | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-24 (土)

フロー名の指定方法について

Zend Framework で Piece_Flow を使おう計画の進捗。 まだ絶対に不具合があると思うが、なんだかそこそこ動くようになった。 今はまだフローの名前や定義をコード中に埋め込んで動かしているので、 その辺を自由に指定できるようにしてやらないといけない。 さて、どう実装していこうか?

Piece_Unity はページコントローラ方式なので、 htdocs ディレクトリ内の各ファイルでフロー名を指定しているが、 Zend Framework はフロントコントローラ方式なので、 index.php にフロー名を書いてしまうわけにはいかない。

Zend Framework で指定できるのは、 URL を分解して得られる Controller, Action 名やその他のパラメータ。 パラメータの部分でフロー名を指定するという案も考えられるが、 今やろうとしているのは、 同じ Controller、同じ Action でも条件に応じて別のイベントをやらせよう、 ということなので、 Controller, Action 名の組み合わせをフロー名のように扱う方が、 考え方としてはスマートだろう。

結局考えたのは、フローの定義をする際に、 フロー名と Controller, Action 名との対応関係を書いておくこと。

name:       CounterTest
controller: counter
action:     index
file:       CounterTest.yaml

のようにフローの定義をしておいて、 http://example.com/counter/index のような URL にアクセスしたら、 flowName = CounterTest が指定されたものとしてフロー開始、 という動作にしようと思う。

Tags: Piece Zend | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-25 (日)

Zend Framework で継続サーバ Piece_Flow を使う

ということで、 ここ数日取り組んでいた物が一応形になったと思うので公開してみる。 専用ページを作って、説明も書いておいた。

これを使えば、 Piece Framework のようなステートフルなプログラミングが、 Zend Framework でも一応できるようになる。

エラー処理を書いていなかったり、オプション指定が効かない部分があったり、 はっきり言ってまだアルファ版の状態だが、 少なくとも付属のサンプルは問題なく動作しているので、 興味のある人は試してみて欲しい。

なお、もう少し作りこんでいくつもりだが、 使ってみて不具合(や実装上の勘違い)に気付いたら、 ぜひ教えて下さい。お願いします。

Tags: Piece Zend | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

2007-02-26 (月)

Revulo-Controller-Dispatcher-Flow クラス Ver.0.2 をリリース

昨日リリースしたばかりの Revulo_Controller_Dispatcher_Flow クラス ですが、ちょっとバージョンアップしておきます。

前バージョンでは、Zend_Controller_Action クラスでなく Piece_Flow_Action クラスを継承して使っていたため、 getRequest() や _redirect() などのメソッドが アクションコントローラ中で使えませんでしたが、 それらが使えるように手を加えました。

Piece_Flow のコード自体をいじる必要があるかと思っていましたが、 Zend_Controller_Action クラスにいくつかメソッドを追加した Revulo_Controller_Action クラスを作り、 ちょっと細工してやることでなんとかなりました。

これで Zend Framework ユーザーにとっても、 それほど違和感なく使えるようになったと思います。


と、ここからはいつもの文体で。

もうしばらくひっそりとやっていくつもりでいたが、 Piece Framework のページ とか PHPプロ!ニュース とか、 何ヶ所かで紹介されたようだ。 フィードバックを期待して公開しているので、紹介されるのは嬉しいが、 いろいろ鋭い指摘が来たりしないかと、ちょっと冷や汗ものだったりする。

ついでに書いてしまうと、実は手元では Piece_Right も Zend Framework に組み込んでみている。 これもそのうち公開できるように整理していきたい。

Tags: Zend | このエントリを含む del.icio.us | このエントリを含むはてなブックマーク | このエントリを含む livedoor クリップ | Permalink

追記