<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>ECWorks Blog &#187; schema</title>
	<atom:link href="http://blog.ecworks.jp/archives/tag/schema/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.ecworks.jp</link>
	<description>CakePHPを中心としたサイト開発情報をメインに公開。新しもの好きなので時々製品レポートなんかも。</description>
	<lastBuildDate>Fri, 09 Dec 2011 07:24:42 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://blog.ecworks.jp/archives/tag/schema/feed" />
	<div id='fb-root'></div>
					<script type='text/javascript'>
						window.fbAsyncInit = function()
						{
							FB.init({appId: 122492164489250, status: true, cookie: true, xfbml: true});
						};
						(function()
						{
							var e = document.createElement('script'); e.async = true;
							e.src = document.location.protocol + '//connect.facebook.net/ja_JP/all.js';
							document.getElementById('fb-root').appendChild(e);
						}());
					</script>	
						<item>
		<title>【CakePHP】お手軽便利なCakeSchema</title>
		<link>http://blog.ecworks.jp/archives/851</link>
		<comments>http://blog.ecworks.jp/archives/851#comments</comments>
		<pubDate>Thu, 27 Aug 2009 20:55:24 +0000</pubDate>
		<dc:creator>MASA-P</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[schema]]></category>

		<guid isPermaLink="false">http://blog.ecworks.jp/?p=851</guid>
		<description><![CDATA[DBのテーブル設定は非常に面倒な作業の一つです。
特に、開発時は仕様変更などでテーブル内のフィールドが頻繁に増減することもあるかもしれません。
テーブルを作成したり、更新したりするのに、皆さんはどのような手順を踏まれるでしょうか？
CakePHPには、schemaシェルが付属されていて、これを用いることで簡単にテーブルを初期化することができます。コマンドラインからコマンド一発で書き換わるので大変に便利です。]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.ecworks.jp%252Farchives%252F851%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22%E3%80%90CakePHP%E3%80%91%E3%81%8A%E6%89%8B%E8%BB%BD%E4%BE%BF%E5%88%A9%E3%81%AACakeSchema%22%20%7D);"></div>
<p><a href="http://blog.ecworks.jp/wp-content/uploads/2009/02/cake-logo.jpg"><img class="alignleft size-thumbnail wp-image-336" style="margin: 5px;" title="cake-logo" src="http://blog.ecworks.jp/wp-content/uploads/2009/02/cake-logo-150x150.jpg" alt="cake-logo" width="150" height="150" /></a>DBのテーブル設定は非常に面倒な作業の一つです。<br />
特に、開発時は仕様変更などでテーブル内のフィールドが頻繁に増減することもあるかもしれません。</p>
<p>テーブルを作成したり、更新したりするのに、皆さんはどのような手順を踏まれるでしょうか？まずSQLを書いて、アップロードして、mysqlやpsqlのコンソールを使って実行していますでしょうか？それとも、mysqladminとかのguiツールを使っていますでしょうか？</p>
<p>CakePHPには、schemaシェルが付属されていて、これを用いることで簡単にテーブルを初期化することができます。コマンドラインからコマンド一発で(実際には確認メッセージがあるのでy/n選択がありますが)、書き換わるので大変に便利です。<br />
ただ、ドキュメントや情報が公開されているブログなどが少ないため、どのように記述して良いか分からない方も多いかと思います。そこで、簡単に使い方を解説し、今回の目玉である「初期値を登録する方法」も伝授しちゃいます。</p>
<h3>■schemaシェルの使い方</h3>
<p>schemaシェルは、cakeコンソール内から呼び出されます。基本的な使用方法は次の通りです。</p>
<p>cake schema [-app (app名)] run create [(スキーマ名)] [(テーブル名)]</p>
<p>スキーマ名が無指定だと、AppSchemaが使われ、テーブル名が無指定だと全てのテーブルを処理します。<br />
ちなみに、最初の「y/n/q」は「現在あるテーブルをドロップするか？」の問い合わせ、次が「新しくテーブルを作るか？」の問い合わせです。</p>
<p>また、現在設定されているテーブルを解析して、AppSchemaを作ることもできます。</p>
<p>cake schema [-app (app名)] generate [-f]</p>
<p>なお、AppSchemaはschema.phpとして、「app/config/sql」に保存されます。<br />
自前で作成する場合も、基本的にはここに作成します。<br />
また、標準では２回目以降は、スナップショットをとるか聞いてきますが、「-f」オプションをつけるとオーバーライトします。</p>
<p>※ほかにもオプションなどがありますので、詳しくはusageをご覧ください。</p>
<h3>■schema.phpの記述方法</h3>
<p>schema.phpは、次のようなクラスを記述します。</p>
<pre class="brush: php; ">

&lt;?php
class AppSchema extends CakeSchema {
var $name = &#039;App&#039;;

//beforeコールバック
//
function before($event = array()) {
return true;　　//正常終了はtrueを与える
}

//afterコールバック
//
function after($event = array()) {
}

//各テーブル（この場合はusersテーブル)
//
var $users = array(
&#039;id&#039; =&gt; array(
&#039;type&#039; =&gt; &#039;integer&#039;, 　　//型(int型)
&#039;null&#039; =&gt; false, 　　//nullがOKか?(falseなので不許可)
&#039;default&#039; =&gt; null,　　//デフォルト値(null)
&#039;key&#039; =&gt; &#039;primary&#039;,　　//インデックス(primaryを指定)
&#039;extra&#039; =&gt; &#039;auto_increment&#039;, 　//auto_increment指定
&#039;length&#039; =&gt; 10,　　//型の長さ(int(10))
),
&#039;created&#039; =&gt; array(
&#039;type&#039; =&gt; &#039;datetime&#039;,
&#039;null&#039; =&gt; false,
&#039;default&#039; =&gt; null,
),
&#039;modified&#039; =&gt; array(
&#039;type&#039; =&gt; &#039;datetime&#039;,
&#039;null&#039; =&gt; false,
&#039;default&#039; =&gt; null,
),

