前回までの作業によって、
Piece_Unity_Component_Flexy 1.0.0から1.1.0へのアップグレード
今回からはPiece_
> pear.bat upgrade piece/piece_unity_component_flexy ... > pear.bat list -a INSTALLED PACKAGES, CHANNEL __URI: ================================== (no packages installed) INSTALLED PACKAGES, CHANNEL PEAR.PHP.NET: ========================================= PACKAGE VERSION STATE Archive_Tar 1.3.2 stable Cache_Lite 1.7.2 stable Console_Getopt 1.2.3 stable HTML_Template_Flexy 1.2.5 stable Net_URL 1.0.15 stable PEAR 1.6.2 stable Structures_Graph 1.0.2 stable INSTALLED PACKAGES, CHANNEL PEAR.PIECE-FRAMEWORK.COM: ===================================================== PACKAGE VERSION STATE Piece_Examples_Basics 1.0.0 stable Piece_Flow 1.13.0 stable Piece_Right 1.7.0 stable Piece_Unity 1.1.0 stable Piece_Unity_Component_Authentication 0.13.0 beta Piece_Unity_Component_Flexy 1.1.0 stable Piece_Unity_Component_NullByteAttackPreventation 1.0.0 stable Stagehand_FSM 1.9.0 stable INSTALLED PACKAGES, CHANNEL PECL.PHP.NET: ========================================= (no packages installed)
では、
入力項目の検討とHTMLテンプレートの変更-新規エントリー入力画面
このフローは新規エントリー入力画面と新規エントリー入力確認画面のふたつを持っています。新規エントリー入力画面は、
<h4 class="date-header">New</h4>
<form name="New" id="New">
<input type="hidden" name="{__flowExecutionTicketKey}" value="{__flowExecutionTicket}" id="flowExecutionTicket" />
<p>
Title: <input type="text" name="title" id="title" />
</p>
<p>
Content: <textarea name="content" id="content"></textarea>
</p>
<p>
<input type="submit" name="{__eventNameKey}_DisplayNewConfirmFromDisplayNew" value="Create" />
</p>
</form>
先述のとおり、
また、
名称 | 値 |
---|---|
__ | フロー実行チケットとして認識されるリクエストパラメータの名称 |
__ | フロー実行チケット |
__ | イベント名として認識されるリクエストパラメータの名称 |
ビルトインビューエレメントは上記の他にも多数用意されています。詳細は、
さて、

この画面はこれで完了といきたいところですが、
...
<form name="New" id="New"> <input type="hidden" name="_flowExecutionTicket" value="9ad59006046cf7ef42281c74ffe9a1e9d3148a38" id="flowExecutionTicket" />
<p>
Title: <input type="text" name="title" id="title" /> </p>
<p>
Content: <textarea name="content" id="content"></textarea> </p>
<p>
<input type="submit" name="_event_DisplayNewConfirmFromDisplayNew" value="Create" />
</p>
</form>
...
見てのとおり、
イベントハンドラの設定-新規エントリー入力画面
PHPコードからform要素の属性を設定するには、
firstState: DisplayNew
lastState:
name: DisplayNewFinish
view: http://example.org/list.php
viewState:
- name: DisplayNew
view: New
activity:
class: Entry_NewAction
method: doActivityOnDisplayNew
transition:
- event: DisplayNewConfirmFromDisplayNew
nextState: DisplayNewConfirm
- name: DisplayNewConfirm
view: NewConfirm
transition:
- event: DisplayNewFinishFromDisplayNewConfirm
nextState: DisplayNewFinish
- event: DisplayNewFromDisplayNewConfirm
nextState: DisplayNew
activity要素には、
アクションクラスの作成-新規エントリー入力フロー
Piece_
ステートフルアプリケーションコンポーネントの場合、
ステートレスアプリケーションコンポーネントの場合、
今回はステートフルアプリケーションコンポーネントのため、
例えば、
[プロジェクトディレクトリ (/path/to/pieceblog)] | +- [web] | +- [webapp] | +- [actions] | +- [Entry] | +- NewAction.php - 新規エントリー入力フローに対応するEntry_NewActionクラス | +- ListAction.php - エントリー一覧フローに対応するEntry_ListActionクラス | +- EditAction.php - エントリー編集フローに対応するEntry_EditActionクラス
<?php
require_once 'Piece/Unity/Service/FlowAction.php';
require_once 'Piece/Unity/Service/FlexyElement.php';
class Entry_NewAction extends Piece_Unity_Service_FlowAction
{
function doActivityOnDisplayNew()
{
$flexyElement = &new Piece_Unity_Service_FlexyElement();
$flexyElement->addForm($this->_flow->getView(), $this->_context->getScriptName());
}
}
?>
ステートフルアプリケーションコンポーネントのアクションクラスは、
さて、
...
<form name="New" id="New" action="/new.php" method="post" enctype="application/x-www-form-urlencoded">
...
今回はきちんとaction要素が出力されています。これで、
表示項目の検討とHTMLテンプレートの変更-新規エントリー入力確認画面
引き続き、
<h4 class="date-header">NewConfirm</h4>
<p>Title: {entry.title}</p>
<p>Content: {entry.content}</p>
<form name="NewConfirm" id="NewConfirm">
<input type="hidden" name="{__flowExecutionTicketKey}" value="{__flowExecutionTicket}" />
<p>
<input type="submit" name="{__eventNameKey}_DisplayNewFromDisplayNewConfirm" value="Back" />
<input type="submit" name="{__eventNameKey}_DisplayNewFinishFromDisplayNewConfirm" value="Create" />
</p>
</form>
上記の準備が完了したらエントリポイントにアクセスし、

