申し込み機能を作る

よくある申し込み、お問い合わせ画面の機能をCakePHPで作ってみる。
申し込み画面→確認画面(バリデーションチェック)→完了画面
という流れ。

DBの作成

moushikomiテーブルを作成

CREATE TABLE `testcake`.`moushikomi` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `namekanji` TEXT,
  `namekana` TEXT,
  `email` TEXT,
  `tel` TEXT,
  `postcode` TEXT,
  `address` TEXT,
  `detail` TEXT,
  `created` DATETIME,
  `modified` DATETIME,
  PRIMARY KEY ( `id`)
)
CHARACTER SET utf8;

モデルの作成

app/models/moushikomi.phpという名前で、下記のようにモデルを作成
モデルの中にバリデーションチェックも記述する。
バリデーションの記述方法は、CakePHP1.2のみの方法が含まれています。

<?php

class Moushikomi extends AppModel {

	var $name = 'Moushikomi';
	var $useTable='moushikomi'; //moushikomiテーブルを利用する 

	var $validate = array(
		'namekanji' => array(
			"rule1" => array('rule' => array('maxlength','50'),
							'message' => '名前(漢字)は50文字以内です'
			),
			"rule2" => array('rule' => VALID_NOT_EMPTY,
							'message' => '名前(漢字)を入力してください'
			),
		),
		'namekana' => array(
			"rule1" => array('rule' => array('maxlength','50'),
							'message' => '名前(カナ)は50文字以内です'
			),
			"rule2" => array('rule' => VALID_NOT_EMPTY,
							'message' => '名前(カナ)を入力してください'
			),
		),
		'email' => array(
			"rule1" => array('rule' => array('maxlength','128'),
							'message' => 'emailは128文字以内です'
			),
			"rule2" => array('rule' => array("email",true),
							'message' => '正しいメールアドレスを入力してください'
			),
		),
		'tel' => array(
			"rule1" => array('rule' => array('maxlength','50'),
							'message' => '電話番号は50文字以内です'
			),
			"rule2" => array('rule' => array("custom",'/^\d{2,4}(-)*\d{2,4}(-)*\d{4}$/'),
							'message' => '正しい電話番号を入力してください'
			),
		),
		'postcode' => array(
			"rule1" => array('rule' => array('maxlength','10'),
							'message' => '郵便番号は10文字以内です'
			),
			"rule2" => array('rule' => array("custom",'/^\d{3}(-)*\d{4}$/'),
							'message' => '正しい郵便番号を入力してください'
			),
		),
		'address' => array(
			"rule1" => array('rule' => array('maxlength','100'),
							'message' => '住所は100文字以内です'
			),
			"rule2" => array('rule' => VALID_NOT_EMPTY,
							'message' => '住所を入力してください'
			),
		),
		'detail' => array(
			"rule1" => array('rule' => array('maxlength','1000'),
							'message' => '申し込み内容は1000文字以内です'
			),
			"rule2" => array('rule' => VALID_NOT_EMPTY,
							'message' => '申し込み内容を入力してください'
			),
		),

	);


}

?>

続いてコントローラ。

app/controllers/moushikomi_controller.phpというファイルを作る。
indexで入力画面を表示し、confirmで確認画面、completeで登録完了を行う。

<?php


class MoushikomiController extends AppController {
  var $name = 'Moushikomi';

  var $uses = array('Moushikomi'); //Moushikomiモデルを利用する

  var $layout = "moushikomi";  //layoutでmoushikomi.ctpを利用する
  var $pageTitle  = "申し込み画面のタイトルです";  //layoutファイルの$title_for_layoutにタイトルをセットする

  function index() {

  }


  function confirm(){
	//バリデーションチェック
	$this->Moushikomi->set($this->data);
	$error = $this->validateErrors($this->Moushikomi);

	//バリデーションエラーがあれば、index画面に戻し、エラーを表示する
	if(!empty($error)){
		//バリデーションがエラーになったら、indexのhtmlを読み込む
		//エラーメッセージを、indexのviewのerrorsにセット
		$this->set("errors",$error);
		$this->render($action = "index");
	}
  }


  function complete(){
		if (!empty($this->data)) {
			$this->Moushikomi->create();

			//データをDBに登録
			if ($this->Moushikomi->save($this->data)) {
				//メール送信を書く

			}else{
				$this->flash(__('DBエラー', true), array('action'=>'index'));
				$this->_stop();

			}
		}
  }

}

今回、completeメソッドで、DB登録完了後にメール送信の箇所を記載する予定だったが、
cakePHP1.2ではメールの日本語に不具合があるため、とりあえず後回し。
本当は完了画面の時に再度バリデーションチェックをした方がいいけど、今回は省略。

最後にViewを記述。

ViewはCakePHPのフォーム機能を使ってみた。補完とかされてマジ楽!

まずはindexのView
app/views/moushikomi/index.ctpを作る

<!-- $form->create("Moushikomi")とやってしまうと、MoushikomisコントローラーにPOSTしてしまうので、省略する -->
<?php echo $form->create(array("action" => "confirm", "type" => "post"));?>


<!-- エラーメッセージの表示 単一表示(今回はこっちは利用しない) -->
<!--
	<?php echo $form->error("Moushikomi.namekanji"); ?>
-->


<!-- エラーメッセージの表示 コントローラで$errorに入れたエラー文字列の配列を展開して表示 -->
<?php if(!empty($errors)){
			foreach ($errors as $error){
				echo h($error) . "<br/>";
	  		}
	  }
