プロジェクト作成
/path/to/yii/framework/yiic webapp [アプリケーション名]
アプリケーション名のフォルダが作られ、その下に各ファイルが展開される。
設定
基本的にprotected以下のファイルを編集する。以降特に注意書きがなければprotected以下のファイルである。
- nameにアプリケーション名を書く
- dbのconnectionStringにDSNを書く。DSNの書式はPDO準拠
- ユーザ名、パスワードが必要ならdbにusername、passwordを作る
<?php ... return array( 'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..', 'name'=>'アプリケーション名', // autoloading model and component classes 'import'=>array( 'application.models.*', 'application.components.*', ), // application components 'components'=>array( 'user'=>array( // enable cookie-based authentication 'allowAutoLogin'=>true, ), // uncomment the following to set up database 'db'=>array( 'connectionString'=>'mysql:dbname=testapp;hostname=localhost;', 'username'=>'testuser', 'password'=>'testpass', ), ), );
Modelを書く
create table Post ( id integer not null auto_increment, title varchar(128) not null, content text not null, create_time datetime not null, primary key(id) );
というテーブルを作る。
アプリケーション直下(protectedの上)で、
$ protected/yiic shell
を叩くとインタラクティブシェルが起動する。
Yii Interactive Tool v1.0 Please type 'help' for help. Type 'exit' to quit. >>model Post generate Post.php The 'Post' class has been successfully created in the following file: /path/to/app/protected/models/Post.php If you have a 'db' database connection, you can test it now with: $model=Post::model()->find(); print_r($model);
これで雛形が作成される。
ちなみにテーブル名に無いmodelを作ろうとすると警告が出るがそのまま作ることはできる。テーブル名とクラス名の対応を変えたい場合は、先に生成してから、生成されたファイルのtableNameが返す値を変えればいい。
とりあえずScaffold
Yii Interactive Tool v1.0 Please type 'help' for help. Type 'exit' to quit. >> crud Post generate PostController.php generate create.php mkdir /path/to/app/protected/views/post generate update.php generate list.php generate show.php generate admin.php Crud 'post' has been successfully created. You may access it via: http://hostname/path/to/index.php?r=post
デフォルトだとユーザ認証が有効になるので、controllers/PostController.phpのfiltersからaccessControlを外すなりaccessRulesを変えるなりするといいかもしれない。
↑に書いてあるURLを参考にしてアクセスする
create_timeを入れないとエラーなんだけど何なの?死ぬの?
テーブル定義側でやれよ
beforeSave()で入れればいいんじゃね?
<?php ... public function beforeSave() { if ($this->isNewRecord) { if (empty($this->create_time)) { $this->create_time = date('Y-m-d H:i:s', YII_BEGIN_TIME); } } return true; }
titleとかcontentとかNOT NULLのはずなのに空欄でも入るんだけど馬鹿なの?死ぬの?
空欄って普通''の扱いだから正しくね?
validation書くといいよ
<?php ... public function rules() { return array( array('title', 'length', 'max'=>128), array('title', 'required'), array('content', 'required'), ); }
scaffoldそろそろ飽きたんだけど実際の画面はどうやって組むの
なぜか途中で口調が悪くなってるけど気にしない
controllerを生成する。
>> controller blog generate BlogController.php generate index.php mkdir /path/to/app/protected/views/blog Controller 'blog' has been created in the following file: /path/to/app/protected/controllers/BlogController.php You may access it in the browser using the following URL: http://hostname/path/to/index.php?r=blog
このへんっていちいちshellに入らないといけないのかな…
ところでURLださいんだけど2008年のフレームワークとしてこれは(略
ちゃんと変えれるよ
config/main.phpを書き足す
<?php ... 'components'=>array( 'urlManager'=>array( 'urlFormat'=>'path', ), ...
これでhttp://.../index.php/controller/actionみたいなのでアクセスできる
実装
controllers/BlogController.php
<?php ... public function actionIndex() { $posts = Post::model()->findAll(); $this->render('index', array('posts'=>$posts)); }
views/blog/index.php
<?php foreach($posts as $post): ?> <div> <h1><?php echo $post->title ?></h1> <div><?php echo nl2br($post->content) ?></div> </div> <?php endforeach ?>
おいこれXSSし放題だぞ!まさかhtmlspecialcharsとかめんどくさくて書いてられねー
CHtml::encodeってものがあるよ!
<?php foreach($posts as $post): ?> <div> <h1><?php echo CHtml::encode($post->title) ?></h1> <div><?php echo nl2br(CHtml::encode($post->content)) ?></div> </div> <?php endforeach ?>
なんか余計面倒な気が…
ってかもう<?php echoとか長くてだるいんだけど
CPradoViewRendererとかあるよ!
config/main.phpを書き足す
<?php ... 'components'=>array( 'viewRenderer'=>array( 'class'=>'CPradoViewRenderer', ), ...
テンプレートを書き換える
<?php foreach($posts as $post): ?> <div> <h1><?= CHtml::encode($post->title) ?></h1> <div><?= nl2br(CHtml::encode($post->content)) ?></div> </div> <?php endforeach ?>
short_open_tag=Offでもテンプレートだけshort_open_tagが使えるようになるよ!
ついでに自動エスケープもしてくれないのかなぁ
ところでこのままだとレコードが100件とかになったらやばくね?
findAllでlimit指定すればいいんじゃね?
<?php ... public function actionIndex() { $posts = Post::model()->findAll(array('limit'=>10)); $this->render('index', array('posts'=>$posts)); }
おいそれだと過去のデータ見れないだろ!paginationとかないの!
ちゃんとあるから落ち着け
<?php ... public function actionIndex() { $pages = $this->paginate(Post::model()->count(), 2); $conditions = array( 'limit'=>$pages->pageSize, 'offset'=>$pages->currentPage*$pages->pageSize, ); $posts = Post::model()->findAll($conditions); $this->render('index', array('posts'=>$posts, 'pages'=>$pages)); }
<?php $this->widget('CLinkPager',array('pages'=>$pages)); ?> <?php foreach($posts as $post): ?> <div> <h1><?= CHtml::encode($post->title) ?></h1> <div><?= CHtml::encode($post->content) ?></div> </div> <?php endforeach ?> <?php $this->widget('CLinkPager',array('pages'=>$pages)); ?>
とりあえずここまで
詳しくは公式のドキュメントを見てね!
若干怪しい部分があるけど、使いやすそうなので期待