CakePHP入門 ITかあさん

ITかあさん

目次:CakePHP入門

Cakephpとは人気のフレームワークの一つです。
SQLを書かなくても、何と10分足らずでプログラムが作れちゃいます!
そんな大人気のCakephpの入門をまとめました。
この記事の通りに進めていくと、オリジナルのデザインリンク集を作ることが可能です。
ぜひこの記事を通してCakephpの魅力を存分に知ってくださいね!

cakephpでブックマークアプリを作る 最終回!

はい、正真正銘、今回で最終回を迎えます、Cakephpでブックマークアプリを作る。
今後もちょこちょこCakephp雑記帳の中に入れていくこともありますが、このカテゴリーでの更新は終了します。

今まで熱心に読んでくださったみなさん、ありがとうございました。この記事の下の方にここまで作ったプログラムをまとめて公開しております。
責任は負いませんが、よろしければぜひご利用下さい。

エラーページを変更する

存在しないページにアクセスするとページがありませんってあれです。

私の今回このブログために設置したCakephpのURLは

http://sp.websta.info/posts
http://sp.websta.info/

前回の記事でURL叩いたときの表示も変更しましたが(ドキュメントルート)

さて、存在しないURLをたたくとどうなるでしょうか

http://sp.websta.info/test

(URLは自分の設置したURLと置き換えてください)

testっていう名前のコントローラーが存在しません、というおなじみの緑と黄色のエラーページが表示されます。

エラーページのデフォルトを変更する

エラーページを管理するデフォルトレイアウト

/cake/libs/view/errors

このディレクトリを見てください。
ここには様々なエラーページをあらかじめ作っておいてくれています。
特に解説しなくても、このディレクトリ内のファイル名を見れば、それぞれ何をしているのかは分かると思います。

今回は

http://sp.websta.info/test

testというコントローラーがない、というエラーですから
missing_controller.ctp
を変更すればいいわけです。

missing_controller.ctp をコピーして変更変更

先ほどの

/cake/libs/view/errors

のエラーのうち、missing_controller.ctpをコピーして、変更します。
そして、

app/views/errors/

このディレクトリに
移動します。

私はmissing_controller.ctpに、testとだけ書いてアップしました。すると

エラーの表示は消えて、緑地に

missing_controller.ctp

に書いた内容が表示されています。

Cakephpのデフォルト画面を変更する

エラーページの際、Cakephpの緑のデフォルト画面が出るのはやっぱり恥ずかしいです。
Cakephpのデフォルトを管理しているのが、

/cake/libs/view/layouts/default.ctp

なので、こいつをコピーして、

/app/views/layouts/default.ctp

こちらに設置。そしてカスタマイズしてあげます。

<!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 $this->Html->charset(); ?>
<title>
<?php echo $title_for_layout; ?>
</title>
<?php
echo $scripts_for_layout;
?>
</head>
<body>
<div id="container">
<div id="content">

<?php echo $this->Session->flash(); ?>

<?php echo $content_for_layout; ?>

</div>
<div id="footer">
</div>
</div>
</body>
</html>


とてもあっさりしたデフォルトページの完成です★

おさらい

Cakephpエラー画面の変更

/cake/libs/view/errors
このディレクトリにそれぞれにエラーページがある。それを

app/views/errors/

に移動して変更。

Cakephpのデフォルト画面の変更

/cake/libs/view/layouts/default.ctpがデフォルトページ。
これを
/app/views/layouts/default.ctp
にコピーして好きなように編集。

ダウンロードはこちら

http://sp.websta.info 今回設置したCakephp ダウンロード

http://sp.websta.infoこのページはいずれ、スマートフォンサイトのデザイン集にしようと思っているので、そのうち違う見た目になってしまいます。
このCakephp入門コーナーで作った内容をそっくりそのまま見たい場合はこちらをダウンロードしてください。
再利用してかまいませんが、テンプレートに関しては私の著作物ではないので注意してください。

マスター管理ダウンロード

あと、本来Cakephpは複数アプリケーションを1つのCakephpの中で動かすことが出来ます。
入門ということもあり、この程度で2つのCakephpを設置するという荒業に出ました。
なお、マスター管理画面の設置は、http://sp.websta.infoで設置した時のように、
同一サーバー内にサブドメインを設定して 設置してあげるとよいでしょう。
同一のバーチャルホストのドキュメント直下に2つのCakephpを同時に動かすのはちょっと無理があります。
もし、サクっとCakephpの基礎の基礎だけ勉強したい人はマスターの方だけでもいいかもしれません。

このプログラムのデータベース dumpファイル

必要ないかもしれませんが、このプログラムのデータベースの構造もダウンロードできます。
ダウンロードして、設置して、データベースのユーザー名とパスワードさえ設定できればプログラム初心者でも動かすことが出来ます。

cakephpでブックマークアプリを作る (8)-2

ドキュメントルートを変更する

仮にURLがこうだとして

http://example.com/posts