?>


	<fieldset>
 		<legend><?php __('申し込み画面');?></legend>

		<!-- 下記のように、cakePHPのformヘルパを使ったhtmlタグ出力を行うと、エラー画面表示の際などにPOSTしたデータを
		あらかじめvalueにセットしてくれて激しく便利!  -->

		名前(漢字)<?php echo $form->text("Moushikomi.namekanji", $options=array("size" => "10", "maxlength" => "50")); ?>
		<br/>
		名前(かな)<?php echo $form->text("Moushikomi.namekana", $options=array("size" => "10", "maxlength" => "50")); ?>
		<br/>
		メール <?php echo $form->text("Moushikomi.email", $options=array("size" => "10", "maxlength" => "128")); ?>
		<br/>
		電話番号 <?php echo $form->text("Moushikomi.tel", $options=array("size" => "10", "maxlength" => "50")); ?>
		<br/>
		郵便番号 <?php echo $form->text("Moushikomi.postcode", $options=array("size" => "10", "maxlength" => "10")); ?>
		<br/>
		住所 <?php echo $form->text("Moushikomi.address", $options=array("size" => "10", "maxlength" => "100")); ?>
		<br/>
		申し込み内容 <?php echo $form->textarea("Moushikomi.detail", $options=array("rows" => "10", "maxlength" => "1000")); ?>


	</fieldset>

<?php echo $form->end('Submit');?>


続いて、確認画面。
app/views/moushikomi/confirm.ctpを作る。

名前(漢字): <?php echo h( $form->value("Moushikomi.namekanji") ) ?>

<br/>
名前(カナ): <?php echo h( $form->value("Moushikomi.namekana") ) ?>

<br/>
Email: <?php echo h( $form->value("Moushikomi.email") ) ?>

<br/>
電話番号: <?php echo h( $form->value("Moushikomi.tel") ) ?>

<br/>
郵便番号: <?php echo h( $form->value("Moushikomi.postcode") ) ?>

<br/>
住所: <?php echo h( $form->value("Moushikomi.address") ) ?>

<br/>
申し込み情報:<br/>
<?php echo nl2br( h( $form->value("Moushikomi.detail") ) ) ?>

<br/>




<?php echo $form->create(array("action" => "complete", "type" => "post"));?>

	<?php echo $form->hidden("Moushikomi.namekanji",
		array("value" => $form->value("Moushikomi.namekanji") ) ); ?>
		
	<?php echo $form->hidden("Moushikomi.namekana",
		array("value" => $form->value("Moushikomi.namekana") ) ); ?>

	<?php echo $form->hidden("Moushikomi.namekana",
		array("value" => $form->value("Moushikomi.namekana") ) ); ?>

	<?php echo $form->hidden("Moushikomi.email",
		array("value" => $form->value("Moushikomi.email") ) ); ?>

	<?php echo $form->hidden("Moushikomi.tel",
		array("value" => $form->value("Moushikomi.tel") ) ); ?>

	<?php echo $form->hidden("Moushikomi.postcode",
		array("value" => $form->value("Moushikomi.postcode") ) ); ?>

	<?php echo $form->hidden("Moushikomi.address",
		array("value" => $form->value("Moushikomi.address") ) ); ?>

	<?php echo $form->hidden("Moushikomi.detail",
		array("value" => $form->value("Moushikomi.detail") ) ); ?>

<?php echo $form->end('登録');?>


<!-- hiddenはvalueの箇所を省略したパターンでもOK -->
<?php echo $form->create(array("action" => "index", "type" => "post"));?>

	<?php echo $form->hidden("Moushikomi.namekanji"); ?>

	<?php echo $form->hidden("Moushikomi.namekana"); ?>

	<?php echo $form->hidden("Moushikomi.namekana" ); ?>

	<?php echo $form->hidden("Moushikomi.email" ); ?>

	<?php echo $form->hidden("Moushikomi.tel" ); ?>

	<?php echo $form->hidden("Moushikomi.postcode" ); ?>

	<?php echo $form->hidden("Moushikomi.address" ); ?>

	<?php echo $form->hidden("Moushikomi.detail" ); ?>

<?php echo $form->end('戻る');?>


最後に、登録完了画面
app/views/moushikomi/complete.ctpを作る

申し込みありがとうございました。
<br/>
<br/>
<a href="index">戻る</a>

ヘッダ、フッタなどを定義したレイアウトファイルを作る。

コントローラで$layoutで入れたファイル名のレイアウトファイルとなる。
app/views/layouts/moushikomi.ctp
$content_for_layout の箇所にviewで定義したファイルの内容が出力される。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<?php echo $html->charset(); ?>
	<title>

		<?php echo $title_for_layout; ?>
	</title>
	<?php
		echo $html->meta('icon');

		echo $html->css('cake.generic');

		echo $scripts_for_layout;
	?>
</head>
<body>
	<div id="container">
		<div id="header">
			<h1>申し込み画面</h1>
		</div>
		<div id="content">
			<?php
				if ($session->check('Message.flash')):
						$session->flash();
				endif;
			?>

			<?php echo $content_for_layout; ?>

		</div>
		<div id="footer">
			フッターです
		</div>
	</div>

</body>
</html>


とりあえず、メール送信機能を除いた申し込みアプリが完成。
Viewのformヘルパーを今回は使った。その使い方などを調べるのに四苦八苦して時間がかかってしまったが、
一度覚えてしまえばこのヘルパーは便利!

CakePHP1.2のいろいろな機能は、「CakePHP ポケットリファレンス」という本が参考になった。

CakePHP ポケットリファレンス (Pocket Reference)

CakePHP ポケットリファレンス (Pocket Reference)

もう少し楽になってほしいのは、Viewのヘルパーでの記述。
POSTされたデータからhiddenタグを自動生成までいけると、もう少し楽になっていいかなと思う。