<?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/"
	>

<channel>
	<title>INSPIRE TECH &#187; CakePHP</title>
	<atom:link href="http://inspire-tech.jp/tag/cakephp/feed/" rel="self" type="application/rss+xml" />
	<link>http://inspire-tech.jp</link>
	<description>株式会社インスパイアデザインのプログラマーである家富正幸が、デザインやシステム開発、ソーシャルメディアや最近のトレンドなど、Webに関する様々な情報を発信しているブログです。</description>
	<lastBuildDate>Fri, 29 Jan 2016 05:25:58 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.8.41</generator>
	<item>
		<title>CakePHPで指定したフォームにデータが存在する場合だけ、あるフォームのバリデーションを行うためのビヘイビアを書いてみた</title>
		<link>http://inspire-tech.jp/2011/10/cakephp_assoc_field_validation_behavior/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cakephp_assoc_field_validation_behavior</link>
		<comments>http://inspire-tech.jp/2011/10/cakephp_assoc_field_validation_behavior/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 02:30:07 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[開発]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=1193</guid>
		<description><![CDATA[CakePHPでフォームのバリデーションを行う場合、例えばチェックボックスで「選択肢A」が選択されている場合のみ、「アンケート」のテキストエリアを必須入力にしたい！といった事があるかと思います。 バリデーションルールを切 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPでフォームのバリデーションを行う場合、例えばチェックボックスで「選択肢A」が選択されている場合のみ、「アンケート」のテキストエリアを必須入力にしたい！といった事があるかと思います。</p>
<p>バリデーションルールを切り替えるというのも1つの手段かと思いますが、もっと簡単に、バリデーションの定義だけでそれを実現できる関数を、ビヘイビアとして書いてみたので公開します。<br />
<span id="more-1193"></span></p>
<h3><span>ソースコード</span></h3>
<p>下記の<code>assoc_field_validation.php</code>をダウンロードして、<code>APP/models/behaviors/</code>以下に設置してください。</p>
<p><script src="https://gist.github.com/1273549.js"> </script></p>
<h3><span>使い方</span></h3>
<p>ビヘイビアに含まれる<code>checkAssocField</code>関数を、バリデーションのルール（ユーザー定義関数）として指定します。</p>
<p>下記のコードは、先ほどの「選択肢A」が選ばれていた場合に「アンケート」の入力を必須入力にする、というサンプルです。</p>
<pre class="brush: php">
class Contact extends AppModel
{
	public $validate = array(
		'option' =&gt; array(
			'inList' =&gt; array(
				'rule' =&gt; array('inList', array('A', 'B', 'C')),
				'required' =&gt; true,
				'allowEmpty' =&gt; false,
			)
		),
		'questionnaire' =&gt; array(
			'checkAssocField' =&gt; array(
				'rule' =&gt; array('checkAssocField', 'option', array('A'), 'notEmpty'),
				'message' =&gt; '必ず入力してください。',
				'required' =&gt; true,
			),
		),
	);
}
</pre>
<p>checkAssocField関数は3つの引数を取ります。</p>
<dl>
<dt>assocField (string)</dt>
<dd>
値をチェックする入力フォーム名です。
</dd>
<dt>assocValueList (array)</dt>
<dd>
<code>assocField</code>で指定してた入力フォームの値がここで指定された値ならば、<code>delegateRule</code>を用いてバリデーションを行います。
</dd>
<dt>delegateRule (mixed)</dt>
<dd>
<code>assocField</code>で指定したフォームの値が<code>assocValueList</code>の値に含まれる場合に、実行するバリデーションのルールを指定します。<br />
ここでは他のバリデーションのルールを自由に指定する事が出来ます。<br />
例）<code>array('maxLength', 30)</code>、<code>array('between', 20, 30)</code>
</dd>
</dl>
<h3><span>注意</span></h3>
<p><code>checkAssocField</code>関数をバリデーションに利用した場合、そのフィールドの<code>allowEmpty</code>と<code>required</code>の指定に気をつけて下さい。</p>
<p>例えば上述の例の場合、<code>allowEmpty</code>を<code>true</code>と指定してしまうと、この関数は意味を成しません。（値が空でもOKということになるため、「選択肢」がAだとしても「アンケート」の値が空で通ってしまう）</p>
<p>また、<code>allowEmpty</code>を<code>false</code>と指定すると、「選択肢」がAであれBであれ、「アンケート」が空の場合はエラーになってしまうため、これもまた意味がありません。</p>
<p>そこで、<code>required</code>のみを<code>true</code>とすることで<strong>値が空の状態でもバリデーションルールは実行する</strong>、という状態にする事が出来ます。</p>
<p>必須のチェックがしたければ、<code>delegateRule</code>に<code>notEmpty</code>を指定する事で行う事ができるので、<code>allowEmpty</code>ではなくそちらを利用するようにしてください。</p>
<p>この指定にだけは気をつけて下さい。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2011/10/cakephp_assoc_field_validation_behavior/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>CakePHPで簡単にメンテナンスモードを実装するMaintenanceコンポーネントを書いてみたよ。</title>
		<link>http://inspire-tech.jp/2011/10/cakephp_maintenance_component/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cakephp_maintenance_component</link>
		<comments>http://inspire-tech.jp/2011/10/cakephp_maintenance_component/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 02:00:09 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[開発]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=1187</guid>
		<description><![CDATA[CakePHPで開発したアプリケーションを公開する際、たとえばバグの修正やデータベースのアップデートを行う場合など、サイトの全機能をいったん止めて、バックエンドで作業したいことがあるかと思います。 エントリポイントである [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPで開発したアプリケーションを公開する際、たとえばバグの修正やデータベースのアップデートを行う場合など、サイトの全機能をいったん止めて、バックエンドで作業したいことがあるかと思います。</p>
<p>エントリポイントである<code>APP/webroot/index.php</code>を差し替えるという強硬手段もあるかと思いますが、もっと手軽に実現するためのMaintenanceコンポーネントを作成してみたので公開します。<br />
<span id="more-1187"></span></p>
<h3><span>利用可能な環境</span></h3>
<p>下記環境で作成・テストを行っています。</p>
<ul>
<li>PHP 5.3.1</li>
<li>CakePHP 1.3.11</li>
</ul>
<p>PHP4系列では動作しません。<br />
また、CakePHP1.2以前では動作するかわかりません。</p>
<h3><span>ダウンロードと設置</span></h3>
<p>下記ソースコードを、<code>maintenance.php</code>として<code>APP/controllers/components</code>/以下に配置してください。</p>
<p><script src="https://gist.github.com/1271972.js"> </script></p>
<h3><span>組み込み</span></h3>
<p>基本的に1つだけのコントローラーをメンテナンスモードにする、というのもあまり考えられないと思うので、<code>AppController</code>自体に組み込んでおくと良いです。</p>
<pre class="brush: php">class AppController extends Controller
{
    public $components = array('Maintenance');
}
</pre>
<h3><span>設定</span></h3>
<p>Maintenanceコンポーネントを動作させる上での設定を、下記の何れかの方法で設定を行います。</p>
<h4>Configureクラスを利用する場合</h4>
<p><code>bootstrap.php</code>などの設定ファイルに記述する際にこちらの方法を使います。</p>
<pre class="brush: php">
Configure::write('Maintenance.level', 2);
Configure::write('Maintenance.errorMethod', 'error404');
</pre>
<h4>コンポーネントの指定時に設定を行う場合</h4>
<pre class="brush: php">
class AppController extends Controller
{
    public $components = array('Maintenance' => array(
        'level' => 2,
        'errorMethod' => 'error404',
    );
}
</pre>
<h4>Controller::beforeFilterメソッドを利用する場合</h4>
<pre class="brush: php">
class AppController extends Controller
{
	public $components = array('Maintenance');
	
	public function beforeFilter()
	{
		$this->Maintenance->level = 1;
		$this->Maintenance->errorMethod = 'error404';
	}
}
</pre>
<h4>利用出来る設定の一覧</h4>
<p>下記の項目を設定可能です。</p>
<p>動作の仕様上、コンポーネントのコンストラクタで利用する設定や、<code>Component::initialize</code>メソッドの実行時に利用する設定もあるため、そういった設定は<code>bootstrap.php</code>で<code>Configure</code>クラスを利用して指定したり、コンポーネントの指定時に設定する方法しか利用できません。</p>
<p>そのため、注釈にbootstrap.phpのみ等と書いてある項目に関しては、設定のタイミングを間違える（例えば、<code>bootstarp.php</code>と書いてある項目を<code>Controller::beforeFilter</code>で設定する等）と正しく動作しませんので、ご注意下さい。</p>
<dl>
<dt>level (int) <small>※bootstrap.php、またはコンポーネントの指定時のみ</small></dt>
<dd>
メンテナンスモードのレベルを設定します。<br />
<code>0</code> &#8211; メンテナンスモードを利用しません。<br />
<code>1</code> &#8211; <code>allowedCIDR</code>で指定されたIPアドレス帯域以外からのアクセスは、強制的にデバッグレベルを0にします。<br />
<code>2</code> &#8211; <code>allowedCIDR</code>で指定されたIPアドレス帯域以外からのアクセスは、強制的にデバッグレベルを0にした上で、メンテナンス画面へリダイレクトします。
</dd>
<dt>debug (int) <small>※bootstrap.phpのみ</small></dt>
<dd>
<code>allowedCIDR</code>で指定されたIPアドレス帯域でアクセスした場合のデバッグレベルを設定します。
</dd>
<dt>allowedCIDR (array) <small>※bootstrap.php、またはコンポーネントの指定時のみ</small></dt>
<dd>
メンテナンスモードの影響を受けないIPアドレスを<a href="http://ja.wikipedia.org/wiki/Classless_Inter-Domain_Routing">CIDRの形式</a>で記述します。<br />
<code>level</code>が1以上の時にここで指定されたIPアドレス帯域でアクセスすると、<code>debug</code>で指定されたデバッグレベルでアプリケーションが実行されます。<br />
配列を利用する事で複数のパターンを指定する事が可能です。<br />
例）<code>192.168.0.1/32</code>
</dd>
<dt>baseURL (mixed)</dt>
<dd>
アプリケーションのホームURLを文字列またはCakeURLの形式で指定します。<br />
<code>level</code>が2の時にこれ以外のURLにアクセスがあった場合、このURLにリダイレクトした後にメンテナンス画面を表示させます。
</dd>
<dt>errorMethod (string)</dt>
<dd>
メンテナンス画面を表示するためのエラーメソッドの名前を指定します。<br />
内部的には<code>Object::cakeError</code>メソッドを利用しているため、<code>cakeError</code>クラスもしくは<code>appError</code>クラスに定義されているメソッド名を指定します。（デフォルトでは<code>error404</code>です）
</dd>
<dt>errorParams (array)</dt>
<dd>
エラーメソッドに渡すパラメータを配列で指定します。
</dd>
</dl>
<h3><span>利用方法</span></h3>
<p>上記設定を参考に、適切な設定を行うだけでOKです。<br />
あとは必要に応じて<code>level</code>を2に変更する事で、すぐさまアプリケーション全体をメンテナンス中にすることができます。</p>
<p>その際、<code>allowedCIDR</code>に指定されたIPアドレス帯域からは、<code>debug</code>に指定したデバッグレベルで通常通りのアクセスが可能なため、通常のユーザーにはメンテナンス中を表示させ、その間に管理者がシステムのアップデートやバグの調査などを行う事が可能になります。</p>
<p><code>level</code>が1の場合は、通常のユーザーはデバッグレベル0、許可されたIPアドレス帯域からは<code>debug</code>に指定したデバッグレベルでアクセスする事ができるので、小さなバグの検証などにも利用できるかと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2011/10/cakephp_maintenance_component/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>CakePHPでデバッグモード以外でもPHPのエラーログを取る超簡単な方法</title>
		<link>http://inspire-tech.jp/2011/10/cakephp_error_logging/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cakephp_error_logging</link>
		<comments>http://inspire-tech.jp/2011/10/cakephp_error_logging/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 15:56:46 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[問題解決]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=1196</guid>
		<description><![CDATA[CakePHPではデバッグレベルを0としている場合、あらゆるエラーが非表示になり、CakePHPのエラーをはじめPHPのWarningやFatalエラーも記録されなくなります。 例えば、その状態で致命的なエラーが発生して [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPではデバッグレベルを0としている場合、あらゆるエラーが非表示になり、CakePHPのエラーをはじめPHPのWarningやFatalエラーも記録されなくなります。</p>
<p>例えば、その状態で致命的なエラーが発生しても、画面が真っ白になったり、<code>ErrorHandler::error404</code>メソッドが実行されるだけで、どこかで能動的<code>に$this->log</code>などで記録していない限り、解決につながる情報が記録されません。</p>
<p>そんな時、下記ブログを参考にカスタムエラーハンドラや、PHPエラーを記録する条件を定義しておくだけで、手軽にログを取ることができるようになります。</p>
<ul>
<li><a href="http://d.hatena.ne.jp/bennylee/20100427/1272368893" title="CakePHPでdebug=0の際にset_error_handler - benny毎日ラボ">CakePHPでdebug=0の際にset_error_handler &#8211; benny毎日ラボ</a></li>
</ul>
<p>この中の内容で、自分も利用させて頂いている2つめの方法が手軽でよいので、紹介させて頂きます。</p>
<blockquote cite="http://d.hatena.ne.jp/bennylee/20100427/1272368893" title="CakePHPでdebug=0の際にset_error_handler - benny毎日ラボ"><p>
/app/config/bootstrap.phpの中にphpエラーログを常に/app/tmp/log/php_error.logに出力するとか<br />
例えば：<br />
if ( Configure::read(&#8216;debug&#8217;) == 0 )  {<br />
   error_reporting(E_ALL &amp; ~E_NOTICE &amp; ~E_DEPRECATED);<br />
   ini_set(&#8216;display_errors&#8217;, 0);   ini_set(&#8216;log_errors&#8217;, 1);<br />
   ini_set(&#8216;error_log&#8217;, LOGS . DS . &#8216;php_error.log&#8217;);<br />
}
</p></blockquote>
<p><cite><a href="http://d.hatena.ne.jp/bennylee/20100427/1272368893">CakePHPでdebug=0の際にset_error_handler &#8211; benny毎日ラボ</a></cite></p>
<p>下記のコードをAPP/config/bootstrap.phpに書いておくだけです。</p>
<pre class="brush: php">
if (Configure::read('debug') == 0) {
    error_reporting(E_ALL &#038; ~E_NOTICE &#038; ~E_DEPRECATED);
    ini_set('display_errors', 0);
    ini_set('log_errors', 1);
    ini_set('error_log', LOGS . DS . 'php_error.log');
}
</pre>
<p>これだけで、デバッグレベルが0の場合でも、<code>APP/tmp/logs/php_error.log</code>にエラー情報が記録されるようになります。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2011/10/cakephp_error_logging/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>CakePHPの超便利なファイルアップロードプラグイン、FileBinderプラグインの使い方をまとめてみた。</title>
		<link>http://inspire-tech.jp/2011/07/cakephp_file_binder_plugin/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cakephp_file_binder_plugin</link>
		<comments>http://inspire-tech.jp/2011/07/cakephp_file_binder_plugin/#comments</comments>
		<pubDate>Mon, 25 Jul 2011 02:00:39 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[参考]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=975</guid>
		<description><![CDATA[CakePHPを利用している上で、一番悩むのがファイルのアップロードとその管理です。 MediaPluginという有名なファイルアップロードプラグインがありますが、高機能・多機能との引き替えに、インストール方法やその利用 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPを利用している上で、一番悩むのがファイルのアップロードとその管理です。</p>
<p>MediaPluginという有名なファイルアップロードプラグインがありますが、高機能・多機能との引き替えに、インストール方法やその利用方法が非常にわかりづらく、さらにプラグインをバージョンアップしただけでエラーを吐いて動かなくなったりと、常時メンテナンス、するプロジェクトに導入するには少々の抵抗があります。</p>
<p>そこで、もっとシンプルで使いやすいファイルアップロードプラグインである、FileBinderプラグインを紹介したいと思います。</p>
<p><span id="more-975"></span></p>
<h3><span>FileBinderプラグインの特徴</span></h3>
<p>FileBinderプラグインは、ファイルアップロードに関して下記のような機能を持っています。</p>
<ul>
<li>ファイルサイズの制限やファイルタイプの制限など、アップロードしたファイルのバリデーション</li>
<li>ファイルの保存方法を任意のディレクトリに保存するか、DBにバイナリとして保存するか選べる</li>
<li>全てのファイルを1つのテーブルで管理できる</li>
<li>任意のテーブルにファイルの情報を仮想のフィールドとして組み込むことができる</li>
</ul>
<p>ファイルアップロードで必要とされるであろうほとんどの機能が実装されていて、普通に使う分であれば何一つ不自由はしません。</p>
<p>そして、FileBinderプラグインの特徴と言える機能が、上記でも紹介している、<strong>任意のテーブルにファイルの情報を仮想フィールドとして組み込むことができる機能</strong>です。</p>
<p>この機能は、特定のテーブルの検索結果に仮想のフィールドを作成し、そこにファイルの情報を埋め込むことで、あたかもそのテーブルにファイルのデータが格納されているかのように扱うことができるのです。</p>
<h4>仮想フィールドの例</h4>
<p>例えば下記のようなプロフィールを管理するテーブルがあったとします。</p>
<ul>
<li>first_name</li>
<li>last_name</li>
<li>age</li>
<li>blood_type</li>
<li>address</li>
<li>email</li>
<li>phone</li>
</ul>
<p>このテーブルにはプロフィール画像などを格納するフィールドはありません。<br />
しかし、FileBinderプラグインを用いると、このテーブルの構造に全く手を付けずに、検索結果にプロフィール画像の情報を埋め込む事が可能になります。</p>
<ul>
<li>first_name</li>
<li>last_name</li>
<li>age</li>
<li>blood_type</li>
<li>address</li>
<li>email</li>
<li>phone</li>
<li><strong>profile_image</strong>
<ul>
<li>file_size</li>
<li>file_name</li>
<li>file_content_type</li>
<li>file_object</li>
<li>&#8230;</li>
</ul>
</li>
</ul>
<p>この機能は非常に便利です。</p>
<p>テーブルに手を加えなくても良いのでデータベース設計が柔軟になりますし、1つのテーブルにいくつでも仮想フィールドを加えることができるため、仕様変更が発生した場合でも簡単に対応できます。</p>
<p>また、Mediaプラグイン同様にファイルの情報を1つのテーブルで管理できるため、情報の管理がしやすくなるというメリットもあります。</p>
<h3><span>基本的な利用の流れ</span></h3>
<p>FileBinderプラグインの基本的な利用方法は、下記のようになっています。</p>
<ol>
<li>ファイルの情報を組み込みたいモデルにBindableビヘイビアを組み込む</li>
<li>上記のモデルにファイルアップロードに関する設定を定義</li>
<li>上記のモデルを利用するコントローラーにRingコンポーネントを組み込む</li>
<li>ファイルアップロードを含んだフォームをコントローラーに送信</li>
<li>コントローラーでbindUpメソッドを実行</li>
<li>モデルのsaveメソッドでフォームデータを保存</li>
</ol>
<p>ビヘイビアとコンポーネントを利用するので多少複雑に感じますが、利用し始めると全くその複雑さは感じません。</p>
<h4>実行環境</h4>
<p>解説は下記の環境を前提に行っています。</p>
<ul>
<li>PHP5系</li>
<li>CakePHP 1.3系
</ul>
<p>CakePHPのバージョンは1.2系でも動作しそうではありますが、実際に試していないので動作保証はできません。</p>
<p>1.2系をご利用の場合は、コンソールからの実行コマンドが一部違ったりするため、その点は読み替えてご利用下さい。</p>
<h4>プラグインファイルのダウンロード</h4>
<p>下記のURLにアクセスして、最新バージョンをダウンロードして、<code>app/plugins/</code> ディレクトリ以下に展開してください。</p>
<p><a title="fusic/filebinder - GitHub" href="https://github.com/fusic/filebinder">fusic/filebinder &#8211; GitHub</a></p>
<h4>Attachmentモデルの作成</h4>
<p>まずはファイル情報を格納するためのモデルである、Attachmentモデルを作成します。</p>
<p>プラグインの<code>config/</code>ディレクトリ以下に<code>schema.php</code>ファイルがありますが、そのまま実行するとバイナリデータ保存用のフィールドの型指定がCakePHPの許可する型に無いため、エラーが発生してしまいます。</p>
<p>そのため、下記のように<code>file_object</code>フィールドの型を<code>longtext</code>から<code>text</code>などに変更します。</p>
<pre class="brush: php">
class AppSchema extends CakeSchema {
    var $name = 'App';

    function before($event = array()) {
        return true;
    }

    function after($event = array()) {
    }

    var $attachments = array(
                           'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
                           'model' => array('type' => 'text', 'null' => false, 'default' => NULL),
                           'model_id' => array('type' => 'integer', 'null' => false, 'default' => NULL),
                           'field_name' => array('type' => 'text', 'null' => false, 'default' => NULL),
                           'file_name' => array('type' => 'text', 'null' => false, 'default' => NULL),
                           'file_content_type' => array('type' => 'text', 'null' => false, 'default' => NULL),
                           'file_size' => array('type' => 'integer', 'null' => false, 'default' => NULL),
                           'file_object' => array('type' => 'text', 'null' => true, 'default' => NULL), // この行のタイプを text に変更
                           'created' => array('type' => 'timestamp', 'null' => true, 'default' => NULL),
                           'modified' => array('type' => 'timestamp', 'null' => true, 'default' => NULL),
                           'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
                           'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB')
                           );
  }
</pre>
<p>そして、コンソールから先ほどの<code>schema.php</code>を利用してテーブルを作成します。</p>
<p><ins datetime="2011-07-26T03:03:16+00:00">コンソールからの実行コマンドが間違えていたのを修正しました。（2011.07.26）</ins></p>
<pre class="brush: shell">cake schema create -app your_app_name -plugin filebinder -name app</pre>
<p>データベースにファイルを保存する場合、先ほど変更した<code>file_object</code>フィールドのデータ型を、データベースのコンソールや設定画面から変更しておきましょう。</p>
<p>さもないと、<strong>text型では最大サイズの都合から、テキストファイルや小さな画像程度しか保存できなくなってしまいます</strong>。</p>
<p>また、忘れずにモデルクラスも作成しておきます。<br />
<code>app/models/attachment.php</code></p>
<pre class="brush: php">
class Attachment extends AppModel
{
}
</pre>
<h4>Bindableビヘイビアの組み込み</h4>
<p>ファイルアップロードのキモとなるBindableビヘイビアを、ファイルの情報を結び付けたいモデルに組み込みます。</p>
<pre class="brush: php">
class Profile extends AppModel
{
	public $actsAs = array(
		'Filebinder.Bindable' => array(
			'model' => 'Attachment', // ファイル情報を保存するモデル名
			'filePath' => WWW_ROOT . 'img' . DS, // ファイルを保存するディレクトリ（絶対パス）
			'dbStorage' => true, // ファイルをバイナリデータとしてデータベースに保存するか
			'beforeAttach' => null, // フック関数（ファイル保存前）
			'afterAttach' => null, // フック関数（ファイル保存後）
			'withObject' => false, // 検索結果にファイルのバイナリデータを付加するか
		)
	);
}
</pre>
<p>オプションを指定しない場合、上記の値がデフォルト値として利用されます。</p>
<h4>bindFields変数の定義</h4>
<p>そして、ファイル情報を結び付ける仮想フィールドの設定を、<code>$bindFields</code>というメンバ変数として下記のように定義します。</p>
<pre class="brush: php">
class Profile extends AppModel
{
	public $actsAs = array(
		'Filebinder.Bindable' => array(
			'model' => 'Attachment',
			'filePath' => WWW_ROOT . 'img' . DS,
			'dbStorage' => true,
			'beforeAttach' => null,
			'afterAttach' => null,
			'withObject' => false,
		)
	);

	public $bindFields = array(
		array(
			'field' => 'profile_image', // ファイル情報を組み込む仮想フィールド名
			'filePath' => WWW_ROOT . 'profile_image' // ファイルを保存するディレクトリ（絶対パス）。指定されない場合、ビヘイビアの設定が利用されます。
		),
	);
}
</pre>
<p>もし、仮想フィールドを複数指定したい場合は下記のように指定します。</p>
<pre class="brush: php">
public $bindFields = array(
	array(
		'field' => 'file_upload_filed_name1',
		'filePath' => WWW_ROOT . 'file1'
	),
	array(
		'field' => 'file_upload_filed_name2'
		'filePath' => WWW_ROOT . 'file2'
	),
	array(
		'field' => 'file_upload_filed_name3'
	),
);
</pre>
<h4>バリデーションの定義</h4>
<p>Bindableビヘイビアにはファイルアップロード専用のバリデーションメソッドが揃っています。</p>
<dl>
<dt>checkContentType</dt>
<dd>ファイルのメタ情報を制限します。</dd>
<dd>
<pre class="brush: php">
array(
	'profile_image' => array(
		'rule' => array('checkContentType', array('image/jpeg', 'image/gif', 'image/png'))
	)
);
</pre>
</dd>
<dt>checkExtension</dt>
<dd>ファイルの拡張子を制限します。</dd>
<dd>
<pre class="brush: php">
array(
	'profile_image' => array(
		'rule' => array('checkExtension', array('jpg', 'gif', 'png'))
	)
);
</pre>
</dd>
<dt>checkFileSize</dt>
<dd>ファイルサイズを制限します。<code>KB</code>、<code>MB</code>、<code>GB</code>などの単位が利用出来ます。</dd>
<dd>
<pre class="brush: php">
array(
	'profile_image' => array(
		'rule' => array('checkFileSize', '10MB')
	)
);
</pre>
</dd>
<dt>checkMinFileSize</dt>
<dd>ファイルの最小サイズを制限します。<code>KB</code>、<code>MB</code>、<code>GB</code>などの単位が利用出来ます。</dd>
<dd>
<pre class="brush: php">
array(
	'profile_image' => array(
		'rule' => array('checkMinFileSize', '10MB')
	)
);
</pre>
</dd>
<dt>funcCheckFile</dt>
<dd>ユーザー関数でファイルのバリデーションを行います。</dd>
<dd>
<pre class="brush: php">
array(
	'profile_image' => array(
		'rule' => array('funcCheckFile', 'userFunction')
	)
);
</pre>
</dd>
<dt>notEmptyFile</dt>
<dd>ファイルの未アップロードを制限します。</dd>
<dd>
<pre class="brush: php">
array(
	'profile_image' => array(
		'rule' => array('notEmptyFile')
	)
);
</pre>
</dd>
</dl>
<p>必要に応じて、仮想フィールドを組み込むモデルにバリデーションを定義します。</p>
<pre class="brush: php">
class Profile extends AppModel
{
	public $actsAs = array(
		'Filebinder.Bindable' =&gt; array(
			'model' =&gt; 'Attachment',
			'filePath' =&gt; WWW_ROOT . 'img' . DS,
			'dbStorage' =&gt; true,
			'beforeAttach' =&gt; null,
			'afterAttach' =&gt; null,
			'withObject' =&gt; false,
		)
	);

	public $bindFields = array(
		array(
			'field' =&gt; 'profile_image',
			'filePath' =&gt; WWW_ROOT . 'profile_image'
		),
	);

	public $validate = array(
		'profile_image' =&gt; array(
			'fileSize' =&gt; array(
				'rule' =&gt; array('checkFileSize', '1MB'),
				'message' =&gt; 'ファイルサイズは1MB以内でアップロードしてください。'
			),
			'fileExt' =&gt; array(
				'rule' =&gt; array('checkExtension', array('jpg', 'gif', 'png')),
				'message' =&gt; '許可されていない拡張子を利用しています。'
			)
		)
	);
}
</pre>
<h4>Ringコンポーネントの組み込み</h4>
<p>フォームからのデータを受け取るコントローラーに、Ringコンポーネントを組み込みます。</p>
<pre class="brush: php">
class ProfileController extends AppController
{
	public $components = array(
		'Filebinder.Ring'
	);
}
</pre>
<p>特に設定は必要ありません。</p>
<h4>フォームを作成</h4>
<p>ファイルアップロードを行うフォームを作成します。<br />
このとき、ファイルを選択する入力フォームは、先ほど定義した仮想フィールドの名前と同一にします。</p>
<p><ins datetime="2011-07-26T03:03:16+00:00">フォームの内容がおかしかったのを修正しました。 （2011.07.26）</ins></p>
<pre class="brush: php">
&lt;?php echo $this-&gt;Form-&gt;create(array('type' =&gt; 'file')) ?&gt;
&lt;dl&gt;
&lt;dt&gt;性&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('first_name') ?&gt;&lt;/dd&gt;
&lt;dt&gt;名&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('last_name') ?&gt;&lt;/dd&gt;
&lt;dt&gt;年齢&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('age') ?&gt;&lt;/dd&gt;
&lt;dt&gt;血液型&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('bloodtype') ?&gt;&lt;/dd&gt;
&lt;dt&gt;住所&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('address') ?&gt;&lt;/dd&gt;
&lt;dt&gt;メールアドレス&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('email') ?&gt;&lt;/dd&gt;
&lt;dt&gt;電話番号&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;text('phone') ?&gt;&lt;/dd&gt;
&lt;dt&gt;プロフィール画像&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $this-&gt;Form-&gt;file('profile_image') ?&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;?php echo $this-&gt;Form-&gt;end() ?&gt;
</pre>
<p>仮想フィールドを複数作成した場合、それに対応した入力フォームを用意しましょう。</p>
<h4>BindUpメソッドを実行し、データを保存</h4>
<p>フォームのデータを受け取るコントローラーのアクションで、Ringコンポーネントのの<code>bindUp</code>メソッドを実行し、あと通常通りデータを保存します。</p>
<p><code>bindUp</code>メソッドはファイルアップロードの前処理を行うメソッドで、この<code>bindUp</code>メソッドを実行しないとファイルが保存されません。</p>
<pre class="brush: php">
class ProfileController extends AppController
{
	public $components = array(
		'Filebinder.Ring'
	);

	public function add()
	{
		if (!empty($this->data)) {
			$this->Ring->bindUp();

			if (!$this->Profile->save()) {
				// 保存完了
			}
		}
	}
}
</pre>
<p>このとき、<code>bindUp</code>メソッドの引数には、ファイルの保存処理を行うモデル名を指定する事ができます。</p>
<p>このモデル名は、先ほどBindableビヘイビアを組み込んだモデルを指定しますが、省略した場合、自動的にコントローラーの<code>$modelClass</code>変数に定義されたモデルが利用されます。</p>
<h4>データが登録されているか確認する</h4>
<p>保存したモデルのデータを実際に確認してみます。</p>
<pre class="brush: php">
$profile = $this->Profile->read();
debug($profile);
</pre>
<pre class="brush: php">
[Profile] => Array
(
    [id] => 1
    [first_name] => 太郎
    [last_name] => 山田
    [age] => 25
    [blood_type] => A
    [address] => 東京都千代田区
    [email] => taro.yamada@test.com
    [phone] => 03-1234-5678
    [craeted] => 2011-07-20 00:00:00
    [modified] => 2011-07-20 00:00:00
    [profile_image] => Array
        (
            [id] => 1
            [model] => Profile
            [model_id] => 1
            [field_name] => profile_image
            [file_name] => sample.jpg
            [file_content_type] => image/jpeg
            [file_size] => 65536
            [created] => 2011-07-20 00:00:00
            [modified] => 2011-07-20 00:00:00
            [file_path] => /app/webroot/profile_image/Profile/1/profile_image/sample.jpg
            [bindedModel] => Attachment
        )
)
</pre>
<p>正しくファイルの情報が結びついて読み出されているのがわかりますね。</p>
<h3><span>注意</span></h3>
<p>この検索結果にファイルの情報を結びつける機能は、ビヘイビアのafterFindメソッドで実現しています。</p>
<p>CakePHPでは、<strong>ビヘイビアのaftetFindメソッドは、そのビヘイビアが組み込まれたモデルが直接検索された時にしか呼ばれません</strong>。</p>
<p>要するに、AというモデルにhasManyで結びつけられたBというモデルがあり、そのBモデルにFileBinderビヘイビアが組み込まれているとします。</p>
<p>この時、<strong>Aモデルをfindした結果にBモデルの情報が存在していても、Bモデルの情報にはファイルの情報は結びついて来ません。</strong></p>
<p>これは実に不便なのですが、CakePHPの仕様のため、ビヘイビアではどうすることもできません。</p>
<h3><span>ビューでの使い方</span></h3>
<p>取得したファイルの情報を表示するには、付属のLabelヘルパーが便利です。<br />
Labelヘルパーには下記のような機能があります。</p>
<ul>
<li>ファイル情報の配列からaタグ（リンク）を生成</li>
<li>ファイル情報の配列からimgタグを生成</li>
<li>ファイルがブラウザから参照出来ない場所にある場合でも、ファイルがダウンロード・表示できるようにURLを生成してくれる</li>
</ul>
<h4>Labelヘルパーの使い方</h4>
<p>HTMLヘルパーに似ているので、使い方は簡単です。</p>
<dl>
<dt>ファイル情報からａタグを生成する</dt>
<dd>
<pre class="brush: php">
echo $this->Label->link($profile['profile_image']);
</pre>
</dd>
<dt>ファイル情報からimgタグを生成する</dt>
<dd>
<pre class="brush: php">
echo $this->Label->image($profile['profile_image']);
</pre>
</dd>
</dl>
<h3><span>ファイルの削除</span></h3>
<p>仮想フィールドに登録したデータを削除したい場合、下記のようなフィールドを利用します。</p>
<pre class="brush: php">
$this->Form->checkbox('profile_image_delete');
</pre>
<p><code>仮想フィールド名＋_delete</code>という名称のフィールドが送信された場合、そのフィールドの値が真であれば、対応する仮想フィールドに結びついているファイル情報が削除されます。</p>
<h3><span>とても便利なプラグイン</span></h3>
<p>以上、基本的な使い方を解説しましたが、使い慣れると手放せなくなるほど便利なプラグインです。</p>
<p>ファイルのバージョン生成機能やキャッシュ機能などはありませんが、Mediaプラグインのように面倒なインストールや設定作業が必要ではなく、フック関数を利用することで様々な利用方法が考えられます。</p>
<p>是非一度、利用してみてください。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2011/07/cakephp_file_binder_plugin/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>CakePHP1.3でデバッグレベルが0の時でもSQLのログを記録する方法</title>
		<link>http://inspire-tech.jp/2011/07/cakephp_save_sql_log/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cakephp_save_sql_log</link>
		<comments>http://inspire-tech.jp/2011/07/cakephp_save_sql_log/#comments</comments>
		<pubDate>Sat, 09 Jul 2011 13:11:13 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[参考]]></category>
		<category><![CDATA[開発]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[データベース]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=857</guid>
		<description><![CDATA[CakePHPではデバッグレベルが2の場合、レンダリングした画面の下部に発行したSQLのログを表示してくれます。 この機能は非常に便利ですが、本番環境などでデバッグレベルを0にしていると、発行したSQLを確認する手段があ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPではデバッグレベルが2の場合、レンダリングした画面の下部に発行したSQLのログを表示してくれます。</p>
<div class="component img">
<a href="http://inspire-tech.jp/wp-content/uploads/2011/07/cakephp-sql-log.png"><img src="http://inspire-tech.jp/wp-content/uploads/2011/07/cakephp-sql-log-570x196.png" alt="" title="cakephp-sql-log" width="570" height="196" class="alignnone size-large wp-image-957" /></a></div>
<p>この機能は非常に便利ですが、本番環境などでデバッグレベルを0にしていると、発行したSQLを確認する手段がありません。</p>
<p>本番環境で何かしらデータベースエラーが発生した場合に、発行されているSQLを確認したいと思っても、そのままでは方法が無いのが現状です。</p>
<p>そこで、利用しているデータベースのドライバクラスを改良して、CakePHPのデバッグレベルに関わらず、発行したSQLをログファイルに保存できるように改造してみます。</p>
<h3><span>ロギング用のデータベースドライバを作成</span></h3>
<p>CakePHPのコアファイルに手を入れるのは避けたいので、データベースのドライバクラスを継承したログファイル保存用のドライバクラスを作成します。</p>
<p>ここではMySQLを利用する場合を想定します。<br />
他のデータベースを利用している場合は、適宜利用しているデータベースのドライバクラスにを読み替えて下さい。</p>
<h4>ファイルを作成</h4>
<p><code>app/models/datasources/</code> に <code>dbo_mysql_log.php</code> を作成します。</p>
<h4>dbo_mysqlを継承したコードを記述する</h4>
<p>ここでは<code>DboMysql</code>を継承した<code>DboMysqlLog</code>という名前でクラスを作成します。</p>
<p>そして、SQLを発行するための関数である<code>execute</code>関数と、SQLのログ表示に関する処理を行う<code>logQuery</code>関数をオーバーライトして、SQLをログに保存する設定であれば、実行したSQLをログファイルに保存できるように改良します。</p>
<p><script src="https://gist.github.com/1073579.js"> </script></p>
<p><code>App::import()</code>関数を利用してスーパークラスを読み込んでおかないとエラーが出ますので注意して下さい。</p>
<h3><span>データベースの接続設定を行う</span></h3>
<p><code>app/configs/database.php</code> ファイルの中で、利用するデータベースのドライバ指定を、先ほど作成したドライバに切り替えます。</p>
<pre class="brush: php">
public $development = array(
	'driver' => 'mysql_log',
	'persistent' => false,
	'host' => 'localhost',
	'login' => '********',
	'password' => '********',
	'database' => 'test',
	'prefix' => '',
	'encoding' => 'utf8'
);
</pre>
<p><code>driver</code>の指定は、作成したドライバのファイル名から <code>dbo_</code> と拡張子を除いたもので指定しましょう。</p>
<h3><span>ログ保存用の設定を行う</span></h3>
<p><code>config/bootstrap.php</code> に下記のようなコードを記述します。</p>
<pre class="brush: php">
Configure::write('Sql.log', true);
</pre>
<p>これで、デバッグレベルに関係なく、発行されたSQLが <code>tmp/logs/sql.log</code> に出力されます。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2011/07/cakephp_save_sql_log/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>CakePHPのデータベースを開発環境と本番環境で切り分ける方法</title>
		<link>http://inspire-tech.jp/2011/04/cakephp_database_settings/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cakephp_database_settings</link>
		<comments>http://inspire-tech.jp/2011/04/cakephp_database_settings/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 13:54:38 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[参考]]></category>
		<category><![CDATA[開発]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=278</guid>
		<description><![CDATA[CakePHPには利用するデータベース定義を複数定義しておける機能がありますが、その使い分けに関するアイデアです。 よくある解決策 よく開発環境と本番環境で自動的にデータベース接続を切り替えられるように、以下のようにDA [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPには利用するデータベース定義を複数定義しておける機能がありますが、その使い分けに関するアイデアです。</p>
<h3><span>よくある解決策</span></h3>
<p>よく開発環境と本番環境で自動的にデータベース接続を切り替えられるように、以下のようにDATABASE_CONFIGクラスのコンストラクタを改良したり、AppModelクラスのコンストラクタに現在の環境を判別できるような設定を書いたりするアイデア多く見かけられます。</p>
<h4>DATABASE_CONFIGクラスの改良</h4>
<pre class="brush: php">
class DATABASE_CONFIG
{
	public $default = array();

	// 公開用
	public $production = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'production.mysql.server',
		'login' => 'admin',
		'password' => '****',
		'database' => 'production_database',
		'prefix' => 'prefix_',
		'encoding' => 'utf8'
	);

	// 開発用
	public $development = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'test',
		'password' => '****',
		'database' => 'development_database',
		'prefix' => 'prefix_',
		'encoding' => 'utf8'
	);

	public function __construct()
	{
		if (env('SERVER_ADDR') !== '127.0.0.1') {
			$this->default = $this->production;

		} else {
			$this->default = $this->development;
		}
	}
}
</pre>
<h4>AppModelの改良</h4>
<pre class="brush: php">
function __construct()
{
	if (env('SERVER_ADDR') == '127.0.0.1') {
		$this->useDbConfig = 'development';
	}  else {
		$this->useDbConfig = 'production';
	}
}
</pre>
<h3><span>よくある解決策の問題点</span></h3>
<p>よくある解決策では、httpから利用する場合には非常に便利で良いのですが、<strong>コンソールから利用する場合、この設定では不都合が発生します。</strong></p>
<p>たとえばschemaコマンドを利用する場合です。<br />
<strong>コンソールではREMOTE_ADDRやSERVER_ADDRなどの環境変数が利用できません。</strong><br />
そのため、コンソールで利用する場合はリモートで利用しているのかローカルで利用しているのかを環境変数から判別することができません。</p>
<p>であれば、schemaコマンドを実行する際に<code> -connection</code>オプションで利用する接続を選択してやれば良いと考えてしまうのですが、CakePHPのコンソールから起動するｓchemaコマンドは、<code>-connection</code>オプションで指定されたデータベース接続（指定されなければdefault）とModelのデータベース接続（Model::$useDbConfig）が一致しない場合、そのModelのスキーマを読み込んでくれません。</p>
<p>実行しているファイルのパスを見て判別するような荒技もありますが、実行ファイルのパスが被らない保証も無いので、こちらも確実とはいえません。</p>
<h3><span>シンプルな解決策</span></h3>
<p>ではどうすれば良いか、というと、Configureクラスを利用する方法が一番わかりやすくてベターです。<br />
<code>config/core.php</code> もしくは <code>config/bootstrap.php</code> に下記のように設定します。</p>
<pre class="brush: php">
Configure::write('database', 'production');
</pre>
<p>そして、config/database.php のDATABASE_CONFIGクラスを下記のように記述します。</p>
<pre class="brush: php">
class DATABASE_CONFIG
{
	public $default = array();

	// 公開用
	public $production = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'production.mysql.server',
		'login' => 'admin',
		'password' => '****',
		'database' => 'production_database',
		'prefix' => 'prefix_',
		'encoding' => 'utf8'
	);

	// 開発用
	public $development = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'test',
		'password' => '****',
		'database' => 'development_database',
		'prefix' => 'prefix_',
		'encoding' => 'utf8'
	);

	public function __construct()
	{
		$connection = Configure::read('database');
		
		if (!empty($this->{$connection})) {
			$this->default = $this->{$connection};
		}
	}
}
</pre>
<p>この方法であれば、データベースを切り替えたいときはデバッグモードの切り替えのように設定値を変更するだけで済みますし、ローカルに依存するコードを記述する必要もなくなります。</p>
<p>さらに今後新しいデータベース接続を追加した場合にも、設定値を変更するだけで対応可能なので、今後の拡張性の面でも安心できます。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2011/04/cakephp_database_settings/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>CakePHPのMediaプラグインでモデル毎にバージョンファイルを生成するアイデア</title>
		<link>http://inspire-tech.jp/2010/11/idea_for_witch_version_file_is_made_with_media_plugin_of_cakephp_in_each_model/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=idea_for_witch_version_file_is_made_with_media_plugin_of_cakephp_in_each_model</link>
		<comments>http://inspire-tech.jp/2010/11/idea_for_witch_version_file_is_made_with_media_plugin_of_cakephp_in_each_model/#comments</comments>
		<pubDate>Wed, 10 Nov 2010 16:21:23 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[参考]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=229</guid>
		<description><![CDATA[CakePHPのMediaプラグインは非常に多機能なプラグインで、バージョン管理という非常に便利な機能が備わっており、本画像に手を加えずにいくつものサムネイル画像を生成する事ができます。 ただ、その便利な機能であるバージ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CakePHPのMediaプラグインは非常に多機能なプラグインで、バージョン管理という非常に便利な機能が備わっており、本画像に手を加えずにいくつものサムネイル画像を生成する事ができます。</p>
<p>ただ、その便利な機能であるバージョン管理機能が少々複雑で、馴れないと使いづらい印象を受けてしまいます。</p>
<p>たとえば画像をアップロードする際、モデルごとに違ったサイズのサムネイルを生成したい、などという場合などが特に悩むポイントかと思います。</p>
<p>基本的にMediaプラグインは、あらかじめアップロードするファイルごとに生成するファイルを「バージョン」として定義しているため、Mediaプラグインを通してアップロードしたファイルは、全て定義した数のバージョンファイルが生成されてしまいます。</p>
<p>そこで、下記のように工夫することで、モデルごとに生成するバージョンファイル取捨選択するアイデアです。</p>
<h3><span>Attachmentモデルをコピーして改良</span></h3>
<pre class="brush: php">
App::import('Lib', 'Media.Media');

class Attachment extends AppModel
{
    public $name = 'Attachment';
    public $useTable = 'attachments';
    public $useVersions = array();

    public $actsAs = array(
        'Media.Transfer' => array(
            'trustClient' => false,
            'transferDirectory' => MEDIA_TRANSFER,
            'createDirectory' => true,
            'alternativeFile' => 100
        ),
        'Media.Generator' => array(
            'baseDirectory' => MEDIA,
            'filterDirectory' => MEDIA_FILTER,
            'createDirectory' => true,
        ),
        'Media.Polymorphic',
        'Media.Coupler' => array(
            'baseDirectory' => MEDIA
        ),
        'Media.Meta' => array(
            'level' => 2
        )
    );

    public $validate = array(
        'file' => array(
            'resource'   => array('rule' => 'checkResource'),
            'access'     => array('rule' => 'checkAccess'),
            'location'   => array('rule' => array('checkLocation', array(
                MEDIA_TRANSFER, '/tmp/'
            ))),
            'permission' => array('rule' => array('checkPermission', '*')),
            'size'       => array('rule' => array('checkSize', '5M')),
            'pixels'     => array('rule' => array('checkPixels', '1600x1600')),
            'extension'  => array('rule' => array('checkExtension', false, array(
                'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'pdf', 'tmp'
            ))),
            'mimeType'   => array('rule' => array('checkMimeType', false, array(
                'image/jpeg', 'image/png', 'image/tiff', 'image/gif', 'application/pdf'
        )))),
        'alternative' => array(
            'rule'       => 'checkRepresent',
            'on'         => 'create',
            'required'   => false,
            'allowEmpty' => true,
        )
    );

    public function makeVersion($file, $process)
    {
        if (!is_array($this->useVersions) &#038;&#038; !empty($this->useVersions)) {
            $this->useVersions = array($this->useVersions);
        }

        if ($this->useVersions === false || !empty($this->useVersions) &#038;&#038; !in_array($process['version'], $this->useVersions)) {
            return true;
        }

        return $this->Behaviors->Generator->makeVersion($this, $file, $process);
    }
}
</pre>
<h3><span>モデルごとに生成するバージョンファイルを切り替える</span></h3>
<p>先ほどのモデルを継承したモデルを生成し、メンバー変数 $useVersions に利用したいバージョンファイル名を配列で列挙します。</p>
<pre class="brush: php">
App::import('Model', 'Attachment');

class UserImage extends Attachment
{
    public $name = 'UserImage';
    public $useVersions = array('main', 'sub');

    public $validate = array(
        'file' => array(
            'resource'   => array('rule' => 'checkResource'),
            'access'     => array('rule' => 'checkAccess'),
            'location'   => array('rule' => array('checkLocation', array(
                MEDIA_TRANSFER, '/tmp/', 'C:\xampp\tmp',
            ))),
            'permission' => array('rule' => array('checkPermission', '*')),
            'size'       => array('rule' => array('checkSize', '1M')),
            'extension'  => array('rule' => array('checkExtension', false, array(
                'jpg', 'jpeg', 'png', 'gif', 'tmp',
            ))),
            'mimeType'   => array('rule' => array('checkMimeType', false, array(
                'image/jpeg', 'image/png', 'image/gif',
            ))),
        ),
    );
}
</pre>
<p>$useVersions が空の場合は全てのバージョンファイルが生成されます。<br />
これにより、モデルごとに生成するバージョンファイルを切り替えることが可能になります。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2010/11/idea_for_witch_version_file_is_made_with_media_plugin_of_cakephp_in_each_model/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MovableTypeのパーマリンクを正規表現でカスタマイズするプラグイン</title>
		<link>http://inspire-tech.jp/2010/08/plugin_to_customize_permalink_of_movabletype/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=plugin_to_customize_permalink_of_movabletype</link>
		<comments>http://inspire-tech.jp/2010/08/plugin_to_customize_permalink_of_movabletype/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 09:56:17 +0000</pubDate>
		<dc:creator><![CDATA[家富 正幸]]></dc:creator>
				<category><![CDATA[その他]]></category>
		<category><![CDATA[開発]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[MovableType]]></category>
		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://inspire-tech.jp/?p=63</guid>
		<description><![CDATA[必要に追われて、MovableTypeのパーマリンクを正規表現でカスタマイズするプラグインを書いたので、需要があるかどうかはわかりませんが公開します。 利用方法はいろいろあると思うんですが、自分の場合はCakePHPのコ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>必要に追われて、MovableTypeのパーマリンクを正規表現でカスタマイズするプラグインを書いたので、需要があるかどうかはわかりませんが公開します。</p>
<p>利用方法はいろいろあると思うんですが、自分の場合はCakePHPのコンテンツ部分を管理するのにMovableTypeを利用する場合に使用しています。<br />
※CakePHPのコンテンツ管理にMovableTypeを利用する、を参照。</p>
<p>CakePHPを設置する場合、Cakeのディレクトリやアプリケーションのディレクトリは公開ディレクトリ以外の部分に設置することが多いため、MovableTypeのテンプレートの生成先をアプリケーションのviewsディレクトリ以下に設定した場合、MovableTypeの生成するパーマリンクや、管理画面上からの記事へのリンク（プレビューなども含めて）が正しく動作しなくなります。</p>
<p>その場合、正規表現でパーマリンクのURLを書き換えることで、正しいURLが生成されるようにできます。</p>
<h3><span>ダウンロード</span></h3>
<p><a href="http://inspire-tech.jp/wp-content/uploads/2010/08/CustomPermalink.zip">http://inspire-tech.jp/wp-content/uploads/2010/08/CustomPermalink.zip</a></p>
<h3><span>動作要件</span></h3>
<p>MovableType 5.0以上</p>
<h3><span>使用方法</span></h3>
<ol>
<li>MovableTypeのPluginsディレクトリにアップロード後、利用したいウェブサイトまたはブログのプラグイン管理画面から、有効のチェックを入れます。</li>
<li>その後、同画面のAdd new pairリンクをクリックするとダイアログが表示されるので、そこに検索する文字列と置換する文字列を設定します。このペアは、複数登録することが可能です。</li>
</ol>
<p>※検索と置換の処理は表示されてるペアの上から順番に実行されていきますので、並び順には注意してください。</p>
]]></content:encoded>
			<wfw:commentRss>http://inspire-tech.jp/2010/08/plugin_to_customize_permalink_of_movabletype/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>
