第3回 ブログツールで学ぶ実践的Zend Frameworkの使い方「Zend Framework」で加速するPHP開発(3/5 ページ)

» 2007年03月08日 07時30分 公開
[杉田直哉,ITmedia]

アクションコントローラ

 Alex@Net Blogのアクションコントローラは、3つ用意されています。1つ目は、間違ったURIにアクセスされた場合など、イレギュラーな処理に対処するためのIndex Controller。2つ目は、ブログのトップページなどを表示するBlog Controller。3つ目は、ブログ管理者だけがアクセスできるAdmin Controllerです。それぞれ詳しく見ていきましょう。

  • Index Controller

 前述したように、Alex@Net Blogへのアクセスは「http://ホスト名/コントローラ名/アクション名」というURIで行いますが、URIを「http://ホスト名/」などとして、アクションを指定せずにアクセスされる場合があります。また、不正なコントローラがURIへ指定される場合もあります。このような場合に、代わりにディスパッチされるコントローラがIndex Controllerです。

 「http://ホスト名/」を指定された場合は、「http://ホスト名/Blog/Index」へリダイレクトされ、存在しないコントローラが指定された場合には、HTTP/1.1 404 Not foundのページが表示されます。ただし、「http://ホスト名/Index/route」と入力すると、Fatal ErrorのExceptionが表示されてしまいます。

 存在しないアクションが指定された場合に、もっと気の利いたページを表示するには、例えばリスト4のように、Zend_Controller_Actionの__callメソッドをオーバーライドして、独自の実装を行う必要があります。


require_once 'Zend/Controller/Action.php';
require_once 'Zend/View.php';
class IndexController extends Zend_Controller_Action
{
  public function indexAction()
  {
    $this->_redirect('/Blog/Index/');
  }
  public function noRouteAction()
  {
    header('HTTP/1.1 404 Not found');
    $view = new Zend_View();
    $view->setScriptPath('./_/application/views');
    $view->pageTitle = '404 error';
    echo $view->render('Pages/ServicePages/404.php');
  }

  public function __call($methodName, $args) {     $this->_redirect('/Blog/Index/');   } }
リスト4 存在しないアクションが指定された場合の処理をカスタマイズ
  • Blog Controller

 Blog Controllerは、Blogを表示するIndexアクションと、Atomフィード*を配信するAtomアクションで構成されます。

1:Indexアクション

 Indexアクションのコードはリスト5のようになっています。ここではまず、「$this->_getAllParams()」によって、URIで指定されているキーとその値を取得しています。if文の最初の条件節であるpreg_matchは、「http://ホスト名/Blog/Index/2006-06-06/lorem-ipsum」のように、「Indexアクションのキーが日付であるかどうか」を判別しています。


foreach ($this->_getAllParams() as $key => $value) {
  if (preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $key)) {
    $date = strtotime($key);
    $name = $value;
  } else if ('Page' == $key) {
    $page = (int)$value;
  } else {
    $this->_redirect('/Blog/Index/');
  }
}

リスト5 Indexアクションのコード

 このブログでは、Permalink*のURIを投稿日と簡略タイトルにすることで、各エントリを一意に判別するようにしているからです(同一日に同一タイトルの投稿がある場合は一意になりませんが、通常のブログ使用の範囲で問題は起こらないということでしょう)。

 また、キーにPageが指定された場合も値が取得され、$page変数に代入されます。そのほか、想定外のキーが指定されていた場合は、Indexアクションに再びリダイレクトして受け付けないようになっています。

 リスト6の処理では、Model層のオブジェクトを呼び出してデータベースへ問い合わせています。$dateがnullの場合はエントリの一覧表示、nullでない場合はPermalinkの問い合わせです。


if (null == $date) {
  $model = BlogModel::GetPosts(Config::getInstance()->DefaultBlog, $tags, $page);
  $model['page'] = $page;
  $p =& $model['posts'];
  $model['showPrevLink'] = (0 < count($p) && !$p[count($p) - 1]['is_last']);
  $model['showNextLink'] = $page > 1;
} else {
  $model = BlogModel::GetPost(Config::getInstance()->DefaultBlog, array($date, $name));
  $model['page'] = null;
}

