2007年8月13日
●【Ethna事始め】#7蔵書管理システムのリスト表示部分
蔵書の追加部分を作ったので、次はリスト表示の部分。
これは、
・app/action/Index.php(アクション)
・app/view/Index.php(ビュー)
・template/ja/index.tpl(テンプレート)
・app/Books_Books.php(O/Rマッパー)
の部分に該当します。
まずは、O/Rマッパーの編集です。
Books_Books.phpをエディタに開くとわかりますが、これはApp_ManagerのBooks_BooksManagerクラスと、App_ObjectのBooks_Booksクラスで構成されていて、リスト表示にはBooks_BooksManagerにメソッドを記述していきます。
先にコードを示すと
public function getList()
{
$ret = $this->getObjectList('Books', null, array('release_on' => OBJECT_SORT_DESC));
if (Ethna::isError($ret)) {
return false;
}
return $ret;
}
を、Books_BooksManagerクラス内に記述します。
この$this->getObjectList()は、App_Objectの上位に該当するメソッドで、複数のApp_Objectを取得する際に利用するメソッドです。
第1引数に利用するテーブル名、第2引数に検索条件、第3引数にソート条件、第4引数にオフセット値、第5引数にリミット値を指定します。
ここで僕がよく間違えてしまっていた箇所として、第1引数のテーブル名の指定方法があります。よくテーブル名に『_』を区切り文字として利用した命名方法をすることがあります。例えばテーブル名が『hoge_foo』だった場合、ここに指定するテーブル名は『HogeFoo』のようにします。だけれども、App_Objectでは、『hoge_foo』のようにテーブル名を指定します。似たような機能であっても、微妙な際がありますので注意が必要です。
あと、第2引数や第3引数は少々クセのある指定の仕方をします。ここでは細かいことを書きませんが、基本は配列で、応用としてはAppSearchObjectを利用します。詳しくはEthna公式サイトのクラスリファレンスのAppSearchObjectの欄をご覧ください。
次にアクションです。ActionFormは利用しないので、ActionClassのサブクラス、Books_Action_Indexのみを騙取します。
これもソースを先に示すと、
function perform()
{
$book_list = "";
$books_Man = $this->backend->getManager('Books');
$books = $books_Man->getList();
list($num, $list) = $books;
foreach ($list as $book) {
$book_list[] = array(
'id' => $book->get('id'),
'isbn' => $book->get('isbn'),
'name' => $book->get('name'),
'author' => $book->get('author'),
'manufacturer' => $book->get('manufacturer'),
'release_on' => $book->get('release_on'),
);
}
$this->af->setApp('books', $book_list);
return 'index';
}
です。
4行目の
$this->backend->getManager('Books');
で、BooksテーブルのApp_Managerを取得し、5行目にて先ほど記述したgetList()メソッドを呼び出しています。
getListメソッドで取得した値は配列となっていて、それをlist()で分けています。
$numには取得した値の数(countにあたる内容)が入っていて、$listにはApp_Objectの配列が入っています。そして、$listをforeachで回し、$books_listにApp_Objectを用いて値を入れていきます。
#$books_listに値を入れる処理は、もっと簡潔に書く方法がありそうですが・・・。
18行目で、$books_listをActionFormを利用してテンプレートに値をアサインしています。
アクションの処理は以上です。
最後にテンプレートの記述です。bodyタグ内に以下のような記述をしてください。
{if $app.books != ""}
<table>
<tr>
<th>ISBN</th>
<th>書名</th>
<th>著者名</th>
<th>出版社</th>
<th>発行日</th>
<th></th>
<th></th>
</tr>
{foreach from=$app.books item=book}
<tr>
<td>{$book.isbn}</td>
<td>{$book.name}</td>
<td>{$book.author}</td>
<td>{$book.manufacturer}</td>
<td>{$book.release_on}</td>
<td><a href="{url action="edit" id=$book.id}">Edit</a></td>
<td><a href="{url action="delete" id=$book.id}">Delete</a></td>
</tr>
{/foreach}
</table>
{/if}
<a href="{url action="add"}">New</a>
ここで使っているEthnaの技術は2つ。
先ほどアクションのActionFormを利用してアサインした値を、$app.hogeのようにして取得している点。
そして、Ethnaの組み込みSmarty関数としてのurlです。urlでは、引数としてactionを必須としていて、指定したactionへのURLを自動作成します。また、それ以外のクエリもソースのように指定する事ができます。
これらを記述したら、URLにアクセスしてみてください。

