投稿者: Rob Allen、 akrabat.com
オリジナル: akrabat.com/zend-framework-tutorial
翻訳:アレクサンダー・ムサエフ、 musayev.com
データベース
アプリケーションの制御部分と視覚化コードが分離されたので、今度はモデルに取り組みます。 モデルは、その基本機能を実装するアプリケーションの基本部分であることに注意してください。 したがって、この場合、モデルはデータベースを使用して作業を実行します。 データベーステーブルのレコードを検索、挿入、更新、削除するために設計されたZend Frameworkクラス
Zend_Db_Table
を使用します。
カスタマイズ
Zend_Db_Table
を使用するには、どのデータベース、どのユーザー名、どのパスワードでアクセスするかを彼に伝える必要があります。 この情報をコードに打ち込まないことが望ましいことを考慮して、構成ファイルを使用して保存します。
Zend Frameworkは、この目的のために
Zend_Config
クラスを提供し
Zend_Config
。これにより、INIおよびXML形式の構成ファイルへの柔軟なオブジェクト指向アクセスが提供されます。 INIファイルで停止しましょう:
zf-tutorial/application/config.ini:
[general] db.adapter = PDO_MYSQL db.config.host = localhost db.config.username = rob db.config.password = 123456 db.config.dbname = zftest
(もちろん、例に示されているものではなく、独自のデータベースアクセスパラメータを使用する必要があります。)
Zend_Config
は非常に簡単です:
$config = new Zend_Config_Ini('config.ini', 'section');
この場合、
Zend_Config_Ini
はINIファイルから1つのセクションを読み込みます(必要に応じて他のセクションを読み込むこともできます)。 セクションに名前を付ける機能が実装されているため、不必要なデータが不必要にロードされることはありません。
Zend_Config_Ini
は、パラメーター名にピリオドを階層的な区切り記号として使用するため、関連するパラメーターをグループ化できます。
config.ini
ファイルでは、パラメーター
host
、
username
、
password
、および
dbname
が
$config->db->config
オブジェクトにグループ化されます。
ブートストラップファイル(
index.php
)から構成ファイルをロードします。
zf-tutorial/index.php:
... Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Config_Ini'); Zend_Loader::loadClass('Zend_Registry'); // load configuration $config = new Zend_Config_Ini('./application/config.ini', 'general'); $registry = Zend_Registry::getInstance(); $registry->set('config', $config); // setup controller ...
操作に必要なクラス(
Zend_Config_Ini
および
Zend_Registry
)を読み込んだ後、
general
呼ばれる設定ファイル
application/config.ini
セクションが
$config
オブジェクトに読み込まれます。 次に、レジストリに
$config
オブジェクトが含まれます。これにより、アプリケーション全体からアクセスできます。
注:この例では、
$config
をレジストリに保存する必要はありません。 これは、「実際の」アプリケーションの動作の例として行われます。その設定ファイルには、おそらくデータベースアクセスパラメータ以外のものを保存する必要があります。 レジストリを使用する場合、レジストリ内のデータはグローバルレベルでアクセス可能であり、不注意に使用すると、アプリケーション内で競合が発生する可能性があることに注意してください。
Zend_Db_Tableを使用する
Zend_Db_Table
クラスを使用するには、ロードされたばかりのデータベースアクセスパラメータを渡す必要があります。 これを行うには、
Zend_Db
オブジェクトを作成し、
Zend_Db_Table::setDefaultAdapter()
関数で登録します。 以下は、ブートストラップファイル内の対応するコードスニペットです。
zf-tutorial/index.php:
... Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Config_Ini'); Zend_Loader::loadClass('Zend_Registry'); <b>Zend_Loader::loadClass('Zend_Db'); Zend_Loader::loadClass('Zend_Db_Table');</b> // load configuration $config = new Zend_Config_Ini('./application/config.ini', 'general'); $registry = Zend_Registry::getInstance(); $registry->set('config', $config); <b>// setup database $db = Zend_Db::factory($config->db->adapter, $config->db->config->toArray()); Zend_Db_Table::setDefaultAdapter($db);</b> // setup controller ...
テーブル作成
MySQLデータベースを使用するため、テーブルを作成するSQLクエリは次のようになります。
CREATE TABLE album ( id int(11) NOT NULL auto_increment, artist varchar(100) NOT NULL, title varchar(100) NOT NULL, PRIMARY KEY (id) );
このクエリは、phpMyAdminや標準コンソールユーティリティなど、MySQLクライアントを介して実行できます。
テストレコードの追加
テーブルにいくつかのテストエントリを追加して、後で表示されるメインページの機能を確認します。
INSERT INTO album (artist, title) VALUES ('James Morrison', 'Undiscovered'), ('Snow Patrol', 'Eyes Open');
モデル
Zend_Db_Table
は抽象クラスであるため、それに基づいて、タスクに特化した継承クラスを作成する必要があります。 新しいクラスの名前は重要ではありませんが、そのようなクラスは、対応するデータベーステーブルと同じ方法で呼び出す必要があります(これにより、コードの自己文書化のレベルが向上します)。 したがって、
album
テーブルのクラス名は
Album
ます。
管理するテーブルの名前を
Zend_Db_Table
に渡すには、この値をクラス
$_name
保護されたプロパティに割り当てる必要があります。
Zend_Db_Table
クラスは、デフォルトで
id
という名前のテーブルのキー自動インクリメントフィールドを常に使用することに注意してください。 必要に応じて、このフィールドの名前の値も変更できます。
Album
クラスはモデルディレクトリに保存されます。
zf-tutorial/application/models/Album.php:
<?php class Album extends Zend_Db_Table { protected $_name = 'album'; }
複雑なことはありませんか? この場合のニーズは非常に小さいことを考えると、
Zend_Db_Table
の基本機能はそれらを完全に満たすのに十分です。 タスク内でデータベースと対話するより複雑な操作を実装する必要がある場合、モデルクラスは、対応するコードを配置する場所になります。
アルバムリスト
データベースの構成が完了したので、アプリケーションのメインタスクの実行を開始し、いくつかのエントリを表示できます。 これは、
IndexController
クラスに実装する必要があります。
IndexController
内の各アクション関数は、
Album
クラスを介して
Album
テーブルとやり取りします。 したがって、コントローラーを
init()
関数内で初期化するときにロードすることは理にかなっています。
zf-tutorial/application/controllers/IndexController.php:
... function init() { $this->view->baseUrl = $this->_request->getBaseUrl(); Zend_Loader::loadClass('Album'); } ...
注:このコードスニペットは、
Zend_Loader::loadClass()
メソッドを使用して非標準クラスをロードする例を示しています。 これは、モデルディレクトリ(ロードされたクラス
Albums
が格納されている)が
include_path
に追加されたために機能し
include_path
。
indexAction()
を使用して、データベースからアルバムのリストを作成します。
zf-tutorial/application/controllers/IndexController.php:
... function indexAction() { $this->view->title = "My Albums"; $album = new Album(); $this->view->albums = $album->fetchAll(); } ...
fetchAll()
関数は
Zend_Db_Table_Rowset
オブジェクトを返します。これにより、次の形式のテンプレートファイル内のすべてのエントリのリストを作成できます。
zf-tutorial/application/views/scripts/index/index.phtml:
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <p><a href="<?php echo $this->baseUrl; ?>/index/add">Add new album</a></p> <table> <tr> <th>Title</th> <th>Artist</th> <th> </th> </tr> <?php foreach($this->albums as $album) : ?> <tr> <td><?php echo $this->escape($album->title);?></td> <td><?php echo $this->escape($album->artist);?></td> <td> <a href="<?php echo $this->baseUrl; ?>/index/edit/id/<?php echo $album->id;?>">Edit</a> <a href="<?php echo $this->baseUrl; ?>/index/delete/id/<?php echo $album->id;?>">Delete</a> </td> </tr> <?php endforeach; ?> </table> <?php echo $this->render('footer.phtml'); ?>
で
localhost/zf-tutorial
localhost/zf-tutorial
2つのアルバムのリストが表示されます。
新しいアルバムを追加する
それでは、データベースに新しいディスクを追加する機能に移りましょう。 このタスクは2つの部分で構成されます。
- ユーザーがデータを入力するためのフォームの表示。
- フォームから受け入れたデータをデータベースに追加します。
addAction()
function-actionに上記の操作を実装します。
zf-tutorial/application/controllers/IndexController.php:
... function addAction() { $this->view->title = "Add New Album"; if ($this->_request->isPost()) { Zend_Loader::loadClass('Zend_Filter_StripTags'); $filter = new Zend_Filter_StripTags(); $artist = $filter->filter($this->_request->getPost('artist')); $artist = trim($artist); $title = trim($filter->filter($this->_request->getPost('title'))); if ($artist != '' && $title != '') { $data = array( 'artist' => $artist, 'title' => $title, ); $album = new Album(); $album->insert($data); $this->_ redirect('/'); return; } } // set up an "empty" album $this->view->album = new stdClass(); $this->view->album->id = null; $this->view->album->artist = ''; $this->view->album->title = ''; // additional view fields required by form $this->view->action = 'add'; $this->view->buttonText = 'Add';</b> } ...
関数の開始時に、フォームのデータの転送があったかどうかがどのように判断されたかに注目してください。 フォームからデータが送信された場合、
artist
と
title
値を抽出し、
Zend_Filter_StripTags
タグのHTMLフィルターで処理します。 さらに、行に空でない値がある場合、
Album()
クラスを使用してデータベーステーブルに新しいレコードを追加します。 アルバムを追加した後、ユーザーはコントローラーメソッド
_redirect()
を使用してメインページにリダイレクトされます。
最後に行うことは、ビューテンプレート用のHTMLフォームを準備することです。 先を見ると、レコード編集フォームはそれらを追加するためのフォームと同じように見えることに注意できます。 したがって、
add.phtml
および
edit.phtml
使用される共通のテンプレートファイル(
_form.html
)を使用します。
新しいアルバムページテンプレートを追加:
zf-tutorial/application/views/scripts/index/add.phtml:
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('index/_form.phtml'); ?> <?php echo $this->render('footer.phtml'); ?>
zf-tutorial/application/views/scripts/index/_form.phtml:
<form action="<?php echo $this->baseUrl ?>/index/<?php echo $this->action; ?>" method="post"> <div> <label for="artist">Artist</label> <input type="text" name="artist" value="<?php echo $this->escape(trim($this->album->artist));?>"/> </div> <div> <label for="title">Title</label> <input type="text" name="title" value="<?php echo $this->escape($this->album->title);?>"/> </div> <div id="formbutton"> <input type="hidden" name="id" value="<?php echo $this->album->id; ?>" /> <input type="submit" name="add" value="<?php echo $this->escape($this->buttonText); ?>" /> </div> </form>
結果は、かなり単純なコードです。 レコードの編集時にも
_form.phtml
を使用する場合、必要なアクションの名前をハード設定する代わりに、変数
$this->action
を使用します。 同様に、変数を介して、フォームからデータを送信するためのボタンの碑文が設定されます。
アルバム編集
アルバムの編集は、多くの点で新しいレコードの追加と同じであるため、コードは似ています。
zf-tutorial/application/controllers/IndexController.php:
... function editAction() { $this->view->title = "Edit Album"; $album = new Album(); if ($this->_request->isPost()) { Zend_Loader::loadClass('Zend_Filter_StripTags'); $filter = new Zend_Filter_StripTags(); $id = (int)$this->_request->getPost('id'); $artist = $filter->filter($this->_request->getPost('artist')); $artist = trim($artist); $title = trim($filter->filter($this->_request->getPost('title'))); if ($id !== false) { if ($artist != '' && $title != '') { $data = array( 'artist' => $artist, 'title' => $title, ); $where = 'id = ' . $id; $album->update($data, $where); $this->_redirect('/'); return; } else { $this->view->album = $album->fetchRow('id='.$id); } } } else { // album id should be $params['id'] $id = (int)$this->_request->getParam('id', 0); if ($id > 0) { $this->view->album = $album->fetchRow('id='.$id); } } // additional view fields required by form $this->view->action = 'edit'; $this->view->buttonText = 'Update'; } ...
データがフォームからスクリプトに転送されなかった場合、
getParam()
メソッドを使用して
Request
オブジェクトの
params
プロパティから
id
パラメーターを取得できることに注意してください。
テンプレートコードを以下に示します。
zf-tutorial/application/views/scripts/index/edit.phtml:
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <?php echo $this->render('index/_form.phtml'); ?> <?php echo $this->render('footer.phtml'); ?>
リファクタリング
もちろん、
addAction()
と
editAction()
非常によく似ており、レコードを追加および編集するためのテンプレートが一般的に同じであることに注意する必要はありません。 コードのリファクタリングの必要性を想定するのは理にかなっています。 追加の実践的な演習として、この問題を自分で解決します。
アルバムを削除
アプリケーションの開発を完了するには、レコードを削除する機能を追加する必要があります。 リスト内の各アイテムの反対側のアルバムを削除するためのリンクを提供しました。 頭に浮かぶ最初の解決策は、これらのリンクのいずれかをクリックするとすぐにエントリを削除することです。 しかし、これは間違ったアプローチです。 HTTP仕様に従って、GETメソッドを使用して元に戻せないアクションを実行しないでください。 このような場合、POSTを使用することをお勧めします。 この例は、Google Acceleratorの成果です。
レコードを削除する前に確認を要求し、受信後にのみ削除する必要があります。 これらのアクションを実装するコードは、アプリケーションに既に存在するアクション関数に多少似ています:
zf-tutorial/application/controllers/IndexController.php:
... function deleteAction() { $this->view->title = "Delete Album"; $album = new Album(); if ($this->_request->isPost()) { Zend_Loader::loadClass('Zend_Filter_Alpha'); $filter = new Zend_Filter_Alpha(); $id = (int)$this->_request->getPost('id'); $del = $filter->filter($this->_request->getPost('del')); if ($del == 'Yes' && $id > 0) { $where = 'id = ' . $id; $rows_affected = $album->delete($where); } } else { $id = (int)$this->_request->getParam('id'); if ($id > 0) { // only render if we have an id and can find the album. $this->view->album = $album->fetchRow('id='.$id); if ($this->view->album->id > 0) { // render template automatically return; } } } // redirect back to the album list unless we have rendered the view $this->_redirect('/'); } ...
同じ方法を使用して、スクリプトにアクセスし、必要な操作を選択する方法を決定しました(レコードの削除または確認フォームの発行)。 追加および編集の場合と同じ方法で、
delete()
メソッドによって
Zend_Db_Table
を介して削除が実行されます。 関数の最後に、ユーザーはアルバムリストページにリダイレクトされます。 したがって、パラメータ
_redirect()
チェックの1つが失敗した場合、関数内で
_redirect()
を繰り返し呼び出すことなく、元のページに戻ります。
テンプレートはシンプルなフォームです:
zf-tutorial/application/views/scripts/index/delete.phtml:
<?php echo $this->render('header.phtml'); ?> <h1><?php echo $this->escape($this->title); ?></h1> <b><?php if ($this->album) :?> <form action="<?php echo $this->baseUrl ?>/index/delete" method="post"> <p>Are you sure that you want to delete '<?php echo $this->escape($this->album->title); ?>' by '<?php echo $this->escape($this->album->artist); ?>'? </p> <div> <input type="hidden" name="id" value="<?php echo $this->album->id; ?>" /> <input type="submit" name="del" value="Yes" /> <input type="submit" name="del" value="No" /> </div> </form> <?php else: ?> <p>Cannot find album.</p> <?php endif;?></b> <?php echo $this->render('footer.phtml'); ?>
トラブルシューティング
index
/
index
以外のアクションにアクセスするときに問題が発生する場合、最も可能性が高いのは、ルータークラスがWebサイトがどのディレクトリにあるかを正しく判断できないことです。 この状況は、サイトのURLが、ネットワークからアクセスするために開いているルートディレクトリを基準としたディレクトリへのパスと一致しない場合に発生する可能性があります。
上記のコードがケースに一致しない場合は、
$baseURL
変数をサーバーの正しい値に設定する必要があります。
zf-tutorial/index.php:
... // setup controller $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); $frontController->setBaseUrl('/mysubdir/zf-tutorial'); $frontController->setControllerDirectory('./application/controllers'); ...
値
/mysubdir/zf-tutorial/
は、
index.php
ファイルへの実際のパスに置き換える必要があります。 たとえば、
index.php
へのURLが次のようになっている場合
localhost/~ralle/zf-tutorial/index.php
localhost/~ralle/zf-tutorial/index.php
の場合、
$baseUrl
変数の正しい値は
/~ralle/zf-tutorial/
です。
おわりに
これについては、シンプルだが完全に機能するMVCアプリケーションの構築が完了したと見なすことができます。 このレビューがあなたにとって有益で有益であることを願っています。 元のテキストに関するコメントは、rob @ akrabat.comで記事の著者に送信できます。 ロシア語の翻訳に関するコメントは、musayev @ yandex.ruに送信してください。
この記事では、Zend Frameworkの表面的な概要のみを提供します。ここには、ここに挙げたクラス以外にも非常に多くのクラスがあります。 それらの詳細なレビューについては、適切なリソースを参照する必要があります。
- 公式ドキュメント→ framework.zend.com/manual
- 追加コンテンツを含むWiki→ framework.zend.com/ wiki
- 開発者向けWiki→ framework.zend.com/ developer
- 英語のオリジナル記事、および著者のウェブサイトのコード例→ akrabat.com/zend-framework-tutorial
この翻訳では、無料の百科事典Wikipedia.orgの資料を使用しました。