&#039;name&#039; =&gt; array(
&#039;type&#039; =&gt; &#039;string&#039;,　　//string = varchar型
&#039;null&#039; =&gt; false,
&#039;default&#039; =&gt; null,
&#039;length&#039; =&gt; 255,　　//= varchar(255)
),

&#039;indexes&#039; =&gt; array(
&#039;PRIMARY&#039; =&gt; array(
&#039;column&#039; =&gt; &#039;id&#039;,　　//対象カラム
&#039;unique&#039; =&gt; true, 　　//ユニークなインデックスの場合はtrueを
),
&#039;user_name_idx&#039; =&gt; array(
&#039;column&#039; =&gt; array(&#039;id&#039;, &#039;name&#039;),　　//カラムが複数の場合はarrayで
&#039;unique&#039; =&gt; true,
),
),
);

}
</pre>
<p>型は、データベースの種類によって違いますが、おおむね次のような型を指定できます(下記はmysqlのもの)。<br />
各DBのdatasourceの最初の方に定義されていますので、お使いのDBでどんな型が使えるか、確認してみてください。</p>
<p>string　　=&gt; varchar<br />
text<br />
integer　　=&gt; int<br />
float<br />
datetime<br />
timestamp<br />
time<br />
date<br />
binary　　=&gt; blob<br />
boolean　　=&gt; tinyint</p>
<p>定義されていない型は、string(varchar)と見なされるようです。<br />
※これはdatasource由来のものなので、schemaだからということはありません。</p>
<h3>■初期値を簡単に与える方法</h3>
<p>さて、ここまではソースを参照すれば何となく分かる範囲だと思いますが、ここからはECWorksオリジナルのTipsです。</p>
<p>このようにしてテーブルの初期化はできますが、マスタ(定数)を登録しておきたい場合もあると思います。毎回値を手入力するのは大変ですよね。<br />
そこで、schema.php内にある「after()」コールバックで定義してしまおう、というのが今回の趣旨です。</p>
<p>しかし、一つ困った点があります。それは「schema.php内に記述したプロパティは、全部テーブルを作るのに使われてしまう」のです。さらに困ったことに、ご丁寧にも「テーブルとして登録したデータは、プロパティから削除されてしまう」のです。つまり、schema.php内に、定義したいデータを書くことができないのです。</p>
<p>そこで、「schema.phpではない場所にデータを書いて、schema.phpから呼び出してしまう」ことで、上記問題を解決してしまいます。</p>
<p>まず、after()コールバックに、次のようなコードを記述します。</p>
<pre class="brush: php; ">

function after($event = array()) {
//初期値ツールの呼び出しと実行
//
if(!empty($event[&#039;create&#039;])){
if(!isset($this-&gt;InitialValues)){
require_once($this-&gt;path.DS.&#039;initial_values.php&#039;);
$this-&gt;InitialValues = new InitialValues();
}
$modelname = Inflector::classify($event[&#039;create&#039;]);
$this-&gt;InitialValues-&gt;set($modelname);
}
}
</pre>
<p>これは、テーブルのcreate時にのみ、InitialValuesというクラスを呼び出し、$event['create']に書かれているテーブル名からモデル名を作成し、そのモデルを呼び出してデータ登録を行います。<br />
そして、InitialValuesクラスは次のように記述します。</p>
<pre class="brush: php; ">

&lt;?php
class InitialValues extends Object {

//各モデルの初期値
//
var $values = array(
&#039;User&#039; =&gt; array(
array(
&#039;name&#039; =&gt; &#039;麻生&#039;,
),
array(
&#039;name&#039; =&gt; &#039;鳩山&#039;,
),
array(
&#039;name&#039; =&gt; &#039;志位&#039;,
),
array(
&#039;name&#039; =&gt; &#039;綿貫&#039;,
),
array(
&#039;name&#039; =&gt; &#039;福島&#039;,
),
);

//初期化処理
//
function startup($schema = null){
if($schema === null){
return false;
}
}

//セット関数
//
function set($modelname){

if(!empty($this-&gt;values[$modelname])){
$this-&gt;{$modelname} = ClassRegistry::init($modelname);
$this-&gt;{$modelname}-&gt;saveAll($this-&gt;values[$modelname]);
}
}
}
</pre>
<p>今回はUserしか書いていませんが、複数テーブルがある場合は同階層で列挙していきます。<br />
欠点は、model名とテーブル名をcake規約で書いていない場合、このやり方ではうまくいきません。別途テーブルを作るとかの改造が必要です。<br />
また、配列を工夫すれば、アソシエーション付きのデータを登録することもできると思います。</p>
<p>以上で簡単な説明になりますが、コマンドラインが使え、なおかつ複雑なテーブル定義をしない(Cakeで一般的とされているテーブル定義で事足りる)場合は、上記手法はなかなかおすすめかと思います。<br />
なお、現時点のバージョン(1.2.4)では、エラーがコールバック内で参照できないため、その点も注意が必要かもしれません。</p>
<p>schemaはまだまだ発展途上の機能かと思われますが、それは大勢の方に使われていないからだと思います。この情報を公開することで、schemaの利用が活発になり、よりよいものになってくれればと期待します。</p>

<div class='wpfblike' style='height: 40px;'><fb:like href='http://blog.ecworks.jp/archives/851' layout='default' show_faces='true' width='400' action='like' colorscheme='light' send='false' /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.ecworks.jp/archives/851/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://blog.ecworks.jp/archives/851" />
	</item>
	</channel>
</rss>