みたいな感じで表示されたらOKです。
削除機能とか、編集機能は考えて作ってみてください。( ゚Д゚)マンドクセーなってきたので、蔵書管理システムはこれで終了。一応、ソースをココに置いておきます。ただし、途中で疲れたのでかなりテキトーです。あと、俺はUTF化したEthnaを使っていたりしますので、動作がなぁ・・・(^▽^;)
追記
・・・作っていて思ったけど、これだと詳細表示部分いらないんだよなぁ。
それと、途中で飽きるなよ、と(苦笑)ま、そのうちリベンジします。
Tags:Ethna事始め
2007年8月12日
●【Ethna事始め】#7蔵書管理システムの追加処理Part3
では、DBに登録する処理をperformメソッドに記述していきます。
ここでApp_Objectを利用します。App_Objectを利用する事で、SQLを書かなくてもDBへの追加・編集・削除ができたりします。
実際にperformメソッドに以下のように記述します。
function perform()
{
$books = $this->backend->getObject('books');
$books->importForm();
$books->add();
header('Location:'.$this->config->get('url'));
?>
まず、
$this->backend->getObject('books');
とすることで、booksテーブルのO/Rマッパーを利用できるようになります。
$books->importForm();
をすると、ActionFormで取得する値をクエリにそのままセットすることができます。元々は
$books->set('isbn', $this->af->get('isbn');
$books->set('name', $this->af->get('name');
...
って感じで、クエリにセットしていくんですが、それらを個別でやるのが面倒なので作ったメソッドだそうです。
んで、
$books->add();
で、実際にDBへのINSERTをおこないます。
まだリスト出力の部分を作っていませんが、これで蔵書の追加処理は完了です。ターミナルなどからmysqlを直接確認すれば、追加されていることがわかると思います。
なお、ISBNの重複に関しては、mysql側でユニークキーを設定しているので、そっち側に一任。本当なら、スクリプト側でやる方が正しいのでしょうが・・・(^▽^;)
では、次にリスト出力の部分を作っていこうと思います。
Tags:Ethna事始め
2007年8月11日
●【Ethna事始め】#7蔵書管理システムの追加処理Part2
次に、validateの設定をします。
doneアクションをエディタで開きます。
先ほどはActionFormクラスを書き換えましたが、次はActionClassクラス(Books_Action_AddDoneクラス)を書き換えます。
Books_Action_AddDoneクラスには、prepareとperformの2つのメソッド(これら2つの他にauthenticateってクラスも継承されていますが、ここでは触りません)が入っています。prepareメソッドでvalidateとかをして、performメソッドで実際の処理をおこなうとでも思っていたらいいです。
今はvalidateを行うので、prepareメソッドの編集です。
function prepare()
{
if ($this->af->validate() > 0) {
return 'add';
}
return null;
}
みたいな感じに書き換えてください。
$this->af->validate()
をすると、先ほど記述したActionFormの定義($formの値)にのっとってvalidateを行います。もし定義に合致しないデータであった場合、値が1以上になるためにif内に入ります。if内では(定義に合致)しない場合は、perfomの処理をおこなわず、returnで指定したビュー(この場合はaddビュー)に処理を引き渡します。
エラーの表示はテンプレートに
{if count($errors)}
<ul>
{foreach from=$errors item=error}
<li>{$error}</li>
{/foreach}
<ul>
{/if}
と記述すると、
って感じで表示させることができます。
・・・ものすごくわかりにくい説明だorz
次は、DBに登録する処理をperformに記述していきます。
Tags:Ethna事始め
●【Ethna事始め】#7蔵書管理システムの追加処理Part1
では、これからは実際にコーディングに入っていきます。
まずは、蔵書の追加処理から行います。Index(リスト表示)から入らないのは、・・・いろいろと理由があったりします。
#リスト表示させるには、App_Manager使わなきゃいけなくて、それはそこそこにややこしいので。だったら、わかりやすい追加処理から書こうかな、と。
蔵書の追加処理に使うファイルは
・app/action/Add.php(addアクション)
・app/action/Add/Done.php(doneアクション)
・app/view/Add.php(addビュー)
・template/ja/add.tpl(addテンプレート)
の4つです。
大雑把な説明をすると、addアクションからdoneアクションにデータが受け渡されます。その受け渡されるデータの定義はdoneアクションがして、フォームはビューとテンプレートがdoneアクションに定義された形で出力します。・・・かえってややこしくなってしまいましたorz
実際に書いていった方が早いので、ちゃっちゃとやっていきます。
まずは、doneアクションをエディタで開きます(addアクションを変更することはありません)。
そのファイルをザッと眺めてください。2つのクラスから成り立ってるのがわかりますでしょうか。
先に書かれているが、Books_Form_AddDoneクラスです。こいつは、ActionFormと呼ばれるクラスのサブクラスで、GET/POSTなどのクエリを管理するクラスです。
後ろの方に書かれているのが、Books_Action_AddDoneクラスです。こいつは、ActionClassと呼ばれるクラスのサブクラスで、実際の処理を記述していくクラスです。
今は、Books_Form_AddDoneクラスを記述していきます。
このBooks_Form_AddDoneクラスの中に
var $form = array();
ってのがあります。ここに受け取るクエリの条件などを記述していきます。
今回、追加処理で受け取るクエリとしまして
・isbn
・name
・author
・manufacturer
・release_on
です。
んで、それぞれの条件を踏まえながら、書いていきますと
var $form = array(
'isbn' => array(
'name' => 'ISBN',
'type' => VAR_TYPE_STRING,
'form_type' => FORM_TYPE_TEXT,
'required' => true,
),
'name' => array(
'name' => '書名',
'type' => VAR_TYPE_STRING,
'form_type' => FORM_TYPE_TEXT,
'required' => true,
),
'author' => array(
'name' => '筆者名',
'type' => VAR_TYPE_STRING,
'form_type' => FORM_TYPE_TEXT,
'required' => false,
),
'manufacturer' => array(
'name' => '出版社',
'type' => VAR_TYPE_STRING,
'form_type' => FORM_TYPE_TEXT,
'required' => false,
),
'release_on' => array(
'name' => '発行日',
'type' => VAR_TYPE_DATETIME,
'form_type' => FORM_TYPE_TEXT,
'required' => false,
),
),
って感じです。
次に、ビューを少し書き換えます。
Books_View_Addクラス内に、
var $helper_action_form => array( 'add_done' => null);
ってのを付け加えます。これは、doneアクションで定義したフォーム値をaddビューで使いますよ、って宣言だと思ってもらえば、あながち間違っていないはず。・・・ただ、書かなくても動くのは動くんだよなぁ(^▽^;)
ビューが書けたなら、テンプレートの編集に移ります。
テンプレートのbodyタグ内に
{form ethna_action="add_done"}
{form_name name="isbn"}{form_input name="isbn"}
{form_name name=”name”}{form_input name=”name”}
{form_name name=”author”}{form_input name=”author”}
{form_name name=”manufacturer”}{form_input name=”manufacturer”}
{form_name name=”release_on”}{form_input name=”release_on”}
{form_submit value=”追加する”}
{/form}
って感じで書いてやります。
そこまでできたら、シンボリックリンクをはったURLにaction_add=trueっていうGETクエリをつけたURIにアクセスしてください。(僕の場合だと、http://localhost/~siukaido/books/?action_add=true)
こんなフォームの見れてるでしょうか?

フォームが見れていたら成功。これがActionFormのフォーム出力機能です。
・・・ちょっと長くなってきたので、ここで一回区切ります。
Tags:Ethna事始め
●【Ethna事始め】#6蔵書管理システムのアクション等の追加
では、今回のシステムに必要なアクションやビューを追加していきます。
まずは簡単な設計を考えます。ミニマムな物を作って、それを拡張していくようにしましょう。
必要な機能としては、
・蔵書のリスト表示
・蔵書の詳細表示
・蔵書の追加フォームと追加処理
・蔵書の編集フォームと編集処理
・蔵書の削除処理
といったところでしょうか。
リスト表示はIndexを使うとして、詳細表示をitem、追加フォームをadd、追加処理をadd/done、編集フォームをedit、編集処理をedit/done、削除処理をdeleteとします。
このうち、ビューが必要なのは、
・蔵書のリスト表示
・蔵書の詳細表示
・蔵書の追加フォーム
・蔵書の編集フォーム
というところでしょう。
では、ethnaコマンドでそれらを追加していきます。
アクションを追加するには、
$ ethna add-action [action name]
ビューを追加するには、
$ ethna add-view [view name]
テンプレートを追加するには、
$ ethna add-template [template name]
ビューとテンプレートを同時に追加するには、
$ ethna add-view -t [view&template name]
としてやります。
#アクション・ビュー・テンプレートを同時に追加するコマンドはないのでしょうかね?あったら便利だとは思うのですが、見つけきれませんでした(^▽^;)
アクション・ビュー・テンプレート名の区切り文字として『_』がデフォルト設定されています。なので、『_』を使うアクション名とかは避けた方が賢明です。あと、頭文字が数字でも上手く行きませんので注意してください。
では、実際に追加していきます。なお、レスポンスは書きませんのでご了承あれ。
$ ethna add-action item $ ethna add-action add $ ethna add-action add_done $ ethna add-action edit $ ethna add-action edit_done $ ethna add-action delete $ ethna add-view -t item $ ethna add-view -t add $ ethna add-view -t edit
次にO/Rマッパーを追加しましょう。Ethnaでは、これをApp_ObjectやApp_Managerって呼ばれてます。これを使うと、簡単な処理であればSQLを直接記述することなくDB操作を行う事が可能となります。
#あと、キャッシュ処理もしてくれてるので、少しはDBアクセスが減ります。・・・たぶん(^▽^;)
O/Rマッパーを追加するには、
$ ethna add-app-object [table name]
ってしてやります。これで、App_ObjectとApp_Managerが生成されます。
今回であれば、使うテーブルはbooksなので、
$ ethna add-app-object books
としてやります。
これで必要なファイルの生成は完了です。次からは、これらのファイルに、必要な処理を記述していきます。
Tags:Ethna事始め
●【Ethna事始め】#5蔵書管理システムの初期設定
プロジェクトを作成したので、まずはBooksプロジェクトの初期設定をします。これをしとかないと、O/Rマッパーを使えなかったり、いろいろと面倒なことになります。
プロジェクトのルートフォルダ内のetcフォルダに、books-ini.phpってファイルがあるので、こいつをエディタで開いてやります。
まず、9行目あたりに
'url' => '',
ってのがあるので、そこにエントリポイントのあるURLを書いてやります。
- 'url' => '', + 'url' => 'http://localhost/~siukaido/books/',
次に、29行目あたりに、dsnの設定を追加してやります。これはPEAR::DBと同じような書き方ですし、24行目にサンプルがあるんで、それを真似て書いてやります。
+ 'dsn' => 'mysql://root:********@localhost/ethna_recipe',
#僕がよくやる間違いとして、『,』じゃなく、『:』って書いちゃうことがあります。あくまでも配列の値なんですよね(^▽^;)
とりあえずは、これで初期設定はこれだけ。あと、共有で利用するような設定項目(後々使う事になりますが、AmazonWebServiceのIDとか)を追加してやることもできます。ここで設定しておけば、プログラム中に
$this->config->get('hoge');
って感じで呼び出せるので、結構便利だったりします。
#本当なら、defineとかで定数化すべきなのかもしれませんが・・・。
次はアクションやらビューやらを追加していく作業です。
Tags:Ethna事始め
2007年8月9日
●【Ethna事始め】#4蔵書管理システムのプロジェクト作成etc
では、ethnaコマンドを使ってプロジェクトを作成していきます。
今は、作業用フォルダにいる状態です。そこで
$ pwd /Users/siukaido/ethna $ ethna add-project books
と入力してやると、『ディレクトリを作ってもいいか?』と聞いてくるので、yを入力してやります。すると、必要なフォルダ構成が自動生成されます。まるでRoRのように!!
#倒置法で書くと英語のテキストを和訳してるみたいだなwww
んで、lsでチェックしてやると実際にbooksフォルダが作成されてるので、そこに移動。以降、ここをプロジェクトのルートフォルダとして作業していくことになります。
$ ls -F books/ $ cd books
このルートフォルダには以下のようなフォルダが作成されてると思います。
$ ls -F app/ lib/ schema/ tmp/ bin/ locale/ skel/ www/ etc/ log/ template/
このうちのwwwフォルダがエントリポイントが含まれた公開フォルダとなるので、公開フォルダ(嗚呼ややこしい…)にシンボリックリンクでも貼付けてやります。
$ pwd /Users/siukaido/ethna/books $ ln -s ~/ethna/books/www/ ~/Sites/books
これで、ブラウザからhttp://localhost/~siukaido/books/にアクセスすることで、booksプロジェクトにアクセスできるはずです。
アクセスできたなら

な感じで表示されてると思います。
これで、第一歩は終了。次からはエディタを用いてガシガシとコーディングです。
※ここまででつまずいたなら、GREE Lab.にもっと詳細に説明がされているので、そちらも参照してください。
Tags:Ethna事始め
●【Ethna事始め】#3蔵書管理システムの下準備
まずは下準備として、データ項目あたりを云々とします。
書籍データとして、次の項目を扱えるようにします。
・ISBN
・書名
・著者名
・出版社
・発行日
んで、これらを英語表記して
・isbn
・name
・author
・manufacturer
・release_on
としておきます。
EthnaにはRoRみたいに、自動でデータベース設定を行う機能がないので、まずはそこからやりましょう。
#そのうち、Ethnaにも自動でデータベースを設定する機能を付けて欲しいなぁ・・・。
データベース名はethna_recipeで、テーブル名はbooks、項目は上に記した通りです。ユーザは面倒なのでrootでやります(爆)
$ mysql -u root -p
Enter Password:
Welcom(略
mysql> CREATE database ethna_recipe;
Query OK, 1 row affected (0.08 sec)
mysql> USE ethna_recipe;
Database changed
mysql> CREATE TABLE books (
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
-> isbn VARCHAR( 255 ) NOT NULL ,
-> name VARCHAR( 255 ) NOT NULL ,
-> author VARCHAR( 255 ) NOT NULL ,
-> manufacturer VARCHAR( 255 ) NOT NULL ,
-> release_on DATE NOT NULL ,
-> UNIQUE (isbn)
-> ) ENGINE = MYISAM ;
これでデータベースの設定は終了。ethna事始めとか言っときながら、いっさいethnaに触れてないしwww
次からは実際にethnaコマンドを使ったりしていきます。・・・たぶん。
Tags:Ethna事始め
●【Ethna事始め】#2Ethnaの下準備
ようやくEthnaの下準備です。とは言っても、インストールされてることを前提に書いているので、一般的な下準備じゃないんですけどねwww
まずは作業用フォルダを作ります。
$ pwd /Users/siukaido $ mkdir ethna $ cd ethna $ pwd /Users/siukaido/ethna
って感じで、作業用フォルダを作成して、そこに移動してください。僕はホームフォルダ直下に『ethna』ってフォルダを作っていて、そこにethnaで作成するシステムを突っ込んでいます。
#同様にRoRの作業用フォルダは、ホーム直下のrailsって名前だったりします。安直と言われようが、わかりやすいんだもんwww
・・・うん、下準備って言ってもこれだけwww
次からは、実際のシステムを作る行程です。最初のサンプルは、ライド・オン・Railsにのっとって『蔵書管理システム』ってヤツです。
Tags:Ethna事始め
●【Ethna事始め】#1 Httpd.conf for Mac
Ethnaの下準備の前に、Apacheの下準備をしておきます。
MacOSXはデフォでApacheがインストールされているので、『システム環境設定』→『共有』を選択してやり『パーソナルWeb共有』にチェックを入れてやればWebサーバが動いてくれます。
#ここらへんは知っているという前提なので、PHPやMySQLの動かし方のような細かいところは書きません。
こんな簡単にWebサーバを起動することができるMacOSXなのですが、デフォで入ってるApacheでは公開フォルダ(~/Sites/)にシンボリックリンクを貼ったとしても、403になってしまいアクセスできません。なので、httpd.confを少しだけいじる必要があります。
#/Liverary/WebServer/Documents/にシンボリックリンクを貼るのであれば、問題はないんですけどね。
ちなみに、Macのhttpd.confは少し奇妙な位置にありまして、/private/etc/httpd内にあったりするので注意が必要です。こういう時、Linuxで育った人間には違和感があったりなかったりwww
$ cd /private/etc/httpd $ ls -F httpd.conf users/ $ cd users $ ls siukaido.conf
このsiukaido.confが、ユーザ用公開フォルダに対するコンフィグなので、こいつを少し書き換えます。
- Options Indexes MultiViews + Options Indexes FollowSymLinks MultiViews
って感じ。
#このとき、スーパーユーザで処理する必要ありますからね。
細かいところはApacheの仕様書なりを読んでください。僕もよくわかってません(爆)
デフォだと上手く動かなくて、僕自身、かなりハマってしまった箇所なので紹介しときましたwww







