2011年2月28日月曜日

Twigエラーを回避

Twigを使っていて、一つだけイラッとすることがあります。

Twig_Environment生成時にauto_reloadオプションをtrueにした場合、

テンプレートを変更してアプリを再実行すると、

内部的には、キャッシュ更新のためコンパイル結果をキャッシュファイルに書き込む処理が

走るようですが、このとき、renameでエラーになる場合があります。


1.発生条件
環境依存な問題ですので、当方でのテスト環境を示しておきます。
OS : Win7
PHP : Ver5.2.6
Twig : 1.0.0-BETA1


2.回避方法
パッといい方法を思いつかなかったので、
ダウンロードしてきたtwigのソースを書き換えてしまいました。。。
(.../Twig/Environment.php#line.560)
(変更前)
if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
(変更後)
if (/*@rename($tmpFile, $file) ||*/ (@copy($tmpFile, $file) && unlink($tmpFile))) {


書き換える内容については、OSがWindowsでphpが5.2.6以下の場合にはrenameはやめる、

というようにした方がよいような気がします。(が、面倒なので、ざっくりやめてみました。)



というより、ダウンロードしてきたものを書き換えるしか方法がないのかしら?・・と。

もっとスマートな回避方法があれば、ぜひご教授ください。

2010年12月4日土曜日

ITC資格認定申請を登録

HPから簡単に入力できました。

これから12/24まで、待ちに入ります。

何だか色々と時間が掛かり気味なのが気掛かりです。

2010年11月8日月曜日

ITC研修を修了

11月7日、ITコーディネータのケース研修を修了しました。

今後、具体的に、資格取得に向けての動いていくことになります。

==============================>
1.資格認定申請(2010/12/3~2010/12/15)

2.認定者発表(2010/12/24)

3.認定証送付(2010/12/24)

4.プロフィール登録開始(2010/12/24)

5.写真提出締め切り(2011/01/17)

6.認定料支払締め切り(2011/02/10)

==============================<

正直な感想としては、「長かった」「やっとか」といったところです。

様々な経営者の方々とお会いするのが必要だと感じています。

IT化まわりで何か悩み・迷い・不安などございましたら、

当方サイトからお気軽にご相談ください。

2010年10月26日火曜日

マーケティング

※以下、サラリーマンを脱皮しようとする意識・行動に目覚めた
 全ての会社人に捧げます。



商売を営んでいく上で、マーケティングの重要性について

疑念を抱く人はいないでしょう。

右肩あがりの時代には、会社が自分自身をマーケティングし、

ブランド化していった。そのため、社員は、名刺に会社名を

大きく書いておくだけでブランドに乗っかって商売できた。



しかし、時代は変わり、大企業に勤めていても、

40代50代といえども、いざとなれば首を切られる様を

新聞・TVで垣間見るにつけ、今は個人でも

「自分の価値を高めておかなければならない」といった

認識が広がり始めているように見受けられる。

かつ、そのように行動しているように見える方々がいる。



このとき、もっと有効なのは、恐らく、「自分をマーケティングする」と

いう考え方を取り入れて行動することだと思う。



「自分に出来ることは何か」を主体に考えるのでなく、

「まず市場が何を求めているか」を考え、

「周りから見た自分の強みは何か」とか

そういったことを考えることから始めていって、

やがて「戦略(方向性)」に結実させていく。

さらに、それを戦術レベルに落とし込んでいき、

具体的な行動プランに仕上げ、それを粛々と実行する。

実行にあたっては、勿論、タイミングごとにチェックをかけ、

行動やプランを見直す機会を設ける。



この一連の流れをより精緻に、分析的に、客観的に

実行できるようになれば、それだけで一つ武器を

手に入れたようなものだ。



「自分をマーケティングする」とか

「自分をブランディングしていく」とか

そういう方法論を、強くお勧めします。

2010年8月17日火曜日

ITC研修テキスト届く

今日、ITコーディネータ資格の研修テキストが届きました。

※どうでもいいですが、13日発送で16日AM着指定になってました。
 研修は、22日にスタートです。
 一週間前に届くようにしたかったんでしょうね。。。



内容をパラパラと斜め読みしてますが、

これは、SEの研修テキストにしてみても面白いかも知れません。

「あっ、会計の勉強しなきゃ」

って思うことでしょう。

それだけでも意味があるんじゃないかと思います。

2010年7月20日火曜日

Twigでテンプレート側からAppを起動

現在、当方では、PHPのテンプレートクラスであるTwigの

可能性を追求しているところです。



今回は、テーマファイルからAppを呼び出す仕組みを開発してみました。



通常のWEBアプリでは、まずAppを呼び出して処理した後に

Appでの実行結果をテーマに書き出すような処理順序になると思います。



今回、この処理順序をちょっと変えて、

テーマファイルに「app=blog fct=EntryView id=3」のように書いておけば

該当箇所にAppの実行結果が自動的に表示されるようにしてみました。

※イメージ的には、SoyCMSでやってるようなことです。
 SoyCMSでは独自テンプレートエンジンでやってると思いますが、
 当方では今回これをTwigという有名なテンプレートエンジン上で
 やってみている、というワケです。



以下、実装クラスのソースコードを晒しておきますので、

ご参考いただければ幸いです。



Extensionクラス

当該クラスで、TokenParserを定義します。(c.f. getTokenParsers())
<?php
/**
* Twig_Extension_Sample
* @author spark43
*
*/
class Twig_Extension_Sample extends Twig_Extension
{
    /**
     * (non-PHPdoc)
     * @see v0.02/Sample/_opt/Twig/Twig_Extension::getTokenParsers()
     */
    public function getTokenParsers()
    {
        return array(
            new Twig_TokenParser_Sample(),
        );
    }


    /**
     * (non-PHPdoc)
     * @see v0.01/Sample/_opt/Twig/Twig_Extension::getFilters()
     */
    public function getFilters()
    {
        return array(
            'nl2br' => new Twig_Filter_Method($this, 'nl2br'),
        );
    }

    /**
     * (non-PHPdoc)
     * @see v0.01/Sample/_opt/Twig/Twig_ExtensionInterface::getName()
     */
    public function getName()
    {
        return 'aither';
    }

    /**
     * nl2br
     * @param $string
     */
    public function nl2br($string)
    {
        return str_replace("\n", "<br />", Twig_Filter_Method);
    }
}

?>




TokenParserクラス

当該クラスでテーマに書かれた構文をトークンに解析します。
使用するフレームワークの構文に合わせることが必要です。
※オープンソースCMSなどに見られる場合があるのですが、
 使用モジュールごとにそれぞれ独自なフレームワークを使っている場合、
 該当フレームワークごとに必要となる場合もあるかと思います。
<?php
/**
* Twig_TokenParser_Sample
* @author spark43
*
*/
class Twig_TokenParser_Sample extends Twig_TokenParser
{
    /**
     * (non-PHPdoc)
     * @see v0.02/Sample/_opt/Twig/Twig_TokenParserInterface::parse()
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();
        $exp = $this->parser->getExpressionParser();


        // parse
        $request = array();
        $param = array();
        while($stream->test(Twig_Token::NAME_TYPE)) {
            $expk = $exp->parseExpression();
            $stream->expect(Twig_Token::OPERATOR_TYPE, '=');
            $expv = $exp->parseExpression();

            switch ($expk['name']) {
                case 'app':
                case 'fct':
                case 'with':
                    if (! ($expv instanceof Twig_Node_Expression_Name)) {
                        throw new Twig_SyntaxError("'". $expk['name']. "' paameter is invalid", $lineno);
                    }
                    $request[$expk['name']] = $expv;
                    break;
                default:
                    // TODO : other expressions...?
                    if (! ($expv instanceof Twig_Node_Expression_Name)
                    && ! ($expv instanceof Twig_Node_Expression_Constant)) {
                        throw new Twig_SyntaxError("'". $expk['name']. "' paameter is invalid", $lineno);
                    }
                    $param[$expk['name']] = $expv;
                    break;
            }
        }
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);


        // check
        if (! isset($request['app'])) {
            throw new Twig_SyntaxError("no 'app' paameter", $lineno);
        }
        if (! isset($request['fct'])) {
            throw new Twig_SyntaxError("no 'fct' paameter", $lineno);
        }
        if (! isset($request['with'])) {
            throw new Twig_SyntaxError("no 'with' paameter", $lineno);
        }


        // return
        return new Twig_Node_Sample(new Twig_Node($param), new Twig_Node($request), $lineno, $this->getTag());
    }


    /**
     * (non-PHPdoc)
     * @see v0.02/Sample/_opt/Twig/Twig_TokenParserInterface::getTag()
     */
    public function getTag()
    {
        // using tag name
        return 'aither';
    }
}
?>





Nodeクラス

当該クラスでトークンをコンパイルします。
TokenParserクラスと同様に、
使用するフレームワークとの整合性に
十分に配慮する必要があります。

<?php
/**
* Twig_Node_Sample
* @author spark43
*
*/
class Twig_Node_Sample extends Twig_Node
{
    /**
     * __construct
     * @param $name
     * @param $value
     * @param $lineno
     * @param $tag
     */
    public function __construct($param, $request, $lineno, $tag = null)
    {
        parent::__construct(array('param' => $param), array('request' => $request), $lineno, $tag);
    }

    /**
     * (non-PHPdoc)
     * @see v0.02/Sample/_opt/Twig/Twig_Node::compile()
     */
    public function compile($compiler)
    {
        $compiler->addDebugInfo($this);


        // prepare request (from token parser)
        $app = $this['request']->app['name'];
        $fct = $this['request']->fct['name'];
        $with = (isset($this['request']->with['name'])
                    ? $this['request']->with['name']
                    : VApp::BY_TPL);
        switch ($with) {
            case VApp::BY_OBJ:
            case VApp::BY_TPL:
                $withX = $with;
                break;
            default:
                $withX = VApp::BY_OBJ;
                break;
        }
        $compiler->write("\$req = new VRequest();\n")
                ->write("\$req->app = '". $app. "';\n")
                ->write("\$req->fct = '". $fct. "';\n")
                ->write("\$req->with = '". $withX. "';\n");

        // prepare parameters
        $param = $this->param;
        foreach ($param as $pk => $pv) {
            if ($pv instanceof Twig_Node_Expression_Name) {
                $compiler->write("\$req->". $pk. "=". $pv['name']. ";\n");
            }
            if ($pv instanceof Twig_Node_Expression_Constant) {
                $compiler->write("\$req->". $pk. "=". $pv['value']. ";\n");
            }
        }

        // execute requested app
        $compiler->write("\$vservice = new ThemeService(\$req);\n")
                ->write("\$aether_result = \$vservice->service();\n");
        switch ($withX) {
            case VApp::BY_OBJ:
                $compiler->write("\$context['". $with. "'] = \$aether_result;\n");
                break;
            case VApp::BY_TPL:
                $compiler->write("echo \$aether_result;\n");
                break;
        }
    }

}
?>




Twigでタグを作成する場合、それも特にNodeクラスを作成する場合には、

キャッシュしておくとcompile結果がキャッシュ・ファイルに出力されるので

compile結果がPHPとして正しく動作するか、

組み込むフレームワークとの連動が正しく行われるか、

実行結果がただしく画面表示されるか、

というようにソースコードのレベルでチェックできると思います。



このように、独自でタグを作成する場合には、

詳述しませんが、

 ・Tokenクラス

 ・TokenStreamクラス

 ・Nodeクラス

 ・Node/Expression/以下の、NodeExpressionクラス

などのソースを熟読することをお勧めしておきます。

2010年7月13日火曜日

twigのクラス階層図

doxygen+graphvizで、twigのクラス階層図を作成してみました。






ダウンロードして、拡大して、参照してみてください。

一応、ご参考まで。(あまり参考になりませんけど。)