動作を確かめたところ、
バリデーション定義による入力値の保存
ステートフルアプリケーションコンポーネントでは、
では、

新たに追加された青色のステートProcessValidateNewは、
firstState: DisplayNew
lastState:
name: DisplayNewFinish
view: http://example.org/list.php
viewState:
- name: DisplayNew
view: New
activity:
class: Entry_NewAction
method: doActivityOnDisplayNew
transition:
- event: ProcessValidateNewFromDisplayNew
nextState: ProcessValidateNew
- name: DisplayNewConfirm
view: NewConfirm
activity:
class: Entry_NewAction
method: doActivityOnDisplayNewConfirm
transition:
- event: DisplayNewFinishFromDisplayNewConfirm
nextState: DisplayNewFinish
- event: DisplayNewFromDisplayNewConfirm
nextState: DisplayNew
actionState:
- name: ProcessValidateNew
activity:
class: Entry_NewAction
method: doActivityOnProcessValidateNew
transition:
- event: DisplayNewConfirmFromProcessValidateNew
nextState: DisplayNewConfirm
- event: DisplayNewFromProcessValidateNew
nextState: DisplayNew
強調表示部分は変更点を表しています。基本的にはステートチャート図をそのまま再現していますが、
次に、
<?php
require_once 'Piece/Unity/Service/FlowAction.php';
require_once 'Piece/Unity/Service/FlexyElement.php';
class Entry_NewAction extends Piece_Unity_Service_FlowAction
{
var $_entry;
function Entry_NewAction()
{
$this->_entry = &new stdClass();
}
function doActivityOnDisplayNew()
{
$flexyElement = &new Piece_Unity_Service_FlexyElement();
$flexyElement->addForm($this->_flow->getView(), $this->_context->getScriptName());
$flexyElement->restoreValues('New', $this->_entry);
}
function doActivityOnProcessValidateNew()
{
$validation = &$this->_context->getValidation();
if ($validation->validate('New', $this->_entry)) {
return 'DisplayNewConfirmFromProcessValidateNew';
} else {
return 'DisplayNewFromProcessValidateNew';
}
}
function doActivityOnDisplayNewConfirm()
{
$flexyElement = &new Piece_Unity_Service_FlexyElement();
$flexyElement->addForm($this->_flow->getView(), $this->_context->getScriptName());
$viewElement = &$this->_context->getViewElement();
$viewElement->setElementByRef('entry', $this->_entry);
}
}
?>
強調表示部分は変更点を表しています。$_entryプロパティは、
また、
DisplayNewConfirmステートのアクティビティに対応するイベントハンドラdoActivityOnDisplayNewConfirm()では、
doActivityOnDisplayNew()に追加された$flexyElement->restoreValues()のコールは、
バリデーション定義ファイルの基本は保存したいフォームのフィールド名を並べることです。上記の場合は、
- name: title
- name: content
バリデーション定義ファイルの基本は保存したいフォームのフィールド名を並べることです。上記の場合は、
最後に、
<?php
error_reporting(E_ALL);
require_once 'Piece/Unity.php';
require_once 'Piece/Unity/Error.php';
Piece_Unity_Error::pushCallback(create_function('$error', 'var_dump($error); return ' . PEAR_ERRORSTACK_DIE . ';'));
$base = dirname(__FILE__) . '/../webapp';
ini_set('session.cookie_path', str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])));
session_save_path("$base/sessions");
$unity = &new Piece_Unity("$base/config", "$base/cache");
$unity->setConfiguration('Dispatcher_Continuation', 'flowName', 'EntryNew');
$unity->setConfiguration('Renderer_Flexy', 'templateDir', "$base/templates/Entry");
$unity->setConfiguration('Renderer_Flexy', 'compileDir', "$base/compiled-templates/Entry");
$unity->setConfiguration('Configurator_Validation', 'configDirectory', "$base/config/validations/Entry");
$unity->setConfiguration('Configurator_Validation', 'cacheDirectory', "$base/cache/validations/Entry");
$unity->dispatch();
?>
cacheDirectoryに設定したディレクトリを実際に準備する必要があることに注意してください。ここまでの作業が完了したら、


今度は入力値がきちんと保持されていることが確認できます。新規エントリー入力確認画面のBackボタンをクリックしても、
さて、
<?php
...
function displayTextArea($value)
{
return strip_tags(nl2br($value), '<br>');
}
?>
<h4 class="date-header">NewConfirm</h4>
<p>Title: {entry.title}</p>
<p>Content: {GLOBALS.displayTextArea(entry.content):h}</p>
...
これで、

バリデーション結果によるページフローの分岐
さて、
- name: title
required:
message: title is required
- name: content
required:
message: content is required
required要素は、
<h4 class="date-header">New</h4>
<form name="New" id="New">
<input type="hidden" name="{__flowExecutionTicketKey}" value="{__flowExecutionTicket}" id="flowExecutionTicket" />
<p class="error" flexy:if="__NewResults.isError(#title#)">{__NewResults.getErrorMessage(#title#)}</p>
<p>
Title: <input type="text" name="title" id="title" />
</p>
<p class="error" flexy:if="__NewResults.isError(#content#)">{__NewResults.getErrorMessage(#content#)}</p>
<p>
Content: <textarea name="content" id="content"></textarea>
</p>
<p>
<input type="submit" name="{__eventNameKey}_ProcessValidateNewFromDisplayNew" value="Create" />
</p>
</form>
Piece_
おわりに
以上で、
また、
次回は、