<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://purl.org/rss/1.0/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:cc="http://web.resource.org/cc/"
    xmlns:admin="http://webns.net/mvcb/"
    xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
    xml:lang="ja">

    <channel rdf:about="http://devlog.sazysoft.com/index.rdf">
    <title>うばーぷろぐらみんぐ</title>
    <link>http://devlog.sazysoft.com/</link>
    <description>プログラミングに関する話題、その他雑記。</description>
    <dc:language>ja</dc:language>
    <admin:generatorAgent rdf:resource="http://lolipoblog.jp/?v=1.0"/>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=999855" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=973769" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=954315" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=947910" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=892863" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=883028" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=880560" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=877790" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=874917" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=874247" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=872289" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=870547" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=870475" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=862502" />
        <rdf:li rdf:resource="http://devlog.sazysoft.com/?eid=853811" />
      </rdf:Seq>
    </items>
    </channel>

  <item rdf:about="http://devlog.sazysoft.com/?eid=999855">
    <link>http://devlog.sazysoft.com/?eid=999855</link>
    <title>[Smarty] セレクトボックス生成関数（html_options）を使いやすくする</title>
    <description>Smartyにはデフォルトで「html_options」という関数が存在します。

[PHP側]


&amp;#36;smarty-&gt;assign( 'options', array(1,2,3) );



[テンプレート側]


&amp;#123;html_options name=test options=&amp;#36;options&amp;#125;