このURLでアクセスすると、今までローカル環境で作った内容が表示されますよね。

http://example.com/posts

まずはエラーの解決。
エラーの出ているファイルのパーミッションをそれぞれ666に変更してください。

Warning (2): fopen(/home/sp.websta.info/public_html/app/tmp/cache/models/cake_model_default_bookmark_list) [http://php.net/function.fopen]: failed to open stream: Permission denied [CORE/cake/libs/file.php, line 154]
Warning (2): fopen(/home/sp.websta.info/public_html/app/tmp/cache/models/cake_model_default_posts) [http://php.net/function.fopen]: failed to open stream: Permission denied [CORE/cake/libs/file.php, line 154]

次に/public_html/app/views/layouts の
layout.ctpに記述している

<link rel="stylesheet" href="/css/style.css" type="text/css" media="all" />
<!--[if IE 6]>
<link rel="stylesheet" href="/css/ie6.css" type="text/css" media="all" />
<![endif]-->
<script type="text/javascript" src="/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/js/jquery-func.js"></script>

CSS、Javascriptのパスを変更してあげます。(URLの直下ですからね。ローカルと構造がやや異なります)

ローカルと同じに表示された!

これでローカルと同じに表示されました。

ドキュメントルートを変更する

ちなみに私は

というURLで公開したものの

上記URLを叩いたらhttp://sp.websta.info/postsが表示されるようにしたい!

そこで変更するのが
/public_html/app/config/routes.php
です。

通常Cakephpでは、URLの後に来るものは全てコントローラーとしての認識をしてしまいますから、
特別にURLを何か指定したい時はここを触ることになります。

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
↓↓↓↓↓↓↓
Router::connect('/', array('controller' => 'posts', 'action' => 'index', 'index'));

そして、上書きします

そして、URLだけでアクセスします

見事、URLだけでアクセスできるようになりました。
URLやファイルを特別何か指定したい場合はこのroutes.phpをちょこちょこ触ることが多いので覚えておくといいでしょう。

cakephpでブックマークアプリを作る (8)-1

間が開いてしまい、すみません。あと、最終回の予定だったんですが、意外と長くなりそうなので、何回かに分けていきます。もうしらばくお付き合い下さい。

ここまで作った内容は

・一般ユーザーが閲覧するCakephp
・マスター管理のプログラム

2つの構成になっています。
では、ここまでの内容をごっそりアップしていきたいと思います。

まずは一般ユーザーが閲覧するcakeをアップ

まず、閲覧用のCakephpをごっそりサーバーの閲覧可能ディレクトリへアップしてあげます。

そして、URLでアクセス。

Cakephpエラーとの格闘

サーバーにCakephpアップロード直後のエラー全文です。

Warning (512): /home/it-wonder.info/public_html/app/tmp/cache/ is not writable [CORE/cake/libs/cache/file.php, line 267]

Warning: date() [http://php.net/function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /home/it-wonder.info/public_html/cake/libs/log/file_log.php on line 71

Warning (2): strtotime() [http://php.net/function.strtotime]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead [CORE/cake/libs/cache.php, line 570]
Warning: date() [http://php.net/function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /home/it-wonder.info/public_html/cake/libs/log/file_log.php on line 71

Warning (512): /home/it-wonder.info/public_html/app/tmp/cache/persistent/ is not writable [CORE/cake/libs/cache/file.php, line 267]
Warning: date() [http://php.net/function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /home/it-wonder.info/public_html/cake/libs/log/file_log.php on line 71

Warning (512): /home/it-wonder.info/public_html/app/tmp/cache/models/ is not writable [CORE/cake/libs/cache/file.php, line 267]

大量のエラーにびっくりするかもしれませんが、ローカル環境(Win)でプログラムを作っていたのならよくあること。ほとんどがファイルのパーミッションの問題だったりします。

PHP 5.3ならこんなエラーが出る

私は自分で構築したVPSサーバーがPHP5.3.3使っているんですが

Warning: date() [http://php.net/function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /home/it-wonder.info/public_html/cake/libs/log/file_log.php on line 71 

要約しますと、タイムゾーンをちゃんと設定しやがれってことですね。php.iniに設定してもいいのですが、Cakephpからでもいけます。

app\config\core.phpの変更

core.phpの247行目付近に、

//date_default_timezone_set(‘UTC’);

という記述がありますので、コメントアウトを外して、

//date_default_timezone_set(‘UTC’);

date_default_timezone_set('Asia/Tokyo');

と、修正して、core.phpをアップしてあげます。
ちなみにこのエラーはPHP5.3以上の環境で、date関数を実行するとこのエラーは見られます。
Cakephpの問題ってよりは、phpの設定の問題ですね。

エラーが激減する

Warning (512): /home/it-wonder.info/public_html/app/tmp/cache/ is not writable [CORE/cake/libs/cache/file.php, line 267]

Warning (512): /home/it-wonder.info/public_html/app/tmp/cache/persistent/ is not writable [CORE/cake/libs/cache/file.php, line 267]

Warning (512): /home/it-wonder.info/public_html/app/tmp/cache/models/ is not writable [CORE/cake/libs/cache/file.php, line 267]

残りのエラーに関しては、ちょっとPHPをかじった人なら分かりますよね。後怒られているのはパーミッションの部分だけです。

FFFTPなどで、パーミッションをそれぞれ変更する

/app/tmp/cache
/app/tmp/cache/persistent
/app/tmp/cache/models/
この3つのディレクトリをそれぞれパーミッションを777としてください。

/app/tmp/cache/persistent/cake_core_default_ja
こちらのファイルのパーミッションを666としてください

こんな人はいませんか?

エラーは消えたんだけど、CakephpデフォルトのCSSが動いていない


こういう見た目になってしまった人はいませんか??明らかに見た目が悪い・・・というか、Cakephpのデフォルトの黄色と緑のCSSが当たっていない。

/app/webroot/css
に、cake.generic.cssがあるのに、この見た目の人は、/appの直下に
.htaccessがきちんと置かれていないためです。あるいはサーバーに.htaccessの許可がされていないとか。(すんません、私がそうでした)

全てのエラーの対応が終わると、必ずあの緑と黄色のこの見た目になってくれますよ。

この見た目になったら、アップロードは完了です。
データベースをサーバーにもdumpファイル実行して、同じデータベースを容易してあげましょうね。

一通り上がったところで、設定したデータベースのコピー(dump)を実行します。

phpmyadminなどから、ローカル環境のデータベースをエクスポートして、WEBサーバー上にあるphpmyadminにインポートを行います。

きちんとデータベースに接続できると、

ここまで出来れば準備OKですね。

cakephpでブックマークアプリを作る(7)

さてさて、Cakephpで基本的なプログラムの書き方を覚えたのですが、大事なことを何か忘れていますよね!

この見た目ではWEBサイトとして公開することはとてもじゃないけど出来ないですよね!と、いうわけで今回はCakephpの見た目を作る、
『view』『layout』を中心にお送りしたいと思います

Cakephp Layoutを作る

ゼロからテンプレートファイルのデザイン、コーディングをしていくのは大変&面倒なので今回はフリーで商用利用可能なテンプレートを利用することにしましょう。

ChocoTemplates – MovieHunter
今個人的に最もはまっているテンプレート屋さんです。もしこのテンプレートを利用する際は、フッターのコピーライトはそのままにする必要があります。

さて、このテンプレートのindex.htmlをそのままさきlayout.ctpというファイル名にして、

C:\xampp\htdocs\bookmark\app\views\layouts

こちらに設置してください。(layout.ctpとは単なる例なので、なんでもいいです 好きなファイル名を定義してください。)

続いてCSSやJavascriptの設置を行います。

さきほどダウンロードしたフリーテンプレートを下記のようにそれぞれ設置してください。

C:\xampp\htdocs\bookmark\app\webroot

このディレクトリの役割は『ドキュメント直下』という意味になります。画像、CSS、Javascript関係はここに設置するといいでしょう。

ここまで出来たところでプレビューしてみましょう

Cakephpのデフォルト画面ではなくなったものの、完全にCSSなどがリンク切れを起こしていますね・・・
Cakephp内では相対パスではなく、絶対パスで書いていきましょう。

layout.ctpを開いてヘッダーを参照してください。赤字のところをスラッシュ切りの絶対パスに書き換えてあげれば、webrootディレクトリのファイルを読み込んでくれるようになります。

localhostをドメインと考えるならば、webrootのcssフォルダまでのスラッシュ切りの絶対パスと考えれば

<link rel="stylesheet" href="/bookmark/css/style.css" type="text/css" media="all" />
<!--[if IE 6]>
<link rel="stylesheet" href="/bookmark/css/ie6.css" type="text/css" media="all" />
<![endif]-->
<script type="text/javascript" src="/bookmark/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/bookmark/js/jquery-func.js"></script>

変更したらもう一度プレビューしてみましょう。
だいぶ見た目が変わってくれましたね。

ここまで見た目が整ってきたところで、いよいよ今まで作ったプログラムをこのテンプレート内で出力させてみます。

一旦ここまで出来たlayput.ctpのうち、

<div id="content"></div>

この中身をざっくり消して、(後で使うのでどこかにコピーをしておくのが一番いいかと・・・)
こんなカンジで書き換えておきます。

<div id="content">
<?php echo $content_for_layout?>
</div>

$content_for_layoutの中に書くアクション毎のプログラムの結果が返ってくることになります。

最後に、bookmark

C:\xampp\htdocs\bookmark\app\views\posts

このフォルダの中のそれぞれのctpファイルを変更していきます。さきほどlayoutファイルから取り除いたid contentの中身を使います。

実際には、ループのしそうな部分と、サブタイトルだけがあればいいので、必要なのはこの部分だけですね

<!-- Box -->
<div class="box">
<div class="head">
<h2>LATEST TRAILERS</h2>
<p class="text-right"><a href="#">See all</a></p>
</div>

<!-- Movie -->
<div class="movie">

<div class="movie-image">
<span class="play"><span class="name">X-MAN</span></span>
<a href="#"><img src="css/images/movie1.jpg" alt="movie" /></a>
</div>

<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in">

</div>
</div>
<span class="comments">12</span>
</div>
</div>
<!-- end Movie -->

ここに以前作ったループの処理を加えると
こんなカンジになりますね。(赤字の部分が今まで作ったプログラム)

<!– Box –>
<div class="box">
<div class="head">
<h2>LATEST TRAILERS</h2>
<p class="text-right"><a href="#">See all</a></p>
</div>

<!– Movie –>
<?php foreach ($posts as $post ): ?>
<div class="movie">

<div class="movie-image">
<span class="play"><span class="name"><?php echo $post[‘Post’][‘title’];?></span></span>
<a href="<?php echo $post[‘Post’][‘url’];?>"><img src="css/images/movie1.jpg" alt="movie" /></a>
</div>

<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in">

</div>
</div>
<span class="comments"><?php echo $post[‘Post’][‘created’];?></span>
</div>
</div>

<?php endforeach; ?>
<!– end Movie –>

あと、URLに応じて、サイトのサムネイルを自動で取れたら素敵ですね。
ただ、サムネイルの生成については今回のCakephpの内容と若干ずれてきますので
サムネイル自動生成ツールを使うことにします。

HeartRails Capture | サムネイル画像/PDF ファイル作成サービス
サムネイル作成ツールでオススメです。非常に簡単なので、みなさんも使ってください。

例えば http://kaasan.infoのURLのサムネイルを生成したいなら
http://capture.heartrails.com/medium?http://kaasan.info
こうやって書けばいいだけです。これをふまえた上でCakephpでも応用すると

http://capture.heartrails.com/medium?<?php echo $post[‘Post’][‘url’];?>

こんな風にループ中に書けばいいですね。これでサイトごとのサムネイル画像を自動で生成(生成はしてないか)できたわけです。
サイズは自分で自由に設定できるので、詳しくはこのサムネイル生成ツールのホームページより確認してください。

ではプレビューしてみましょう!

なかなか悪くないですね!やっと見れるものができた!ってカンジです。

データベースの設計から始まり、ようやっとここまで完成しましたね、お疲れ様です。

のちほどこのページに完成したマスターと、見た目を整えた閲覧側のCakephpをそれぞれ設置しますので、お待ちください。

お知らせ

重大発表!

長きに渡ってお送りしてきました(ダラダラ書いているからなんだけど)

Cakephp入門は次回で最終回になります!

最後は完成したCakephpをサーバーにアップして、Cakephpをサイトとして運用するための設定、パーミッション、

細かいことなんだけど404エラーや、Googleサイトマップの設置の仕方までお送りしたいと思います。

ただプログラム書いておしまいにしないのがこのITかあさんです!
最終回も、お楽しみに!

cakephpでブックマークアプリを作る(6)

今回マスター管理機能に選択したデータを削除するプログラムを書いていきます。作り方は非常に簡単です。

C:\xampp\htdocs\bookmark_master\app\controllers\posts_controller.php

このファイルを開いて、以下のdeleteアクションを追加してください。
コードはたったこれしかありません。

function delete($id) {

$this->Post->delete($id);

$this->redirect('/posts');

}

解説をしますと、
http://localhost/bookmark_master/posts/delete/8
というURLでアクセスがあった場合$idとはIDが8のことですから、
ID8のデータを削除$this->Post->delete($id);する、ということですね。
たったこれだけ!editアクションに比べるとずいぶんシンプルです。

viewの編集

な、なんと今回はdelete.ctpというファイルすら作りません。
なぜならデータ削除処理をしたらすぐに一覧ページへリダイレクトする流れになるので、必要ないのです。

今回は

C:\xampp\htdocs\bookmark_master\app\views\posts\index.ctp

だけを編集すればよいのです

<table>
<tr>
<th>サイト名</th>
<td>URL</td>
<td>編集</td>
<td>登録日時</td>
<td>更新日時</td>
</tr>
<tr>
<?php foreach ($posts as $post ): ?>
<th><?php echo $post['Post']['title'];?></th>
<td><?php echo $post['Post']['url'];?></td>
<td><a href="/bookmark_master/posts/edit/<?php echo $post['Post']['id'];?>">修正</a>  <a onclick="return confirm('削除してもよろしいですか?');" href="/bookmark_master/posts/delete/<?php echo $post['Post']['id']; ?>">削除</a> </td>
<td><?php echo $post['Post']['created'];?></td>
<td><?php echo $post['Post']['modified'];?></td>
</tr>
<?php endforeach; ?>
</table>

追加したのは、赤字のところだけ、後は前回の分と何も変わっていませんよね。
これだけでもう削除機能はできてしまいました。

解説

Javascriptの confirm(‘削除してもよろしいですか?’)こちらは、Javascriptのalert()に、『OK、キャンセル』の確認ボタンが付いたものです。キャンセルを押せば当然/bookmark_master/posts/edit/8には遷移しません。

削除ボタンを押して削除しているようですが、実際は

http://localhost/bookmark_master/posts/delete/8
にアクセスをしているだけなのです。
すると、8($id=8)を認識して、削除であるdeleteが実行され、すぐに一覧ページへとリダイレクトされる仕組みなのです。
すぐリダイレクトされてしまうので、削除ページを作る必要すら今回はありませんでした。

う~ん、すご~く削除機能はあっさりしていますね!このあっさりしたところがCakePHPの最高にいいところですよね!

cakephpでブックマークアプリを作る(5)-2

今日は前回の解説をします。

PostsController editアクションの解説

http://localhost/bookmark_master/posts/edit/28
このようなURLでアクセスされたときに、お尻の『28』というid番号が$idの中に代入され、
$this->Post->read()を使って対象のデータが$this->dataの中に代入され、
$this->Post->save($this->data[‘Post’])
によって、最終的にフォームデータがデータベースに反映される

というのが一連の流れです。

まずは第一行目のunction edit($id = null) {の $idの正体を見て行きましょう。

中身に何が入っているかを確認するにはdebugを使うんでしたね。

function edit($id = null) {

debug($id);

$this->Post->id = $id;
if (empty($this->data)) {
$this->data = $this->Post->read();
} else {
if ($this->Post->save($this->data['Post'])) {
$this->redirect('/posts');//処理完了後、/postsへリダイレクトされる
}
} }

すると画像のように、仮にURLがhttp://localhost/bookmark_master/posts/edit/8
だとすると、debug($id);の結果は8と返ってきます。

これは、よくパラメータ形式のURLにするときの
http://localhost/bookmark_master/posts/edit/?id=8
と一緒です。
このパラメータを$_GETして、$idに代入しても同じ結果を得ることができます。

2行目に注目すると、$idのデータを$this->Post->idに代入していることが分かります。

では3行目から登場する、$this->dataが何をしているのかを順番に見ていきましょう。

function edit($id = null) {

$this->Post->id = $id;
if (empty($this->data)) {
$this->data = $this->Post->read();
} else {
if ($this->Post->save($this->data['Post'])) {
$this->redirect('/posts');//処理完了後、/postsへリダイレクトされる
}
}
}

$this->dataを動画で確認

いちいち画像をキャプチャするのが面倒なので、動画でまとめました。

注目してもらいたいのが、
$this->data = $this->Post->read();
この上で
debug($this->data);
を実行しても空になる点です。つまり
$this->Post->read();が実行されるまでは$this->dataは空のままなのです。

なぜread();の下では$this->dataに値が入ってくるのでしょう?

read()の役割について:ポイント

$this->Post->read()
Postモデルの一つ目のレベルしかデータを持ってこれない
$this->Post->read(”,$id)
と書いても結果は同じ

$this->Post->read(‘url’, 2);
仮にこのように書くとのidが2番目のurlフィールドを持ってくる、という意味になります。
このread()関数の第一引数がフィールド名ならば、下記の用にフィールド名を空にすると
idが2番目のデータの全てのフィールドを取得する、という意味になります。
$this->Post->read(”, 2);

下記URLにも同じようなことが書いてあります。read()についてはこちらを参考にするといいかもしれません。

3.7.3.6 read()
Blog チュートリアルにつまずいたら” フォーラム – CakePHP Users in Japan

関連するモデル(今回はPost)の直前に取得されたデータ、または、read()のカッコ内で指定されたidのデータを引っ張るのでeditアクションについてはこういう書き方をしてもOKということになります。
実行結果を確認するために、$this->redirect(‘/posts’);は一時的にコメントアウトしてみます。

editアクション コード

function edit($id = null) {
$this->Post->id = $id; if (empty($this->data)) {
$this->data = $this->Post->read('',$id);

} else {
if ($this->Post->save($this->data['Post'])) {

debug($this->data['Post']);

//$this->redirect('/posts');
}
}
}

editアクション コード 実行結果

ちゃんとdebug($this->data[‘Post’]);はフォームに入れたのと同じ結果が入ってきますよね。

忘れちゃいけない

大前提で忘れちゃいけないのが、$this->Post->id = $id;だったりします。
これが無いと、修正をかけたい対象のidが検索できず、
新規登録扱いになってしまいます。

修正かけたい対象は$this->Post->id = $id;
とやって検索をかけてもOKだし、view側のフォーム内のどこかで

<?php echo $form->input('id'); ?>

と書いてもOK!

すると、フォーム送信時に

<?php echo $form->input('id'); ?>

これをhiddenとして、対象のidが渡されます。

(ただ、何でもフォームデータで渡すと、Firebugなどのツールを使って、IDを不正に書き換えたデータを送られてしまう可能性があるので、コントローラー側で処理をするのが無難でしょう)

ちょっと今回は非常に解説が難しかったです!うまく伝わったか心配ですね~。
間違いがあれば訂正していただけるとうれしいです。

この記事に関しては、時間を見つけてもう少し分かりやすく修正できればな~と思います。

今回のコントローラーについてはこちら
次回cakephpでブックマークアプリを作る(6)
にて削除機能を追加したいと思います

cakephpでブックマークアプリを作る(5)-1

Cakephpでブックマークアプリ作成も、いよいよ終盤に差し掛かってきました。
今までDBに直接入れておいたデータや、管理画面から追加したデータを編集するプログラムを作っていきます。

Cakephpのデータ登録の仕組み

idがあれば(このidとはpostsテーブルのidフィールドのこと)データの更新を行い、
idが無ければ新規投稿を行う

これを頭に入れておいてください。

編集画面のedit.ctpを作る

C:\xampp\htdocs\bookmark_master\app\views\posts

こちらを開いて、前回作成したadd.ctpを複製してedit.ctpという名前にしておいてください。

編集用のfunction editの作成

function edit($id = null) {

$this->Post->id = $id;
if (empty($this->data)) {
$this->data = $this->Post->read();
} else {
if ($this->Post->save($this->data['Post'])) {
$this->redirect('/posts');//処理完了後、/postsへリダイレクトされる
}
}
}

アクションの解説はのちほど。

一覧に編集用のリンクを作成

index.ctpファイルを編集します。一覧から編集できるようリンクの追加です。

<table>
<tr>
<th>サイト名</th>
<td>URL</td>
<td>編集</td>
<td>登録日時</td>
<td>更新日時</td>
</tr>
<tr>
<?php foreach ($posts as $post ): ?>
<th><?php echo $post['Post']['title'];?></th>
<td><?php echo $post['Post']['url'];?></td>
<td><a href="/bookmark_master/posts/edit/<?php echo $post['Post']['id'];?>">修正</a></td>
<td><?php echo $post['Post']['created'];?></td>
<td><?php echo $post['Post']['modified'];?></td>
</tr>
<?php endforeach; ?>
</table>

これで今回の編集用のアクションとビューが完成しました。それでは実際にデータを編集してみましょう。

これで書き方は一切間違ってはいないのに、エラーが出てしまうんです。

どんなエラーが出るのか、実際にやってみた

この動画の通り、サブミットボタンを押した瞬間何やらエラーが発動してしまいます。
そして一覧ページに戻ってみると、さきほど修正したデータが問題なく修正されていることが分かります。

http://ortk.main.jp/blog/?p=76

PHPの設定によっては問題ないのですが、このブログを更新している自宅マシンのXamppのphp.iniの設定により、発生する問題だったようです。

『書き方は間違ってないのに、この動画と全くおなじ

Cannot modify header information – headers already sent by…
のエラーが出たらphp.iniの変更を行ってください。

php.iniの変更

php.iniを開いて、

output_buffering = Off →
output_buffering = On
とするだけで、この問題は解決します。

(今日、この記事を書くまで実はこのエラーに出くわしたことが無かったので正直あせりましたが、いい勉強になりました。)

その後Apach再起動をすると、エラーが出なくなり、データの更新も無事行われていることが確認出来ます。

細かい解説は、cakephpでブックマークアプリを作る(5)-2で行いたいと思います。

cakephpでブックマークアプリを作る(4)-2

記事を追加するための見た目の表示である『\posts\add.ctp』はできたので、後は記事を追加するfunction add()を追加するだけですね。

C:\xampp\htdocs\bookmark_master\app\controllers\posts_controller.php

を開いて、下記の赤字の部分を追加してください。

<?php
class PostsController extends AppController {

var $uses = array('Post');

function index($id = null) {

$con = array(
'order' => array('Post.id DESC'),
);

$post = $this->Post->find('all',$con);

$this->set('posts',$post);
}

function add() {
if(!empty($this->data)) {
if($this->Post->save($this->data)) {
$this->redirect('/posts');
}
}
}

}
?>

これだけで、もう記事の投稿はできます。解説は一旦後にして、記事を投稿してみましょう!

Cakephp 記事の追加

登録ボタンを押すと、一覧ページにリダイレクトしてくれます。

もうこれだけで記事の追加ができてしまいました!
さらに注目してほしいのが、登録日時と更新日時両方が、プログラム上何もしていなくても自動で入ってくれます。
フィールド名をcreated、modifiedのDATETIMIE型にしておくことで、
登録日時と更新日時を勝手に入れてくれるんですね!すばらしい

function addの解説

function add() {
	if(!empty($this->data)) {
		if($this->Post->save($this->data)) {
			$this->redirect('/posts');
			}
		}
	}

まず、$this->dataの中身を確認するために、リダイレクト処理である$this->redirect(‘/posts’);をコメントアウトして、$this->dataをdebugしてみましょう。

function add() {
	if(!empty($this->data)) {
		if($this->Post->save($this->data)) {
			//$this->redirect('/posts');
debug($this->data);
			}
		}
	}

もう一度
http://localhost/bookmark_master/posts/add
からデータを投稿してみてください。

ここで言う[Post]とは、Postモデルのことです。この$this->dataの中身は、デバックの結果の通りです。

そして、save関数を使って、データの登録を行っているわけですね。

if(!empty($this->data)) {}

を使って、データが空でなければ登録を行い、無事に登録が完了すると
$this->redirect(‘/posts’);
で指定されたページにジャンプすることができます。

下記URLからダウンロードできます。
http://www.kaasan.info/sample/0528

次回は記事の編集についです。

cakephpでブックマークアプリを作る(4)-1

久々にcakephpでブックマークアプリを作る(4)をお送りします。

間がずいぶん開いてしまいましたが、いよいよ管理画面を作っていきたいと思います。

データの表示をするのがユーザー画面だとすると、データを登録するのはマスター画面となります。
今回からデータの登録を行うマスター画面となるのですが、

ユーザー認証機能まで設けるのは入門としては非常にハードルが上がるので、
前回まで作った

C:\xampp\htdocs\bookmark

このフォルダをそっくりそのまま複製して、

C:\xampp\htdocs\bookmark_master

マスター用のCakephpを用意します。

ポイント

ユーザー用とマスター管理用とそれぞれ別のCakephpを用意する

ということになります。

もし、これにさらにユーザー管理画面も付けるとすると、ユーザー管理画面用とマスター画面と通常画面とで3つのCakephpを用意することになります。

すると、ユーザー管理画面用ならユーザーのみのセッションを確認すればいいわけですし、マスターにいたってはベーシック認証のみをかけるか、IP制限をかけるだけでアクセスはされないわけですから、セッションの管理がすごくシンプルになります。
最初このやり方を聞いたとき、ちょっと乱暴な気がしましたが、よりシンプルに書くことができるという点で、Cakephp使いになってから、私はこの方式をとるようにしています。

さて、前置きはそれくらいにして、いよいよマスター管理画面の編集を行いたいと思います。

posts_controller.phpの編集

まずはコントローラーから編集します。
管理用に一覧表示用である、function indexのみを残して、残りは消してしまいます。

これに、データ追加用のfunctionを追加していきます。
function addはまだ空ですが、コントローラー側の下準備はこれでできました。

<?php
class PostsController extends AppController {

var $uses = array(‘Post’);

function index($id = null) {

$con = array(‘conditions’=>
‘order’ => array(‘Post.id DESC’),

);

$post = $this->Post->find(‘all’,$con);

$this->set(‘posts’,$post);
}


function add() {
}

}

function add用のview編集

下記のフォルダの中に add.ctpファイルを作成して下さい。

C:\xampp\htdocs\bookmark_master\app\views\posts

さきに宣言しちゃいますと、今回はviewの内容が難しいです。
データの追加なので、今回はcakephpでのフォームの作り方がメインになるかと思います。
Cakephpでの独特のフォームの書き方 formヘルパーを覚えていきましょう。

formヘルパー formの作り方。

Cakephpでformを作る時のポイント

actionは自分自身(/bookmark_master/posts/add)
methodは”post”にしたいが、Cakephpのformのデフォルトはgetである

まずはformの枠から作っていきましょう。

formの書き出し

<?php echo $form->create('Post', array('type' => 'post')); ?>

formの終了

</form>と、HTMLでは書けば終了ですが、Cakephpのformヘルパーでは少し書き方が違います

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

これでformの外枠ができました。

Cakephpでformの部品を作ろう

まずはtextフォームから。手始めにタイトルの投稿フォーム。

<?php echo $form->create('Post', array('type' => 'post')); ?>
<?php echo $form->input('title'); ?>
<?php echo $form->end('登録'); ?>

するとこんな感じ。

<?php echo $form->input(‘title’); ?>
これだけのPHPのスクリプトを書いただけで、なんとこれだけのソースが出力されます。

input type=”title”のソース

<div class="input text"><label for="PostTitle">Title</label><input type="text" id="PostTitle" maxlength="50" name="data[Post][title]"/></div>

これだけHTMLがずらずら書かれてしまうと、アレンジが効かせずらいと思いませんか?とりあえずフォームの部品だけ出したい、labelも余計なdivもいらない、maxlengthも自分で書きたい。そんな時はどうしたらいいでしょう。

input type=”text”のアレンジ

<?php echo $form->input('title',array(
'label'=>false,
'div'=>false,
'maxlength'=>false
)
);?>

この状態でソースをプレビューしてみましょう

<input name="data[Post][title]" type="text" id="PostTitle" />

とってもシンプルになりました。これで色々アレンジしやすいですね。さらに、デザイン側の仕様でクラスを追加したいこともあるでしょう。

input type=”text” クラスの追加

classが一つの場合は下記のようになります。

<?php echo $form->input('title',array(
'label'=>false,
'div'=>false,
'maxlength'=>false,
'class'=>'hoge'
)
);?>

クラスが一つだけとは限りませんね。複数追加したい場合は以下のようになります。

<?php echo $form->input('title',array(
'label'=>false,
'div'=>false,
'maxlength'=>false,
'class'=>'hoge hogehoge'
)
);?>

ちょっと意外なのですが、クラスを複数指定したい場合はこのように半角をあけて続けて指定すればよいのです。これでinput type=”text”の詳しいアレンジ方法が分かりましたね。

formヘルパーでselectタグの作り方

残りはselectの作り方です。選択項目をarrayにて代入します。(一行目→7行目に代入)type’ => ‘select’,で、セレクトタグになってくれます。emptyを指定することで、何も選択されていない、デフォルトの値を指定することができます。
後のlabelや余計なdivの排除についてはinput type=”text”とやり方は一緒です。

<?php $category = array('検索エンジン', 'ブログ'); ?>
<?php

echo $form->input('category', array(
'label'=> false,
'div'=>false,
'type' => 'select',
'options' => $category,
''empty' => __('----', true),
'class' => 'styledselect_form_1 required'

))
?>

完成したadd.ctp

<?php echo $form->create('Post', array('type' => 'post')); ?>
<table>

<tr>

<th>タイトル</th>
<td><?php echo $form->input('title',array(
'label'=>false,
'div'=>false,
'maxlength'=>false,
'class'=>'hoge hogehoge'
)
);?></td>

</tr>

<tr>
<th>URL</th>
<td><?php echo $form->input('url',array(
'label'=>false,
'div'=>false,
'maxlength'=>false,
'class'=>'hoge hogehoge'
)
);?></td>

</tr>
<tr>
<th>カテゴリー</th>

<td><?php $category = array('検索エンジン', 'ブログ'); ?>
<?php
echo $form->input('category', array(
'label'=> false,
'div'=>false,
'type' => 'select',
'options' => $category,
'empty' => __('----', true),
'class' => 'styledselect_form_1 required'

))
?></td>
</tr>

</table>

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

プレビュー

次回はコントローラーを利用して、この作成したフォームよりデータが追加出来るよう編集していきたいと思います。

cakephpでブックマークアプリを作る(3)

前回の記事でCakephpのWHEREである、conditionsの使い方が分かりました。さて、これを利用しつつ、カテゴリごとにページを別けたいと思います。

今回の記事でCakephpでのパラメータが分かります。

よくhttp://example.jp/?action=1というよに、?で値を渡します。私もCakephp以前はこのようにやっていたのですが、やはりこの『?=』という形はGoogle先生があまりお好きではありません。ですが、CakephpではGoogle先生が大好きなhttp://example.jp/posts/1
という、スラッシュ切りにしてくれるんです。URLもシンプルで、かつ、SEOにも効果的なURL構造にしてくれるなんて、素晴らしいですね!

これまで私の記事通り作って頂いているなら、
http://localhost/bookmark/posts/category/1
というURLでcategory = 1 のデータを呼び出せるようにしてみましょう!

新規ページ用に、function category()を追加しよう

class PostsController extends AppController に新規functionを追加します。前回までのfunction index($id = null) {}をコピーするとよいでしょう。

function category($id = null) {
$this->Post->category = $id;

$con = array('conditions'=>
	array('Post.category'=>$id),
	'order' => array('Post.id DESC'),
	
);

$post = $this->Post->find('all',$con);
$this->set('posts',$post);
}

$this->Post->category = $id;
これだけで、http://localhost/bookmark/posts/category/1がとれてしまいました。?category=1を$_GET[‘category’]の値を受け取ったのと同じです。

このコントローラーの出力用のViewも追加します。view/posts/index.ctpファイルを複製して、category.ctpという名前で保存してください。

これでばっちりページを別けることができました。view/posts/index.ctpとview/posts/category.ctpの2つのctpファイルの上の方に

<ul>
<li><a href="/bookmark/posts/">トップページ</a></li>
<li><a href="/posts/category/0">検索エンジン</a></li>
<li><a href="/posts/category/1">ブログ</a></li>
</ul>

こんな感じでリンクメニューを追加してみてはどうでしょう??
すっかりブックマークアプリっぽくなりましたね!

今回のデータをZIPファイルで固めました。コメントアウトで詳しい解説付きです。
よかったらダウンロードしてご利用ください。
ダウンロードはこちら

今日のまとめ

$this->Post->category = $id;これでhttp://localhost/bookmark/posts/category/1の、category = 1が取れます。今回はcategoryとしてとりましたが、仮にhttp://localhost/bookmark/posts/id/1とでもして、id = 1のページだけを取りたいときは、$this->Post->id = $id;として、’conditions’=>array(‘Post.id’=>$id) としてあげればid = 1にマッチしたデータが取れます。今回はさらっとしたブックマークアプリですから作りませんが、これを利用すれば各URLの詳細ページみたいなのが作れますね!