リスト6 IndexアクションでModel層のオブジェクトを呼び出して、データベースへ問い合わせ

 リスト7のコードでは、Zend_Viewオブジェクトを生成してビュースクリプトの存在するディレクトリをsetScriptPathで指定、ヘルパーの存在するディレクトリをaddHelperPathで指定します。データベースから取得し、各変数値を整えた$model配列がまとめてassignされ、それとは別にpageTitleへ個別の変数が代入されています。最後は、renderによって指定されたビュースクリプトがレンダリングされます。


$view = new Zend_View();
$view->setScriptPath('./_/application/views');
$view->addHelperPath('./_/application/views/Helpers');
$view->assign($model);
if (null == $date) {
$view->pageTitle = $model['title'] . ' - Blog';
} else {
$view->pageTitle = $model['title'] . ' - Blog - ' . $model['posts'][0]['title'];
}
echo $view->render('Pages/BlogView.php');

リスト7 Zend_Viewオブジェクトを生成からレンダリングまで

2:Atomアクション

 Atomを生成するためのコードには、独自のライブラリが使用されています。現時点のZend_Feedでは、単純なエントリを作成する機能はあっても、複数のエントリを持つフィードを作成する機能を備えていないからです。

 Zend_Feed_Atom が継承しているZend_Feed_Abstractのコンストラクタでは、URIまたは文字列でフィードを読み込むことを想定しており、空のフィードを生成するとFatal Errorが表示されます。PHPのDom関数などを使用して、Atom仕様に従ったXML文書を作成するか、Alex@Net Blogのように独自にライブラリを用意する必要があります。

 このAtomアクションによって配信されるAtomフィードは、Zend_Feed_Atomクラスの引数に渡すことによって、リスト8のように読み取ることが可能です。Zend_Feed_Abstractは、読み取ったフィードをDomDocumentにするので、Atom仕様に従ったDOMアクセスでAtomエントリの各プロパティを参照できます。


<?php
  $feed = new Zend_Feed_Atom('http://ホスト名/Blog/Atom');
  $entry = $feed->current();
  echo 'タイトル:'.$entry->title.'<br />';
  echo 'コンテンツ:'.$entry->content.'<br />';
?>

リスト8 Atomフィードの読み取り
  • Admin Controller

 Admin Controllerはリスト9のようなコードになっています。基本的にBlog Controllerと同じように考えれば良いのですが、postアクションではHTMLフォームの変数を受け取ってデータベースへ更新処理を行っています。


if ('POST' == $_SERVER['REQUEST_METHOD']) {
  $post = array();
  $post['title'] = isset($_POST['title']) ? $this->_stripslashes($_POST['title']) : '';
  if ('' == $post['title']) {
    $data['errors'][] = 'Title is required.';
  }
  $post['content'] = isset($_POST['content']) ? $this->_stripslashes($_POST['content']) : '';
  if ('' == $post['content']) {
    $data['errors'][] = 'Content is required.';
  }
  $post['tags'] = array();
  $tags = isset($_POST['tags']) ? $_POST['tags'] : '';
  foreach ($tags as $tag) {
    if ('' != $tag) {
      $post['tags'][] = $this->_stripslashes($tag);
    }
  }
  if (0 == count($data['errors'])) {
    if (isset($_POST['delete'])) {
      BlogData::DeletePost($id);
    } else if (null == $id) {
      BlogData::CreatePost(2, $post);
    } else {
      BlogData::UpdatePost($id, $post);
    }
    $this->_redirect('/Admin/Posts/');
  }
  $data['post'] = $post;

リスト9 Admin Controllerのコード

 「if ('POST' == $_SERVER['REQUEST_METHOD'])」では、HTTPメソッドがPOSTの場合にForm変数が引き渡されたと解釈し、各POST変数に値が入っていない場合は「$data['errors']」にアラートを出力するようにエラーメッセージを代入しています。

 1つでもPOST変数が不足していた場合は更新処理が行われず、再び同じビュースクリプトが読み込まれて、「$data['errors']」の内容も表示されます。変数の有無によってDELETE/UPDATE/INSERTの処理がデータベースに対して行われ、最後に「/Admin/Posts/」へリダイレクトされます。

このページで出てきた専門用語

Atomフィード

ほとんどのブログツールやサイトでは、サイトの更新情報を「RSS」や「Atom」といったXMLで配信する。Atomは、更新情報を配信するためのフォーマットで、「Atomフィード」は更新情報が格納されたファイルを指す。Atomの仕様はこちらで参照できる。

Permalink

「パーマリンク」と読み、ブログに書かれたエントリのそれぞれを固有に指し示すURI。「永続リンク」などとも呼ぶ。


Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