これで選択肢が「1,2,3」というセレ...</description>
<content:encoded><![CDATA[
Smartyにはデフォルトで「html_options」という関数が存在します。
<p><br>
[PHP側]
<pre class="prettyprint">

&#36;smarty->assign( 'options', array(1,2,3) );

</pre>

[テンプレート側]
<pre class="prettyprint">

&#123;html_options name=test options=&#36;options&#125;

</pre>
<p><br>
これで選択肢が「1,2,3」というセレクトボックスを出力できます。
<br>
しかし、決まりきった選択肢に対して、いちいちPHP側でコードを書くのは面倒です。
<p><br>
しかもこのhtml_options、id属性を指定できません。
<p><br>
そこで、その辺を改善する関数（zb_html_select_options）を作ってみました。
<p><br>
[テンプレート側]
<pre class="prettyprint">

&#123;zb_html_select_options id=test123 name=test options=1,2,3&#125;

</pre>

とするだけで、選択肢が「1,2,3」というセレクトボックスを出力できます。
id属性も出力できます。
<p><br>
また年月日など、数値を選択するセレクトボックスで選択肢を範囲指定できるようにしました。
<p><br>
[テンプレート側]
<pre class="prettyprint">

&#123;zb_html_select_options name=date_d id=selD options_from=1 options_to=31&#125;

</pre>

これで「１〜３１」までの日を選択できるリストボックスを生成できます。<br>
options_stepを指定すれば増分も指定できます。
<p><br>
更にevalを使って今日を選択できます。
<p><br>
[テンプレート側]
<pre class="prettyprint">

&#123;zb_html_select_options name=date_d id=selD options_from=1 options_to=31 selected=eval:date('j')&#125;

</pre>

パラメータの値が「eval:」で始まる文字列であった場合、それ以降の文字列をPHPの式としてevalした結果を設定します。
「selected=eval:date('j')」は今日を選択することになります。
<p><br>
「eval:」の記述は、options、options_from、options_to、options_step、selectedパラメータで指定可能です。
<p><br>
■書式
<p><br>
&#123;zb_html_select_options パラメータ=値&#125;
<p><br>
　　　パラメータ　　　　値<br>
----------------------------------------------------------<br>

id　　　　　　　　　selectタグのid属性を指定する。<br>

name　　　　　　　selectタグのname属性を指定する。<br>

class　　　　　　　selectタグのclass属性を指定する。<br>

style　　　　　　　selectタグのstyle属性を指定する。<br>

options　　　　　　OPTIONタグの配列。配列のkeyがvalueに、配列のvalue
が表示名になります。<br>
options_from　　　　数値を選択するセレクトボックスの場合に、下限値を指定する。optionsが指定された場合は無視される。<br>
options_to　　　　　数値を選択するセレクトボックスの場合に、上限値を指定する。optionsが指定された場合は無視される。<br>
options_step　　　　数値を選択するセレクトボックスの場合に、選択肢の間隔を指定する。optionsが指定された場合は無視される。<br>
selected　　　　　　初期状態で選択される値を指定する。<br>

<p><br>
■サンプル
<br>
年：現在の年−２〜＋２年の範囲　初期状態で現在の年を選択<br>
月：１〜１２の範囲　初期状態で現在の月を選択<br>
日：１〜３１の範囲　初期状態で現在の日を選択<br>

<pre class="prettyprint">

(&#123;zb_html_select_options name=reserve_date_y id=selY options_from=eval:date('Y')-2 options_to=eval:date('Y')+2 selected=eval:date('Y')&#125;)年
(&#123;zb_html_select_options name=reserve_date_m id=selM options=1,2,3,4,5,6,7,8,9,10,11,12 selected=eval:date('n')&#125;)月
(&#123;zb_html_select_options name=reserve_date_d id=selD options_from=1 options_to=31 selected=eval:date('j')&#125;)日

</pre>

<p><br>
■ダウンロード
<br>
<a href="http://sazysoft.com/downloads/zb_html_select_options.txt">zb_html_select_options.txt</a>
<p><br>

ダウンロード後、Smartyのpluginsフォルダに「function.zb_html_select_options.php」という名前で保存してください。
<p><br>

]]></content:encoded>
    <dc:subject>PHP</dc:subject>
    <dc:date>2009-11-03T16:38:17+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=973769">
    <link>http://devlog.sazysoft.com/?eid=973769</link>
    <title>配列＋プロパティ両方のアクセスができるクラスを作ってみました</title>
    <description>オブジェクトをSmartyにバインドしたとき、


&amp;#123;&amp;#36;hoge-&gt;bar&amp;#125;


と書くのが面倒に感じたり、Smartyに怒られてから「あれ、これオブジェクトだったっけ、それとも配列だったっけ？」とソースコードを読み返したりしたことはありませんか？
そんなものぐ...</description>
<content:encoded><![CDATA[
オブジェクトをSmartyにバインドしたとき、
<p><br>
<pre class="prettyprint">
&#123;&#36;hoge->bar&#125;
</pre>
<p><br>
と書くのが面倒に感じたり、Smartyに怒られてから「あれ、これオブジェクトだったっけ、それとも配列だったっけ？」とソースコードを読み返したりしたことはありませんか？<br>
そんなものぐさなPHPerの方のために、配列のようにも、オブジェクトのようにもアクセスできるクラスを作ってみました。
<p><br>

<pre class="prettyprint">
&lt;?php

class DualObject implements Iterator, ArrayAccess
&#123;
  private &#36;__data;
  private &#36;__field_list;

  /*
   *  コンストラクタ
   */
  public function __construct()
  &#123;
    &#36;this->__data   = array();

    // __で始まるフィールドは除外
    &#36;this->__field_list = array();
    &#36;vars = get_object_vars(&#36;this);
    foreach( &#36;vars as &#36;key => &#36;value )&#123;
      if ( strpos(&#36;key,'__')===FALSE )&#123;
        &#36;this->__field_list[] = &#36;key;
      &#125;
    &#125;
  &#125;

  /*
   *  ArrayAccessインタフェース:offsetGetの実装
   */
  public function offsetGet(&#36;offset)
  &#123;
    if ( &#36;offset instanceof Object )&#123;
      &#36;offset = &#36;offset->s();
    &#125;
    if ( property_exists(&#36;this, &#36;offset) ) &#123;
      return &#36;this->&#36;offset;
    &#125;
    return isset(&#36;this->__data[&#36;offset]) ? &#36;this->__data[&#36;offset] : NULL;
  &#125;

  /*
   *  ArrayAccessインタフェース:offsetSetの実装
   */
  public function offsetSet(&#36;offset, &#36;value)
  &#123;
    if ( &#36;offset instanceof Object )&#123;
      &#36;offset = &#36;offset->s();
    &#125;
    if ( property_exists( &#36;this, &#36;offset ) )&#123;
      &#36;this->&#36;offset = &#36;value;
    &#125;
    else &#123;
      &#36;this->__data[&#36;offset] = &#36;value;
      if ( FALSE === array_search( &#36;offset, &#36;this->__field_list ) )&#123;
        &#36;this->__field_list[] = &#36;offset;
      &#125;
    &#125;
  &#125;

  /*
   *  ArrayAccessインタフェース:offsetExistsの実装
   */
  public function offsetExists(&#36;offset)
  &#123;
    if ( &#36;offset instanceof String )&#123;
      &#36;offset = &#36;offset->s();
    &#125;
    return FALSE !== array_search( &#36;offset, &#36;this->__field_list );
  &#125;

  /*
   *  ArrayAccessインタフェース:offsetUnsetの実装
   */
  public function offsetUnset(&#36;offset)
  &#123;
    if ( &#36;offset instanceof Object )&#123;
      &#36;offset = &#36;offset->s();
    &#125;
    if ( property_exists( &#36;this, &#36;offset ) )&#123;
      unset(&#36;this->&#36;offset);
    &#125;
    if ( isset(&#36;this->__data[&#36;offset]) )&#123;
      unset(&#36;this->__data[&#36;offset]);
    &#125;
    &#36;pos = array_search( &#36;offset, &#36;this->__field_list );
    if ( FALSE !== &#36;pos )&#123;
      unset(&#36;this->__field_list[&#36;pos]);
    &#125;
  &#125;

  /*
   *  Iteratorインタフェース:rewidの実装
   */
  public function rewind()
  &#123;
    reset(&#36;this->__field_list);
  &#125;

  /*
   *  Iteratorインタフェース:currentの実装
   */
  public function current()
  &#123;
    &#36;offset = current(&#36;this->__field_list);
    return &#36;this->offsetGet(&#36;offset);
  &#125;

  /*
   *  Iteratorインタフェース:keyの実装
   */
  public function key()
  &#123;
    return current(&#36;this->__field_list);
  &#125;

  /*
   *  Iteratorインタフェース:nextの実装
   */
  public function next()
  &#123;
    return next(&#36;this->__field_list);
  &#125;

  /*
   *  Iteratorインタフェース:validの実装
   */
  public function valid()
  &#123;
    &#36;offset = current(&#36;this->__field_list);
    return &#36;this->offsetExists(&#36;offset);
  &#125;

  /*
   *  プロパティアクセス（取得）
   */
  public function __get( &#36;name )
  &#123;
    return &#36;this->offsetGet(&#36;name);
  &#125;

  /*
   *  プロパティアクセス（設定）
   */
  public function __set( &#36;name, &#36;value )
  &#123;
    &#36;this->offsetSet(&#36;name, &#36;value);
  &#125;


  /*
   *  dump
   */
  public function dump()
  &#123;
    print "--------------[ dump start ]--------------" . nl2br(PHP_EOL);
    foreach( &#36;this as &#36;key => &#36;value )&#123;
      print "[&#36;key]&#36;value" . nl2br(PHP_EOL);
    &#125;
    print "--------------[ dump end ]--------------" . nl2br(PHP_EOL);
  &#125;
&#125;

</pre>
<p><br>

使い方はこんな感じ。
<p><br>

<pre class="prettyprint">
&lt;?php

require_once 'dual_object.php';

class MyObject extends DualObject
&#123;
  public &#36;foo;
&#125;

&#36;o = new MyObject();

&#36;o->dump();

// 通常のpublicフィールドアクセス
&#36;o->foo = 'Boo!';

// 配列でもアクセスできる
&#36;o['foo'] = 'Bazz!';

// 定義していなくてもアクセスできる
&#36;o['bar'] = 'Woot!';
&#36;o->dump();
&#36;o->bar = 'Mzzzz';
&#36;o->dump();

// 読み取りもできる
echo 'o:foo=' . &#36;o['foo'] . nl2br(PHP_EOL);
echo 'o:foo=' . &#36;o->foo . nl2br(PHP_EOL);
echo 'o:bar=' . &#36;o['bar'] . nl2br(PHP_EOL);
echo 'o:bar=' . &#36;o->bar . nl2br(PHP_EOL);

&#36;o->dump();

</pre>
<p><br>
出力結果。

<pre class="prettyprint">
--------------[ dump start ]--------------
[foo]
--------------[ dump end ]--------------
--------------[ dump start ]--------------
[foo]Bazz!
[bar]Woot!
--------------[ dump end ]--------------
--------------[ dump start ]--------------
[foo]Bazz!
[bar]Mzzzz
--------------[ dump end ]--------------
o:foo=Bazz!
o:foo=Bazz!
o:bar=Mzzzz
o:bar=Mzzzz
--------------[ dump start ]--------------
[foo]Bazz!
[bar]Mzzzz
--------------[ dump end ]--------------
</pre>
<p><br>

DualObjectを継承して使うとPHP側でプロパティアクセスし、Smarty側では配列としてアクセスするといった使い方ができます。
<br>
ちなみにIteratorも実装しているので、Dual#dump()を見ても分かるように、
<p><br>
<pre class="prettyprint">
  &#36;obj = new MyObject();
  &#36;obj->foo = 'bar';
  ...
  foreach( &#36;obj as &#36;key => &#36;value )&#123;
    ...
  &#125;
</pre>
<p><br>
のように記述してオブジェクトのプロパティと値を列挙することができます。


]]></content:encoded>
    <dc:subject>PHP</dc:subject>
    <dc:date>2009-07-21T18:49:48+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=954315">
    <link>http://devlog.sazysoft.com/?eid=954315</link>
    <title>さくらでWAFをONにするとPHPSESSIDがENC_PHPSESSIDになってセッション復元できない件</title>
    <description>タイトル長い（笑）

OpenPNEである日突然招待メール送信時の画像認証（キャプチャ画像による認証）ができなくなってしまい、ハマってしまったので、メモ。

エラー内容は、「確認キーワードが誤っています」。

登録時のエラー箇所で_SESSIONの中を見てみると、確...</description>
<content:encoded><![CDATA[
タイトル長い（笑）<br>
<p>
OpenPNEである日突然招待メール送信時の画像認証（キャプチャ画像による認証）ができなくなってしまい、ハマってしまったので、メモ。<br>
<p>
エラー内容は、「確認キーワードが誤っています」。
<p>
登録時のエラー箇所で_SESSIONの中を見てみると、確かに空。<br>
っていうか、何も入ってない。<br>
<p>
なんだこりゃ、ってことで、キャプチャ画像を生成している部分を確認。<br>
public_html/cap.phpからkcapctha.phpを呼び出している。こいつか？<br>
と思うが、特にセッションがらみのロジックは無い。<br>
そこで、Kcaptchaのロジックを外し、session_start()したあとのヘッダ情報を確認してみるが、PHPSESSIDが正しく吐かれている。<br>
がしかし、ブラウザが受け取るクッキーは
<p>
Cookie: ENC_PHPSESSID=%2becFX2FNcQbB61OuymsUNxFW6NVBmuTaOW/sfxrJuahEguweCV3eRLQoQhDiD2L5
<p>
みたいになっている。<br>
なんでやーと１日悩みました・・・が、サーバのコントロールパネルを見ていてハタと気づきました。<br>
<p>
-------------------------------------------------------<br>
本機能を有効にすることにより、ソフトウェアの動作やインストールに影響が出る場合があります。 ご利用の前に必ずこちらをご一読ください。 <br>
-------------------------------------------------------<br>
<p>
これか！（笑
<p>
てことで、サーバのWAF設定を外してみると、ビンゴ、見事にセッションを復元できました。
<p>
多分、
<p>
ブラウザ　←→　WAF　←→　Webサーバ
<p>
って構成になってて、WAFでENC_PHPSESSIDとPHPSESSIDの変換をしているんだろうなと。<br>
んー、しかしこんな簡単な簡単なロジックで復元できないとなると、WAFってあんまり意味ないようなｗ<br>
（パソコンで言うと、ウィルスも駆除する代わりにExcelが起動できなくなるウィルス対策ソフトみたいなｗ）


]]></content:encoded>
    <dc:subject>OpenPNE</dc:subject>
    <dc:date>2009-05-15T15:34:22+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=947910">
    <link>http://devlog.sazysoft.com/?eid=947910</link>
    <title>CharcoalPHP 1.0 Coming soon</title>
    <description>久しぶりの投稿になります。

ここ最近PHP案件ばかりやっていたのですが、
ここ最近よく感じるのは、PHPってなんだかんだでやっぱり生産性いいよなあとか、ふざけんなPHPつかえねーとかいいんだか悪いんだかなPHPがやっぱり好きだなってことですね。PHPのすごさはCやJa...</description>
<content:encoded><![CDATA[
久しぶりの投稿になります。

ここ最近PHP案件ばかりやっていたのですが、
ここ最近よく感じるのは、PHPってなんだかんだでやっぱり生産性いいよなあとか、ふざけんなPHPつかえねーとかいいんだか悪いんだかなPHPがやっぱり好きだなってことですね。PHPのすごさはCやJavaにありがちなFatalError系のヨクワカランエラーがほとんど出ないことと、いろんなライブラリを用意しなくても最初からある程度のことができるのにあまり重さを感じないことだと思います。

<p>

そんなPHPのライトな思想にJavaのインタフェース設計の思想を持ち込もうとして作ったのがCharcoalPHPなわけですが、最近になってインタフェースはいいけれども、設定ファイルが増えるのはPHPらしくないなと。
かと言ってすべての設定をコードで書くのも何かが違う・・・なにがいいんだろうとしばらく考えていました。
その結果がもう少しで出てきそうなので、この際メジャーバージョンでもリリースしてしまうかと思っています。ちょっと危険かなー？（苦笑

<p>
今考えているのは、

<p>
・ディレクトリ構成をプログラム動作に反映させる（配置するだけで使えるようになるとか）<br>
・開発モードを実装し、クラスが見つからない場合、配置先を自動でパースしてautoloadコードを自動生成する（リロードするとエラーが出なくなるイメージです）<br>
・プログラムの分割単位として、ディレクトリ単位といった小さなファイルセットで動作するモジュールのようなものの導入<br>
・自前でクラス定義をするケースを極力なくすための、フレームワーク提供イベントクラス、タスククラスを充実させる<br>

<p>
といったことで、地味ですが、設定ファイルを無くしたり小さな単位で再利用可能とすることでかなり生産性を向上できるのではないかと思っています。

]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2009-04-24T01:53:00+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=892863">
    <link>http://devlog.sazysoft.com/?eid=892863</link>
    <title>CharcoalPHP 0.11.0リリース</title>
    <description>本日CharcoalPHP 0.11.0をリリースしました。 



・複数のリクエストに渡ってデータを保持できるタスクであるステートフルタスクを実装しました。



ステートフルタスクの実装は簡単です。通常のタスクの実装に加えて、IStatefulインタフェースを実装するだけで...</description>
<content:encoded><![CDATA[
本日CharcoalPHP 0.11.0をリリースしました。 
<p><br>

<blockquote>
・複数のリクエストに渡ってデータを保持できるタスクであるステートフルタスクを実装しました。
</blockquote>
<p><br>

ステートフルタスクの実装は簡単です。通常のタスクの実装に加えて、IStatefulインタフェースを実装するだけです。ステートフルタスクの保持するデータはフレームワークにより自動的に保存／復元されます。保存データはセッションハンドラ経由でファイル等に書き出されます。
<p><br>

CharcoalPHP 0.10.0は下記のページからダウンロードできます。 
<p><br>

<a href="http://sourceforge.jp/projects/charcoalphp/files/">http://sourceforge.jp/projects/charcoalphp/files/</a>
<p><br>

]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-11-08T21:24:17+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=883028">
    <link>http://devlog.sazysoft.com/?eid=883028</link>
    <title>CharcoalPHP 0.10.0リリース</title>
    <description>本日CharcoalPHP 0.10.0をリリースしました。 


・タスクまたはページセレクタの実行中に他のタスクの状態を取得できるようになりました（TaskSnapshot）
・SmartGatewayのfind系メソッドでこれまでITableModelを指定していましたが、テーブルモデル名を渡すようにし...</description>
<content:encoded><![CDATA[
本日CharcoalPHP 0.10.0をリリースしました。 

<blockquote>
・タスクまたはページセレクタの実行中に他のタスクの状態を取得できるようになりました（TaskSnapshot）<br>
・SmartGatewayのfind系メソッドでこれまでITableModelを指定していましたが、テーブルモデル名を渡すようにしました<br>
・タスクでドメインモデルを扱えるようになりました。将来的にはフォームモデル、テーブルモデル同様にバリデータによる検証ができるように考えています。<br>
・フォームモデルまたはテーブルモデル固有のDTOを使用できるようになりました。固有DTOを使うにはモデルクラスのcreateDTOをオーバライドします。これはオプションであり、デフォルトはこれまで通りDTOクラスを使用します。<br>
</blockquote>

　今回は最初の「TaskSnapshot」の変更が目玉です。これまでタスクの実行中は他のタスクの状態を取得できませんでしたが、processEvent()メソッドの第二引数にTaskSnapshotが追加され、このオブジェクトを通してメソッド呼び出し直前の他のタスクのプロパティを取得することができます（メソッドを呼び出すことはできません）。<br>
　この変更によりタスク同士の祖結合を保ったまま、お互いの状態に応じた処理をすることができるようになりました。<br>
　利用シーンとしては、今回追加されたドメインモデルタスクを他のタスクで参照し、処理を行うといった使い方を想定しています。<br>
　ページセレクタも、これまでタスクマネージャから直接タスクにアクセスできていましたが、TaskSnapshot経由でアクセスするように変更しました。
<p><br>

CharcoalPHP 0.10.0は下記のページからダウンロードできます。 
<p><br>

<a href="http://sourceforge.jp/projects/charcoalphp/files/">http://sourceforge.jp/projects/charcoalphp/files/</a>

]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-10-12T01:36:45+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=880560">
    <link>http://devlog.sazysoft.com/?eid=880560</link>
    <title>CharcoalPHP 0.9.0リリース</title>
    <description>本日CharcoalPHP 0.9.0をリリースしました。 


今回も大きな機能的な変更はありませんが、タスク関連の処理方式が大きく変わりました。


以前はタスクの処理順序はプロシージャのtask_orderで指定していましたが、より柔軟な処理フローができるように下記の様に変...</description>
<content:encoded><![CDATA[
本日CharcoalPHP 0.9.0をリリースしました。 
<p><br>

今回も大きな機能的な変更はありませんが、タスク関連の処理方式が大きく変わりました。
<p><br>

以前はタスクの処理順序はプロシージャのtask_orderで指定していましたが、より柔軟な処理フローができるように下記の様に変更しました。
<p><br>

<blockquote>
・プロシージャ定義ファイルのtasksで定義されたタスクがタスクマネージャに登録される<br>
・タスクマネージャは受け取ったリクエストを元にhttp_requestシステムイベントを生成、各登録タスクに送信<br>
・タスクは定義ファイルのevent_filtersで受け入れ可能なイベントを定義する。受け入れ可能なイベントはIEventインタフェースを実装するユーザイベントまたはシステムイベント。<br>
・event_filtersで指定されているイベントなら、タスクマネージャはそのタスクのprocessEvent()メソッドを呼び出す。<br>
・タスクのprocessEventメソッド内ではイベントを実際に処理したかのフラグ（Boolean値）または、ユーザイベントを戻り値として返す。<br>
・タスクマネージャはタスクの処理結果を受け取り、ユーザイベントのイベントキューへの追加や現在のイベントの消去などを行う。<br>
・新たにイベントキューに追加されたイベントは、次回以降のイベント実行ループで処理される。<br>
・タスクの処理条件はguard_conditionsで指定可能。例えば「ログインタスクのプロパティloginedがTRUEの時のみこのタスクを実行する」などの条件指定が可能。<br>
・イベントキューにイベントが無いか、タスク実行リストにタスクが無くなったらイベント処理を終了する。<br>
</blockquote>
<p><br>

processEvent()でユーザイベントを返却できるようになったことで、祖結合のままタスク間の連携が取れるようになりました。<br>
たとえば、Aタスクがhttp_requestを処理し、その結果をXイベントにセットしてタスクマネージャ経由でBタスクに渡すことが出来ます。<br>
AタスクはBタスクの存在を知らずに実装でき、またBタスクもAタスクの存在に依存しないため、仕様変更の影響範囲を限定しやすくできます。
<p><br>

CharcoalPHP 0.9.0は下記のページからダウンロードできます。 
<p><br>

<a href="http://sourceforge.jp/projects/charcoalphp/files/">http://sourceforge.jp/projects/charcoalphp/files/</a>

]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-10-05T10:42:00+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=877790">
    <link>http://devlog.sazysoft.com/?eid=877790</link>
    <title>CharcoalPHP 0.8.0リリース</title>
    <description>本日CharcoalPHP 0.8.0をリリースしました。 


大きな機能追加はありませんが、コーディングをする上で幾つか大きな変更がありました。



・タスク処理機構の改善
・TypeHintingの追加



前者はタスクのprocessEventメソッドからイベントを返却することで...</description>
<content:encoded><![CDATA[
本日CharcoalPHP 0.8.0をリリースしました。 
<p><br>

大きな機能追加はありませんが、コーディングをする上で幾つか大きな変更がありました。
<p><br>

<blockquote>
・タスク処理機構の改善<br>
・TypeHintingの追加<br>
</blockquote>
<p><br>

前者はタスクのprocessEventメソッドからイベントを返却することで、別のタスクとの連携が可能になりました。
<p><br>

後者は引数に指定するデータ型をコンパイル時にチェックすることで、よりタイプセーフなプログラミングが可能になりました。
<p><br>

CharcoalPHP 0.8.0は下記のページからダウンロードできます。
<p><br>

<a href="http://sourceforge.jp/projects/charcoalphp/files/">http://sourceforge.jp/projects/charcoalphp/files/</a>



]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-09-28T11:16:53+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=874917">
    <link>http://devlog.sazysoft.com/?eid=874917</link>
    <title>タスクベースフレームワーク　Tremolo</title>
    <description>CharcoalPHPのバージョン1.0を開発中ですが、今まで（実際は0.5.0まで）と仕組み上全く異なっている現実がありますので、コードネームを付けたいと思います。


名前は「Tremolo（トレモロ）」です。


音楽用語で「小刻みに演奏する方法」を指す言葉らしいのですが...</description>
<content:encoded><![CDATA[
CharcoalPHPのバージョン1.0を開発中ですが、今まで（実際は0.5.0まで）と仕組み上全く異なっている現実がありますので、コードネームを付けたいと思います。
<p><br>

名前は「Tremolo（トレモロ）」です。
<p><br>

音楽用語で「小刻みに演奏する方法」を指す言葉らしいのですが、私自身は全く音楽に疎いのですが、語感が気に入ったので決めました。<br>
また、頭文字が「Task」の「T」にしたかったというのもあります。<br>
<p><br>

とりあえずTremolo1.0からは以下のことができます。
<p><br>

<blockquote>
・タスク＋イベントによる擬似並列Webプログラミング。<br>
・CSMLによるウィジェットマークアップ。<br>
</blockquote>
<p><br>

その他、1.1以降では以下の機能の実装も予定しています。

<blockquote>
・コマンドラインからのタスク制御<br>
・Scaffolding<br>
・コンポーネント共有サイトの開設<br>
・汎用インストーラ<br>
・Tremolo上に構築されるCMS<br>
・自動テストツール<br>
</blockquote>
<p><br>


]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-09-20T14:41:06+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=874247">
    <link>http://devlog.sazysoft.com/?eid=874247</link>
    <title>CharcoalPHP 0.7.0リリース</title>
    <description>CharcoalPHP 0.7.0をリリースしました。


大きな変更点として、



・レイアウトマネージャを廃止
・ページセレクタを導入



ページセレクタにより、タスクとビューの橋渡しと分離が明確になりました。


CharcoalPHP 0.7.0は下記のページからダウンロー...</description>
<content:encoded><![CDATA[
CharcoalPHP 0.7.0をリリースしました。
<p><br>

大きな変更点として、
<p><br>

<blockquote>
・レイアウトマネージャを廃止<br>
・ページセレクタを導入<br>
</blockquote>
<p><br>

ページセレクタにより、タスクとビューの橋渡しと分離が明確になりました。
<p><br>

CharcoalPHP 0.7.0は下記のページからダウンロードできます。
<p><br>
<a href="http://sourceforge.jp/projects/charcoalphp/files/
">http://sourceforge.jp/projects/charcoalphp/files/</a>


]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-09-18T17:53:12+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=872289">
    <link>http://devlog.sazysoft.com/?eid=872289</link>
    <title>include/require系ステートメントの戻り値を使って、どのファイルが実際に読まれたか知る</title>
    <description>Tipsです。


includeするのにいちいちフルパスで読み込みたくない場合、include_pathを山のように定義してしまう場合があります（パフォーマンス上よくないそうな）。その場合、実際にどのソースファイルが読み込まれたのか分からなくなる場合があります。特に同名の...</description>
<content:encoded><![CDATA[
Tipsです。
<p><br>

includeするのにいちいちフルパスで読み込みたくない場合、include_pathを山のように定義してしまう場合があります（パフォーマンス上よくないそうな）。その場合、実際にどのソースファイルが読み込まれたのか分からなくなる場合があります。特に同名のソースファイルを複数扱うような場合（あんまりないとは思いますが）とか、読んでるのか読んでないのか分からないケース（笑）など、実際に読み込んだソースファイルの場所が分かると便利です。
<p><br>

マニュアルによるとinclude/require系のステートメントは読み込んだ先のソースファイルでreturnした値を戻り値として返します。
なら読み込むべきソースの最後でそのソースファイルのパスを返してやれば実際に（エラーなく読み込まれた場合は、ですが）読み込まれたパスをコールした側で取得できるはず。
<p><br>

ソースはこんな感じで。
<p><br>

[/var/htdocs/hoge.php :読み込まれる方]
<pre class="prettyprint">
&lt;?php

class Hoge
&#123;
    ....
&#125;

return __FILE__;          ....&lt;--これを追加

?&gt;
</pre>

[/var/htdocs/main.php :読み込む方]
<pre class="prettyprint">
&lt;?php

&#36;ret = include( 'hoge.php' );

print &#36;ret;           // --&gt; /var/htdocs/hoge.php
?&gt;
</pre>

結果をログファイルなどに吐き出すようにすれば、幸せになれる？
<p><br>
XDebugとか入ってたらプロファイラで確認できるのでしょうが、ちょっとしたデバッグとかには有効かもしれません。

]]></content:encoded>
    <dc:subject>PHP</dc:subject>
    <dc:date>2008-09-13T05:31:28+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=870547">
    <link>http://devlog.sazysoft.com/?eid=870547</link>
    <title>CSML(Charcoal　Screen　Markup　Language）</title>
    <description>CharcoalPHPの標準ビューを構成する要素として、CSML(Charcoal Screen Markup Language）というDSL（ドメイン特化言語）を考えています。Smartyの欠点として、



・速度が遅い
・テンプレートが汚くなり（ロジックが書けてしまう）、デザイナーとの協業がしにくい
...</description>
<content:encoded><![CDATA[
CharcoalPHPの標準ビューを構成する要素として、CSML(Charcoal Screen Markup Language）というDSL（ドメイン特化言語）を考えています。Smartyの欠点として、
<p><br>

<blockquote>
・速度が遅い<br>
・テンプレートが汚くなり（ロジックが書けてしまう）、デザイナーとの協業がしにくい<br>
・再利用性が低い<br>
</blockquote>
<p><br>

などがありますが、２番目の「テンプレート汚染」についてはPHPTALやKwartzを使うことである程度解決できます。
<p><br>
しかし３番目の「再利用性」について考えられているテンプレートシステムはあまりなく、考えられていたとしてもそれはテンプレートファイルの再利用であり、ビジュアルコードの再利用についてまで考えられたテンプレートシステムはPHPでは私の知る範囲では皆無です。
<p><br>
そこで、下記のようなテンプレートシステムを考案しました。
<p><br>

<blockquote>
・テンプレートファイルはプレーンなHTML<br>
・ビジュアルコードは「ウィジェット」と呼ばれるクラスにまとめられる<br>
・ウィジェットのテンプレートHTML内の要素へのバインドはXMLを使う<br>
</blockquote>
<p><br>

こうすることで、テンプレートとロジックの分離とともにビジュアルコードの再利用性も高められるわけです。このXMLを冒頭で紹介した「CSML（Chacoal Screen Markup Language）と名づけました。
<p><br>

下記はCSMLとテンプレート（HTML）のサンプルです。
<p><br>

[CSML]
<pre class="prettyprint">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;csml:page xmlns:csml=&quot;http://charcoal.net/csml/ns/&quot;&gt;
  &lt;csml:widget id=&quot;header_panel&quot; class=&quot;HeaderPanelWidget&quot;&gt;
  &lt;csml:widget id=&quot;menu&quot; class=&quot;MenuWidget&quot;&gt;
  &lt;csml:widget id=&quot;main_panel&quot; class=&quot;MainPanelWidget&quot;&gt;
  &lt;csml:widget id=&quot;footer_panel&quot; class=&quot;FooterPanelWidget&quot;&gt;
&lt;/csml:page&gt;
</pre>
<p><br>
[HTMLテンプレート]
<pre class="prettyprint">
&lt;html&gt;
&lt;body&gt;
&lt;div id=&quot;header_panel&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;menu&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;main_panel&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;footer_panel&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

<p><br>
実際、レンダリングを行う時はCSMLとHTMLを関連付けする必要がありますが、それはレイアウトマネージャの方で行います。ですので同じCSMLを異なるHTMLテンプレートに関連付けることも出来ます。タスクの実行結果によって見栄えを大きく変更する場合などに便利な機能です。
<p><br>

HTMLテンプレートの要素とCSML要素の対応はid属性で行います。同じidのHTML要素の位置に、CSMLに記述されたウィジェットクラスのコードが展開されます。コードは描画時に評価されますが、Smartyなどと同じように、展開後のコードはキャッシュされるため、展開にかかるコストは最初の１回だけになります。
<p><br>

ビューコードを記述するウィジェットクラスでは直接HTMLを出力できるほか、更にCSMLを適用すると言った使い方ができます。この方法を使うと、ウィジェットを「塊」で管理することができるようになり、部品の再利用性が高まります。
<p><br>

まだ構想段階ではありますが、CharcoalPHPの次期バージョン（0.7.0）では基本的な機能を実装できればと思っています。

]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-09-08T17:32:27+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=870475">
    <link>http://devlog.sazysoft.com/?eid=870475</link>
    <title>CharcoalPHP 0.6.0リリース</title>
    <description>もうすぐCharcoalPHP 0.6.0をリリースします。少し間が空いてしまいましたが、いろいろと模索していました。


≪パフォーマンス≫

・実行速度が向上


≪設定ファイル関係≫

・デフォルトをSpycからJavaプロパティファイル形式に変更
・Configクラスのインタフ...</description>
<content:encoded><![CDATA[
もうすぐCharcoalPHP 0.6.0をリリースします。少し間が空いてしまいましたが、いろいろと模索していました。
<p><br>

≪パフォーマンス≫
<br>
・実行速度が向上<br>
<p><br>

≪設定ファイル関係≫
<br>
・デフォルトをSpycからJavaプロパティファイル形式に変更<br>
・Configクラスのインタフェースを変更<br>
・システム設定ファイルをアプリケーション設定ファイルでオーバロードできるようにした<br>

<p><br>
≪デバッグ関係≫
<br>
・例外スタック（ExceptionStack）クラスの実装<br>
・スクリーンロガー（ScreenLogger）クラスの修正とポップアップするスクリーンロガー（PopupScreenLogger）クラスの実装<br>

<p><br>
≪プロファイル関係≫
<br>
・デフォルトで外部ライブラリパスを無効にし、プロファイルに有効にするフラグ（USE_EXTLIB）とパス変数（EXTLIB_DIR）を追加した<br>

<p><br>
≪その他≫
<br>
・TypeSafeのためのプリミティブクラス（Boolean、Integer、String）を追加<br>

<p><br>
パフォーマンスについてですが、abコマンドでの測定では以下のようになりました。
<p><br>

<pre class="prettyprint">
CodeIgniter　68.07 #/sec 14.69 ms/#
CharcoalPHP  42.94 #/sec 23.28 ms/#
</pre>

<p><br>
0.5.0では30#/secほどでしたから、50%近い速度の向上を実現しました。

<p><br>
これはデフォルトの設定ファイル形式をSpycからiniファイル（実際はJavaプロパティファイル形式）に変更したことが大きいです。やはりparse_ini_fileは高速ですね。

<p><br>


]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-09-08T12:45:21+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=862502">
    <link>http://devlog.sazysoft.com/?eid=862502</link>
    <title>CharcoalPHP1.0はActorModelをベースに</title>
    <description>CharcoalPHP1.0に向けて構想を練っています。
その間の縫って、Runkitを使ってプロファイラを作って見たり、ChacoalPHPの設定ファイル周りが余りに遅いのでparse_ini_fileと
spycのベンチを取ってみたり、いろいろしていました。


プロファイラの方はWindows版で落...</description>
<content:encoded><![CDATA[
CharcoalPHP1.0に向けて構想を練っています。
その間の縫って、Runkitを使ってプロファイラを作って見たり、ChacoalPHPの設定ファイル周りが余りに遅いのでparse_ini_fileと
spycのベンチを取ってみたり、いろいろしていました。
<p><br>

プロファイラの方はWindows版で落ちてしまうため、あえなく断念。うまくすれば
AOPもいけるよねと期待していただけに残念でした。
<p><br>

parse_ini_fileとSpycのベンチはもちろんparse_ini_fileの圧勝でしたが、その結果は標準の設定ファイル形式としてYAMLとPHPを捨てさせるのに十分なものでした。というわけで、次期リリースではparse_ini_fileを使い、Javaのプロパティファイルっぽいフォーマットにしようかと画策中。
<p><br>

ところで最近Scalaというプログラミング言語に興味を持っているのですが、Scalaは「アクター」
（Actor）というものが使えるらしいと知り、調べて見ました。
<p><br>

アクター（Actor）とは、もともと並列処理のための計算モデルである「Actor Model」
からきています。Scalaのそれは並列処理指向言語であるErlangから拝借したものらしい
です。
<p><br>

Actor自体はメッセージを受け付けるスレッドのようなもので、内部で何らかのトリガーが発生するか、外部からのメッセージを受け取って
処理を行う処理体のことをいいます。
<p><br>

この考え方自体は並列コンピューティングの世界で古くからあるものですが、昨今スケー
リングやらCPUのマルチコア化などで再度注目を浴びています。
<p><br>

調べていくうち、この考え方ってCharcoalPHPの方向性（タスク）とそっくりだなーと
感じるようになりました。実際には細かいところで考え方や実装の
異なる点があるようには感じています。
大まかに「プログラムに並列性を導入することでロジックを簡略化する」という点は
一致しますが、アクターモデルでは「それにより並列性を上げる」のが目的であるの
に対し、CharcoalPHPでは「それにより再利用性を高める」のが目的である点が違いと
言えるでしょう。
<p><br>

というわけで、CharcoalPHPでは「アクターモデル」を中心概念として採用します。
DI+AOPも採用する可能性がありますが、型付けの弱い言語であるPHPでは費用対効果が少ないという
見通しをしているので、採用されたとしてもあくまで補助的な扱いになるでしょう。
<p><br>

]]></content:encoded>
    <dc:subject>Charcoal フレームワーク</dc:subject>
    <dc:date>2008-08-18T01:29:49+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

  <item rdf:about="http://devlog.sazysoft.com/?eid=853811">
    <link>http://devlog.sazysoft.com/?eid=853811</link>
    <title>Kwartzで実行時にテンプレートをコンパイルする方法</title>
    <description>Kwartzはプレゼンテーションロジックとプレゼンテーションデータの分離を実現するテンプレートシステムです。本来テンプレートとはデザイナーとの分業が目的だったわけですが、Smartyなどではどうしてもテンプレートファイルにロジックが混入してしまうので、デザイナーと...</description>
<content:encoded><![CDATA[
Kwartzはプレゼンテーションロジックとプレゼンテーションデータの分離を実現するテンプレートシステムです。本来テンプレートとはデザイナーとの分業が目的だったわけですが、Smartyなどではどうしてもテンプレートファイルにロジックが混入してしまうので、デザイナーと事前にロジック部分の扱いを取り決めておかなければならないなど、完全な分業が不可能です。
Kwartzはテンプレートファイルからロジック部分を完全に排除することができるため、デザイナーはHTMLとCSSのコーディングのみに集中し、プログラマはロジック部分のみに集中することができるわけです。
<p><br>

Kwartzは下記からダウンロードすることができます。
<p><br>
<a href="http://www.kuwata-lab.com/kwartz/" target="_blank">http://www.kuwata-lab.com/kwartz/</a>
<p><br>

Ruby版、PHP版、Java版がありあますので、PHP版をダウンロードします。ダウンロードしたファイルを解凍後、Kwartzディレクトリ以下をPHPのinclude_path以下にコピーすればインストール完了です。
<p><br>

次に以下のファイルを作成してHTTPサーバのhtdocsに配置します。
<p><br>

[index.php]
<pre class="prettyprint">
require_once('Kwartz/Main.php');

&#36;argv = array('kwartz-php', '-l', 'php', '-p', 'my.plogic', 'my.html' );

ob_start();
KwartzMain::main(&#36;argv);
&#36;out = ob_get_clean();

/*
// こういう書き方もできるようです
&#36;kwartz = new KwartzMain(&#36;argv);
&#36;out = &#36;kwartz->execute();
*/

file_put_contents('cache.php', &#36;out);

&#36;members = array( 'member1', 'member2', 'member3', );

include('cache.php');

</pre>
<p><br>

[my.plogic]
<pre class="prettyprint">
/* The element which is marked by 'id="list1"' */
#list1 &#123;
  logic: &#123;
    foreach( &#36;members as &#36;member )&#123;
      _stag()           // start tag
      _cont()           // content
      _etag()           // end tag
    &#125;
  &#125;
&#125;

/* The element which is marked by 'id="mark:item1"' */
#item1 &#123;
  /* replace the content with value of a variable 'member' */
  value: &#36;member;
&#125;

</pre>
<p><br>

[my.html]
<pre class="prettyprint">
&lt;table&gt;
  &lt;tr id="list1"&gt;
    &lt;td id="mark:item1"&gt;foo&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
</pre>
<p><br>

仕組みとしては、index.phpにアクセスするとまずKwartzによりmy.plogic（ロジック記述用ファイル）とmy.html（HTMLテンプレート）がコンパイルされ、PHPファイルが出力されます（cache.php）。次にテンプレート出力用の変数を用意して、cache.phpをincludeします。includeによりテンプレートPHPファイルが解釈され、変数の内容が出力されます。
<p><br>

このようにロジックファイルとテンプレートファイルが分離しているため、非常にメンテナンスはしやすいです。
<p><br>

なお、Kwartzにはコマンドラインツールも用意されていますので、テンプレートPHPファイルは事前にコンパイルしてもいいのですが、上記のようにすることでSmartyのように実行時にテンプレートファイルを更新することができます。

]]></content:encoded>
    <dc:subject>PHP</dc:subject>
    <dc:date>2008-07-30T01:02:55+09:00</dc:date>
    <dc:creator>stk2k</dc:creator>
    <dc:rights>stk2k</dc:rights>
  </item>

</rdf:RDF>