<?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>FLAMA技術Blog</title>
	<atom:link href="http://lab.flama.co.jp/feed" rel="self" type="application/rss+xml" />
	<link>http://lab.flama.co.jp</link>
	<description></description>
	<lastBuildDate>Sun, 29 Jan 2012 15:11:53 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>削除記事について</title>
		<link>http://lab.flama.co.jp/archives/584</link>
		<comments>http://lab.flama.co.jp/archives/584#comments</comments>
		<pubDate>Sun, 29 Jan 2012 15:11:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=584</guid>
		<description><![CDATA[隠蔽する意図はありません（笑）。 いままさに情報が増えているものなので、検索結果に悪影響が出ないようにと思っています。 （現実問題として困ることですしね…） ご理解いただけると幸いです。]]></description>
			<content:encoded><![CDATA[<p>隠蔽する意図はありません（笑）。<br />
いままさに情報が増えているものなので、検索結果に悪影響が出ないようにと思っています。<br />
（現実問題として困ることですしね…）<br />
ご理解いただけると幸いです。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/584/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>削除記事（1/30）</title>
		<link>http://lab.flama.co.jp/archives/532</link>
		<comments>http://lab.flama.co.jp/archives/532#comments</comments>
		<pubDate>Fri, 27 Jan 2012 18:50:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[FuelPHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=532</guid>
		<description><![CDATA[この記事には、FuelPHP本家のサーバトラブルによって、一時的にTOPページでのダウンロードリンクやフォーラムなどが1ヶ月ほど巻き戻っていた、という件にピッタリとハマり込んでアワアワしてしまった内容が書かれていました。 [...]]]></description>
			<content:encoded><![CDATA[この記事には、FuelPHP本家のサーバトラブルによって、一時的にTOPページでのダウンロードリンクやフォーラムなどが1ヶ月ほど巻き戻っていた、という件にピッタリとハマり込んでアワアワしてしまった内容が書かれていました。<br/>
その節は各方面にご迷惑をおかけしてすみません。<br/>
<br/>
検索結果などに対しても問題があるとよろしくないので、予告通り、この記事は削除しました。<br/>
<br/>
この記事のタイトルは「fuelphp-v1.1.zipについて」でした。


<!--
FuelPHPのことを書いている回は全てグダグダなのか？と言われてもしょうがない感のある今日このごろ。
この元エントリのほとんど全ては私の勘違いです。<br/>
間違ったことをバラまくのは本意ではないので、しばらくこの勘違いについて掲載した後、削除します。<br/>
<br/>
まず、FuelPHPのTOPページでダウンロードリンクがv1.1-RC1になっていた理由、それは公式サイト＋フォーラムがトラブっていたから。<br/>
<a href="http://twitter.com/#!/fuelphp/status/162685287598788608" target="_blank">http://twitter.com/#!/fuelphp/status/162685287598788608</a><br/>
そして既に復旧済み。<br/>
<a href="http://twitter.com/#!/fuelphp/status/162687898574008320" target="_blank">http://twitter.com/#!/fuelphp/status/162687898574008320</a><br/>
正直気付かなかった…v1.1のダウンロードリンクがあったこと自体が自分の勘違いだと思ってしまうくらい。
<br/>
で、ドキュメント内にあるダウンロードリンク<br/>
<a href="http://docs.fuelphp.com/installation/download.html" target="_blank">http://docs.fuelphp.com/installation/download.html</a><br/>
は、1.0.1含む以前（つまり最新のStableより過去のもの）が掲載されているのが正しい状態。<br/>
"1.1/master"（v1.1としてリリース「された」バージョンのドキュメントのソース）も<br/>
<a href="https://github.com/fuel/docs/blob/1.1/master/installation/download.html" target="_blank">https://github.com/fuel/docs/blob/1.1/master/installation/download.html</a><br/>
となっています。<br/>
<br/>
では"1.1/develop"とは何か？つまり<br/>
<a href="https://github.com/fuel/core/tree/1.1/master" target="_blank">https://github.com/fuel/core/tree/1.1/master</a><br/>
と<br/>
<a href="https://github.com/fuel/core" target="_blank">https://github.com/fuel/core</a><br/>
は何が違うのか？というと、"1.1/master"はv1.1として「リリースされた」ソースであり、"1.1/develop"はそこから開発が継続されているソース群。<br/>
それが2になるのか1.2になるのか1.1.1になるのか、ということですね。<br/>
<br/>
さてではcore/image/imagemagick.phpのバグの件はどうなのよというと、上記を総合すれば、どうやらv1.1ではバグを残したままリリースされた、ということになるんだと思います。<br/>
ただし"1.1/develop"では既に修正されているので、次バージョンではバグは消えるでしょう。<br/>
でもまだ残っている気がするなというのは<br/>
<a href="https://github.com/fuel/core/issues/762" target="_blank">https://github.com/fuel/core/issues/762</a><br/>
でも挙げられていて、
<blockquote>Should be easily fixed with a file_exists() check. Feel free to submit a commit :)</blockquote>
ですよねー。ということでもうちょっとソースと挙動を見てみようと思う次第です。<br/>
<br/>
ということで三度kenjisさんに感謝。<br/>
<a href="http://d.hatena.ne.jp/Kenji_s/20120128/1327702131" target="_blank">http://d.hatena.ne.jp/Kenji_s/20120128/1327702131</a><br/>
<br/>
<br/>
あと余談ですが、つい最近公式のフォーラムに登録してたんです。<br/>
が、ログインできなくなりかつ再登録ができた（ユーザー名やメールアドレスが重複扱いされなかった）ので、おそらく直近の登録ユーザーアカウントなどは復旧にともなって飛んでいるんじゃないでしょうかね。<br/>
<br/>
そもそもBlogとフォーラムの日付をよく見ればおかしいと気付いたはずですね。注意力が低下してました。睡眠はとりましょう。<br/>
＃あと最近めっきりTwitter使っていないのでツイートは完全に見てなかった…<br/>
＃忘れないうちにGoogleReaderに追加しておこう。<br/>
＃あ、自分で自動まとめ作ればいいのか。<br/>
<br/>
<br/>

------------------------------------------------------------------------------------------------------------------------------------<br/>
<br/>
<del datetime="2012-01-28T08:52:34+00:00">今日ふと気付いたんですが、公式にはv1.1-RC1になっています。<br/>
<a href="http://fuelphp.com/" target="_blank">http://fuelphp.com/</a><br/>
しかし私の手元にはv1.1のzip（fuelphp-v1.1.zip）があります。なぜ？<br/>
<br/>
ということであれこれ見てみたんですが、公式ドキュメントに
<blockquote>Fuel is now at v1.1. You can download Fuel using the links below:</blockquote>
と書かれていつつ、かつダウンロードリンクは1.0.1までしか無いのを発見しました。<br/>
<a href="http://docs.fuelphp.com/installation/download.html" target="_blank">http://docs.fuelphp.com/installation/download.html</a><br/>
<br/>
v1.1はまだリリース準備中らしいので（<a href="http://fuelphp.com/roadmap" target="_blank">http://fuelphp.com/roadmap</a>）、たぶん、どこかの時点までダウンロードリンクが誤って出ていたんじゃないかなと思うわけです。<br/>
<br/>
そこで、手元のv1.1とv1.1-RC1のソースを比較してみたんですが、以前1.1の方のソースを見て「バグがあるなー」と思った個所が、v1.1-RC1版では全く違う記述になっており、かつv1.0.1と全く同じものになっています。<br/>
具体的に比較できる例は、core/classes/image/imagemagick.phpのcreate_color()メソッドの部分です。<br/>
<br/>
v1.0.1, v1.1-RC1
<blockquote>	/**
	 * Creates a new color usable by ImageMagick.
	 *
	 * @param  string   $hex    The hex code of the color
	 * @param  integer  $alpha  The alpha of the color, 0 (trans) to 100 (opaque)
	 * @return string   rgba representation of the hex and alpha values.
	 */
	protected function create_color($hex, $alpha)
	{
		if ($hex == null)
		{
			$red = 0;
			$green = 0;
			$blue = 0;
		}
		else
		{
			// Check if theres a # in front
			if (substr($hex, 0, 1) == '#')
			{
				$hex = substr($hex, 1);
			}

			// Break apart the hex
			if (strlen($hex) == 6)
			{
				$red   = hexdec(substr($hex, 0, 2));
				$green = hexdec(substr($hex, 2, 2));
				$blue  = hexdec(substr($hex, 4, 2));
			}
			else
			{
				$red   = hexdec(substr($hex, 0, 1).substr($hex, 0, 1));
				$green = hexdec(substr($hex, 1, 1).substr($hex, 1, 1));
				$blue  = hexdec(substr($hex, 2, 1).substr($hex, 2, 1));
			}
		}
		return "\"rgba(".$red.", ".$green.", ".$blue.", ".round($alpha / 100, 2).")\"";
	}</blockquote>
<br/>
v1.1
<blockquote>	/**
	 * Creates a new color usable by ImageMagick.
	 *
	 * @param   string   $hex    The hex code of the color
	 * @param   integer  $alpha  The alpha of the color, 0 (trans) to 100 (opaque)
	 * @return  string   rgba representation of the hex and alpha values.
	 */
	protected function create_color($hex, $alpha)
	{
		export($this->create_hex_color($hex));
		return "\"rgba(".$red.", ".$green.", ".$blue.", ".round($alpha / 100, 2).")\"";
	}</blockquote>
このv1.1のソースは、github上の"1.1/master"のソースと同一です。<br/>
<a href="https://github.com/fuel/core/blob/1.1/master/classes/image/imagemagick.php" target="_blank">https://github.com/fuel/core/blob/1.1/master/classes/image/imagemagick.php</a><br/>
<br/>
これに対し、"1.1/develop"の該当部分のソースは次のようになっています。
<blockquote>	/**
	 * Creates a new color usable by ImageMagick.
	 *
	 * @param   string   $hex    The hex code of the color
	 * @param   integer  $alpha  The alpha of the color, 0 (trans) to 100 (opaque)
	 * @return  string   rgba representation of the hex and alpha values.
	 */
	protected function create_color($hex, $alpha)
	{
		extract($this->create_hex_color($hex));
		return "\"rgba(".$red.", ".$green.", ".$blue.", ".round($alpha / 100, 2).")\"";
	}</blockquote>
<a href="https://github.com/fuel/core/blob/1.1/develop/classes/image/imagemagick.php" target="_blank">https://github.com/fuel/core/blob/1.1/develop/classes/image/imagemagick.php</a><br/>
<br/>
＃おそらく"export"は"extract"のTypoなんじゃないかなと思うわけですが…<br/>
<br/>
ということでまとめると、公開されていたv1.1のzipを入手してお持ちの方は、v1.0.1に切り戻すか、githubの"1.1/develop"を適宜ひっぱってくるかした方が良いかもしれません。ただし1.1に向けて構造が若干変わっていることと、1.1/developはまだ完成されていないということで、悩ましい選択になるかと思います。少なくとも私にとっては…。<br/>
<br/>
</del>
-->]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/532/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FuelPHPで×画像○ファイルを出力する方法 ※改定版</title>
		<link>http://lab.flama.co.jp/archives/509</link>
		<comments>http://lab.flama.co.jp/archives/509#comments</comments>
		<pubDate>Wed, 25 Jan 2012 17:28:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[FuelPHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=509</guid>
		<description><![CDATA[ということで、間違いを出しっぱなしなのもアレなので、正しい記述のみをまとめ、正しくない情報については、検索結果の阻害にもなるので削除しました。 画像の表示 \Image::load($filename_full); -> [...]]]></description>
			<content:encoded><![CDATA[ということで、間違いを出しっぱなしなのもアレなので、正しい記述のみをまとめ、正しくない情報については、検索結果の阻害にもなるので削除しました。<br/>
画像の表示
<blockquote>\Image::load($filename_full);
->output('jpeg');</blockquote>
ファイル・画像のダウンロード
<blockquote>\File::download($filename_full,$filename);</blockquote>
<br/>
ということで<a href="http://d.hatena.ne.jp/Kenji_s/" target="_blank">kenjis</a>さんありがとうございました。

<!--

※追記3<br/>
そもそもv1.1のCHANGELOG.mdに
<blockquote>* The `$this->response` Response object is now deprecated.  Your action methods should return either a string, View object, ViewModel object or a Response object.</blockquote>
と書いてありました…。<br/>
ドキュメントについても、v1.1devから反映されているようです。<br/>
<a href="https://github.com/fuel/docs/blob/1.1/develop/classes/response.html" target="_blank">https://github.com/fuel/docs/blob/1.1/develop/classes/response.html</a>
<br/>
というか、v1.1の同梱ドキュメントを見たら、めちゃめちゃ例が増えとります。捗るぞという感じです。ただし↑の通り、v1.1devで変わっているところもあるので注意が必要ですね。<br/>
<br/>
で、今回グダグダとあれこれやっていたもともとの出発点は、「HTTPレスポンスは$this->requestのお仕事」という前提に立ってしまったところ。これは間違いではないんでしょうけども、ある意味間違い。<br/>
FuelPHPのやろうとしていることや拡張していこうとする方向を見誤っていた…という感想です。<br/>
ちょっとおおげさですけど。<br/>
<br/>
※追記2<br/>
ダウンロードさせようとしているんだから
<blockquote>$this->response->set_header('Content-Type',$mime);</blockquote>
のところは
<blockquote>$mime='application/octet-stream';
$this->response->set_header('Content-Type',$mime);</blockquote>
だったな、と思って追記しようとしていたところ、<a href="http://d.hatena.ne.jp/Kenji_s/" target="_blank">kenjis</a>さんからさらに「ダウンロードだったら<a href="http://docs.fuelphp.com/classes/file/usage.html#/method_download" target="_blank">File::download();</a>が使えるよ」と教えてもらいました。たびたびありがとうございます！<br/>
これだと
<blockquote>\File::download($filename_full,$filename);</blockquote>
でOKですね。<br/>
必要なヘッダは徹底的に積まれているので、忘れることもなくなります（忘れるので！）。<br/>
mimeはデフォルトで'application/octet-stream'になるので、それ以外にしたい場合は
<blockquote>$mime='application/pdf';
\File::download($filename_full,$filename,$mime);</blockquote>
というように書けます。<br/>
File::download()が実行された時点で$filename_fullが実在しない場合にはFileAccessExceptionが発生するようなので、事前にチェックしておいても良いし、
<blockquote>try{
\File::download($filename_full,$filename);
}catch(\FileAccessException $e){
//例外処理
}</blockquote>
とすることもできると思います。<br/>
<br/>
全く同じやりとりが2ヶ月ほど前に公式フォーラムでありました（笑）<br/>
<a href="http://fuelphp.com/forums/topics/view/5944" target="_blank">FuelPHP › Forums | General | How to send a file as download</a><br/>
<br/>
Imageクラス・Fileクラスについては別途まとめた方が良い予感。<br/>
ImageMagick使う場合の検証等々含め…。<br/>
<br/>
※追記<br/>
<a href="http://d.hatena.ne.jp/Kenji_s/" target="_blank">kenjis</a>さんから
「<a href="http://docs.fuelphp.com/classes/image.html#/method_output" target="_blank">Image::output();</a>でできるよ」と教えてもらいました。<br/>
ありがとうございます！おっしゃる通り。画像を表示させるということであれば
<blockquote>\Image::load($filename_full);
->output('jpeg');</blockquote>
で終了です。2行。<br/>
しかも↓冒頭で書いた「ログインしているユーザーにだけ画像を表示する」というようなパターンや、表示する直前に生成する、というような場合でもこれでOKなわけです。<br/>
<br/>
…で、全くもって私の書き方が悪かったところなわけですが、念頭にあったのは最後段の「ファイル出力全般に〜」というところだったんですね。おまけのように書いてしまっていますが。<br/>
だからまわりくどいことをやろうとしている形になっていたわけなのです…。<br/>
で、さらに言うと↓で、検証せずに避けた第2引数無しの\File::read();ですが、やっぱりそのまま使えるように見えるんですね。<br/>
となると、画像以外のファイルも含めた書き方というのは、
<blockquote>$this->response->set_header('Content-Type',$mime);
\File::read($filename_full);</blockquote>
でOK、ということになるんじゃないかと思います。<br/>
強制的にDLさせる場合も、
<blockquote>$this->response->set_header('Content-Type',$mime)
->set_header('Content-Disposition','attachment;filename="$filename"');
\File::read($filename_full);</blockquote>
でDLされました。<br/>
<br/>
ということで下記は旅の記録としてのみ残しておきます。<br/>
<br/>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br/>
<br/>
ファイルとして存在する画像をそのまま表示するのではなく、たとえばログインしているユーザーにだけ画像を表示する、というような場面は結構あるわけでして、そのような場合にFuelPHPでどうやって実現するか、というのが今回のお題です。<br/>
<br/>
単純に考えると、controllerの中で
<blockquote>（前略）
header("Content-type:image/jpeg");
readfile($filename);</blockquote>
とすればいいんじゃないのかと思うわけですが、表示されない場合があるようなので、とりあえずはFuelPHPのお作法にのっとった書き方を探ってみようというわけです。<br/>
<br/>
さてそもそも、画面出力する場合のFuelPHPのお作法とは、データを渡したResponseクラスをreturnする、という形になるかと思います。たとえばHTMLの場合こんな感じになっているはずです。
<blockquote>return Response::forge(ViewModel::forge('hogehoge'));</blockquote>
ということは、Responseクラスあたりを見ていけばなにかありそうな気がします。<br/>
Responseクラスのドキュメントはこんな感じです。<br/>
<a href="http://docs.fuelphp.com/classes/response.html" target="_blank">http://docs.fuelphp.com/classes/response.html</a><br/>
<br/>
例がResponse::だったり$this->responseだったり、Requestクラスにresponseメソッドというものがあったり、<br/>
<a href="http://docs.fuelphp.com/classes/request.html#/method_response" target="_blank">http://docs.fuelphp.com/classes/request.html#/method_response</a><br/>
どうなっているのかぱっと見よくわかりません。<br/>
しかしRequestクラスのドキュメント冒頭にこのような説明があります。<br/>
<blockquote>The Request class processes URI requests. It is used by Fuel in index.php to process the users URI request, and you need it to generate requests in an HMVC context.</blockquote>
URLがルーティングされた時点で自動的もしくは暗黙的に生成されるということことなのでしょうかね。<br/>
確かにWebアプリのお仕事は基本的にリクエストとレスポンスの間を作ることでしょうし。<br/>
<br/>
さて脱線しましたが、とにかくResponseクラスをきっちり使えばいいのかな？という目星をつけたわけです。<br/>
今回の場合は、前段で処理が入っているので、$this->responseで続けてみます。
<blockquote>header("Content-type:image/jpeg");</blockquote>
は
<blockquote>$this->response->set_header('Content-Type','image/jpeg');</blockquote>
にします。HTTPレスポンスはヘッダ＋本体になるわけなので、あとは
<blockquote>readfile($filename);</blockquote>
ができればいいわけです。<br/>
ふたたび先ほどのHTMLを返す場合を見てみると
<blockquote>return Response::forge(ViewModel::forge('hogehoge'));</blockquote>
となっていました。<br/>
core/response.phpの中を見ると、forgeメソッドの中身はこんな感じ。
<blockquote>	public static function forge($body = null, $status = 200, array $headers = array())
	{
		return new static($body, $status, $headers);
	}</blockquote>
第一引数に表示する中身を入れればよさそうなのですが、ちょっと下を見ていくとbodyメソッドなるものがあります。
<blockquote>	/**
	 * Sets (or returns) the body for the response
	 *
	 * @param   string  The response content
	 * @return  $this|string
	 */
	public function body($value = false)
	{
		if ($value === false)
		{
			return $this->body;
		}
		$this->body = $value;
		return $this;
	}</blockquote>
「@param   string」と書かれているのが若干気になりますが、こっちで試してみます。
<blockquote>$this->response->set_header('Content-Type','image/jpeg');
$this->response->body('hogehoge');
var_dump($this->response);</blockquote>
この結果はこうなるので
<blockquote>
object(Fuel\Core\Response)#12 (3) {
  ["status"]=>
  int(200)
  ["headers"]=>
  array(1) {
    ["Content-Type"]=>
    string(10) "image/jpeg"
  }
  ["body"]=>
  string(8) "hogehoge"
}</blockquote>
ひとまずこのやりかたをキープします。<br/>
ではあとは$this->response->body()に画像のデータを乗せればいいはずです。
<a href="http://docs.fuelphp.com/classes/file/usage.html#/method_read" target="_blank">File::read();</a>あたりが使えそうですね。
<blockquote>Reads a file and returns it ($as_string == true) or adds it to the output ($as_string == false).</blockquote>
ということは、File::read($filename);としてしまうとその場でバイナリデータをぶちまけてしまうので、
<blockquote>$body = \File::read($filename, true);</blockquote>
とすることになります。<br/>
<br/>
これまでの記述をまとめるとこういうことになるかと思います。
<blockquote>$file = \File::read($filename_full, true);
$this->response->set_header('Content-Type','image/jpeg');
$this->response->body($file);
return $this->response;</blockquote>
<br/>
これでサクっと画像が表示されました。<br/>
<br/>
試してはいませんが、$this->response->set_header()にimage/jpeg以外のContent-typeを入れたり、Content-Disposition: attachmentあたりを追加して強制DLさせたりとすれば、ファイル出力全般に同じ方法がとれるだろうと思います。

-->]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/509/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>削除記事（1/30）</title>
		<link>http://lab.flama.co.jp/archives/488</link>
		<comments>http://lab.flama.co.jp/archives/488#comments</comments>
		<pubDate>Mon, 23 Jan 2012 19:01:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[FuelPHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[実験・検証]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=488</guid>
		<description><![CDATA[ごめんなさい！ 記事の内容が正しくない可能性を発見したため、いったん削除します。 この記事のタイトルは「FuelPHPでDBトランザクションを使う方法（複数DB編）」でした。]]></description>
			<content:encoded><![CDATA[ごめんなさい！<br/>
記事の内容が正しくない可能性を発見したため、いったん削除します。<br/>

この記事のタイトルは「FuelPHPでDBトランザクションを使う方法（複数DB編）」でした。

<!--
ということで、<a href="http://lab.flama.co.jp/archives/472" title="FuelPHPでDBトランザクションを使う方法（1DB編）">前回</a>わかったことをベースに、複数DBに対応させてみます。<br/>
ここでは「複数DB」という語を、参照元と書き込み先（つまりSELECTを投げるサーバとUPDATE/INSERT/DELETEを投げるサーバが）別、というざっくりとした意味合いで使います。<br/>
<br/>
さて、前回書いた最終版はこれです。
<blockquote>DB::start_transaction();
try{
	DB::update('testtable')
		->set(array('columnbody' => 'hogehoge'))
		->where('columnid','=',1)
		->execute();
	DB::update('testtable')
		->set(array('columnbody' => 'mogemoge'))
		->where('columnid','=',2)
		->execute();
	DB::commit_transaction();
}catch(\Database_Exception $e){
	DB::rollback_transaction();
}</blockquote>
<br/>
さて複数DBですが、ドキュメントを見るとこういう設定例があります。<br/>
<a href="http://docs.fuelphp.com/classes/database/introduction.html" target="_blank">http://docs.fuelphp.com/classes/database/introduction.html</a><br/>
DBの設定が複数積めるということは、おそらく都度設定を切り替えて使えるはずです。<br/>
<br/>
やり方がわからないので、またしてもソースを見てみることにします。<br/>
構造上、ほぼ間違いなく core/classes/db.php だろうとは見当がつきますが、DBクラスには初期化メソッドが無いようなので、
<blockquote>$db=new DB('db1');</blockquote>
のような書き方はできそうにありません。一応、
<blockquote>$db=new DB();</blockquote>
はできるんですが、やっぱり$dbは空です。これ以降のどこかのタイミングで初期化されるのでしょう。今回は追いません。<br/>
<br/>
さてDBクラスを見ていたところ、start_transactionメソッドを発見。
<blockquote>	/**
	 * Begins a transaction on instance
	 *
	 *     DB::start_transaction();
	 *
	 * @param   string  db connection
	 * @return  bool
	 */
	public static function start_transaction($db = null)
	{
		return \Database_Connection::instance($db)->start_transaction();
	}</blockquote>
実体はDatabase_Connectionクラスのようです。<br/>
しかも引数の$dbが猛烈に怪しいです。DBのリソースIDかと思いきや「String」ということなので。<br/>
<br/>
ということで core/classes/database/connection.phpを見てみます。<br/>
instanceメソッドを見ると、
<blockquote>	/**
	 * Get a singleton Database instance. If configuration is not specified,
	 * it will be loaded from the database configuration file using the same
	 * group as the name.
	 *
	 *     // Load the default database
	 *     $db = static::instance();
	 *
	 *     // Create a custom configured instance
	 *     $db = static::instance('custom', $config);
	 *
	 * @param   string   instance name
	 * @param   array    configuration parameters
	 * @return  Database_Connection
	 */
	public static function instance($name = null, array $config = null)
	{
		\Config::load('db', true);
		if ($name === null)
		{
			// Use the default instance name
			$name = \Config::get('db.active');
		}
		if ( ! isset(static::$instances[$name]))
		{
			if ($config === null)
			{
				// Load the configuration for this database
				$config = \Config::get("db.{$name}");
			}
（以下略）</blockquote>
ということなので、つまり、DB::start_transaction($db);とDatabase_Connection::instance($db);の$dbは、config/db.phpの設定名（＝連想配列のキー）だということになります。<br/>
また、同様に設定が切り替えられる個所をさがしてみたところ、core/database/query.php 内でexecuteメソッドについても引数でDB設定が指定できることがわかりました。こんな感じに書かれています。
<blockquote>	/**
	 * Execute the current query on the given database.
	 *
	 * @param   mixed    Database instance or name of instance
（以下略）</blockquote>
これで、単発のSQL、トランザクションともに接続先を切り替えられることが確かになりました。<br/>
<br/>
では設定ファイル（config/db.php）をこんな感じに書いてみます。<br/>
（２つ設定を作った、ということ以外は適当な設定です）
<blockquote>return array(
'active' => 'read',
'read' => array(
    'type'           => 'mysqli',
    'connection'     => array(
        'hostname'       => 'localhost',
        'port'           => '3306',
        'database'       => 'readdb',
        'username'       => 'reader',
        'password'       => 'password_reader',
        'persistent'     => false,
    ),
    'table_prefix'   => '',
    'charset'        => 'utf8',
    'caching'        => false,
    'profiling'      => false,
),
'write' => array(
    'type'           => 'mysqli',
    'connection'     => array(
        'hostname'       => 'localhost',
        'port'           => '3306',
        'database'       => 'writedb',
        'username'       => 'writer',
        'password'       => 'password_writer',
        'persistent'     => false,
    ),
    'table_prefix'   => '',
    'charset'        => 'utf8',
    'caching'        => false,
    'profiling'      => false,
),
);</blockquote>
readdbとwritedbの内容は全く同じく
<blockquote>CREATE TABLE `testtable` (
  `columnid` int(11) NOT NULL,
  `columnbody` varchar(255) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `testtable` (`columnid`, `columnbody`) VALUES(1, 'lolololololol');
INSERT INTO `testtable` (`columnid`, `columnbody`) VALUES(2, 'wtfwtfwtfwtf');</blockquote>
という中身だとします。<br/>
<br/>
以上総合すると、冒頭のコードは次のように書くことができます。
<blockquote>DB::start_transaction('write');
try{
	DB::update('testtable')
		->set(array('columnbody' => 'hogehoge'))
		->where('columnid','=',1)
		->execute('write');
	DB::update('testtable')
		->set(array('columnbody' => 'mogemoge'))
		->where('columnid','=',2)
		->execute('write');
	DB::commit_transaction();
}catch(\Database_Exception $e){
	DB::rollback_transaction('write');
}
// "read"はactiveに設定されているのでexecuteの引数が無ければ"read"になる
$result1= DB::select()
		->from('testtable')
		->execute();
print 'readdb:'.PHP_EOL;
var_dump($result1->as_array());
//Commitが反映されたのがreadではなくwriteであることを確認
$result2= DB::select()
		->from('testtable')
		->execute('write');
print 'writedb:'.PHP_EOL;
var_dump($result2->as_array());
</blockquote>
この実行結果は次のようになります。
<blockquote>readdb:
array(2) {
  [0]=>
  array(2) {
    ["columnid"]=>
    string(1) "1"
    ["columnbody"]=>
    string(13) "lolololololol"
  }
  [1]=>
  array(2) {
    ["columnid"]=>
    string(1) "2"
    ["columnbody"]=>
    string(12) "wtfwtfwtfwtf"
  }
}
writedb:
array(2) {
  [0]=>
  array(2) {
    ["columnid"]=>
    string(1) "1"
    ["columnbody"]=>
    string(8) "hogehoge"
  }
  [1]=>
  array(2) {
    ["columnid"]=>
    string(1) "2"
    ["columnbody"]=>
    string(8) "mogemoge"
  }
}</blockquote>

結果としてはOKなんですが、なんだかDB::がゲシュタルト崩壊を起こしかけています。<br/>
もうちょっとすっきりできないものでしょうか？<br/>
実は、Database_Connection::instanceの返り値として
<blockquote>@return  Database_Connection</blockquote>
とコードヘッダには書いてあるんですが、実際のコードには
<blockquote>return static::$instances[$name];</blockquote>
となっていました。ということは、
<blockquote>$db = \Database_Connection::instance('write');
$db->start_transaction();
〜</blockquote>
と書けます。<br/>
DB::updateについては継承関係の問題で
<blockquote>$db = \Database_Connection::instance('write');
$db->start_transaction();
try{
	$db->update('testtable')
		->set(array('columnbody' => 'hogehoge'))
		->where('columnid','=',1)
		->execute();
〜</blockquote>
とは書けないようですね。ただし別途
<blockquote>$update = new DB();
$update->update('testtable')
		->set(array('columnbody' => 'hogehoge'))
		->where('columnid','=',1)
		->execute();
〜</blockquote>
とすることはできるようです。今回はやりません。<br/>
<br/>
ということで、最終的なコードは次のようになります（結果確認部分は削除）。
<blockquote>$db = \Database_Connection::instance('write');
$db->start_transaction();
try{
	DB::update('testtable')
		->set(array('columnbody' => 'hogehoge'))
		->where('columnid','=',1)
		->execute('write');
	DB::update('testtable')
		->set(array('columnbody' => 'mogemoge'))
		->where('columnid','=',2)
		->execute('write');
	$db->commit_transaction();
}catch(\Database_Exception $e){
	$db->rollback_transaction('write');
}</blockquote>
<br/>
めでたしめでたし。
-->]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/488/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>削除記事（1/30）</title>
		<link>http://lab.flama.co.jp/archives/472</link>
		<comments>http://lab.flama.co.jp/archives/472#comments</comments>
		<pubDate>Mon, 23 Jan 2012 15:35:06 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[FuelPHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[実験・検証]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=472</guid>
		<description><![CDATA[ごめんなさい！ 記事の内容が正しくない可能性を発見したため、いったん削除します。 この記事のタイトルは「FuelPHPでDBトランザクションを使う方法（1DB編）」でした。]]></description>
			<content:encoded><![CDATA[ごめんなさい！<br/>
記事の内容が正しくない可能性を発見したため、いったん削除します。<br/>
<br/>
この記事のタイトルは「FuelPHPでDBトランザクションを使う方法（1DB編）」でした。<br/>
<br/>
<!--
情報が無ければソースを見ればいいじゃない。<br/>
<br/>
まずテスト用のデータはこういう中身だとします。（適当です）
<blockquote>CREATE TABLE `testtable` (
  `columnid` int(11) NOT NULL,
  `columnbody` varchar(255) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `testtable` (`columnid`, `columnbody`) VALUES(1, 'lolololololol');
INSERT INTO `testtable` (`columnid`, `columnbody`) VALUES(2, 'wtfwtfwtfwtf');</blockquote>
<br/>
このテーブルに対するUPDATEにトランザクションを使います。<br/>
とりあえずマニュアル通りに書いてみます。
<blockquote>DB::start_transaction();
DB::update('testtable')->set(array('columnbody' => 'hogehoge'))->where('columnid','=',1)->execute();
DB::update('testtable')->set(array('columnbody' => 'mogemoge'))->where('columnid','=',2)->execute();
DB::rollback_transaction();
//結果を見る
$result= DB::select()->from('testtable')->execute();
var_dump($result->as_array());</blockquote>
<br/>
実行すると、UPDATEが2本ともRollbackされるので、<br/>
<blockquote>array(2) {
  [0]=>
  array(2) {
    ["columnid"]=>
    string(1) "1"
    ["columnbody"]=>
    string(13) "lolololololol"
  }
  [1]=>
  array(2) {
    ["columnid"]=>
    string(1) "2"
    ["columnbody"]=>
    string(12) "wtfwtfwtfwtf"
  }
}</blockquote>
という結果になります。ちゃんとRollbackされていますね。<br/>
ということなので、もちろんDB::rollback_transaction();をDB::commit_transaction();に書き換えればCommitされます。
<blockquote>DB::start_transaction();
DB::update('testtable')->set(array('columnbody' => 'hogehoge'))->where('columnid','=',1)->execute();
DB::update('testtable')->set(array('columnbody' => 'mogemoge'))->where('columnid','=',2)->execute();
DB::commit_transaction();
$result= DB::select()->from('testtable')->execute();
var_dump($result->as_array());</blockquote>
結果は
<blockquote>array(2) {
  [0]=>
  array(2) {
    ["columnid"]=>
    string(1) "1"
    ["columnbody"]=>
    string(8) "hogehoge"
  }
  [1]=>
  array(2) {
    ["columnid"]=>
    string(1) "2"
    ["columnbody"]=>
    string(8) "mogemoge"
  }
}</blockquote>
となります。<br/>
<br/>
しかしこれで終了にはできません…。<br/>
そもそもなんでトランザクションを使うか、というお話がありまして、Rollbackが必要ということは複数実行されるSQLのどこか途中でエラーが起きた場合ということですから、エラーを検知してCommitを実行するかRollbackを実行するか、分岐させなくてはならないわけです。<br/>
<br/>
とりあえず、わざとSQLエラーを発生させてみましょう。
<blockquote>//正：columnbody／誤：columnbodydydydydy
DB::update('testtable')->set(array('columnbodydydydydy' => 'hogehoge'))->where('columnid','=',1)->execute();</blockquote>
こんな画面が出たはずです。
<img src="http://lab.flama.co.jp/wp-content/uploads/2012/01/fueltest.jpg" alt="" title="fueltest" width="480" height="278" class="alignnone size-full wp-image-474" />
「Database_Exception」と書いてあるということは、つまりExceptionが発生するのでそれを捕らえればいいというわけですね。<br/>
PHPにおいてExceptionをつかまえる方法は、<a href="http://php.net/manual/ja/language.exceptions.php" target="_blank">try〜catch文</a>です。<br/>
今回の場合はDatabase_Exceptionをcatchするように書けばいいはず。<br/>
では上のエラーを発生させる部分を書き直してみます。
<blockquote>try{
DB::update('testtable')->set(array('columnbodydydydydy' => 'hogehoge'))->where('columnid','=',1)->execute();
}catch(Database_Exception $e){
//とりあえずcatchされたかどうかだけ確かめたい
var_dump('Error!');
}</blockquote>
しかし、これではcatchできません。全く同じエラーが表示されます。<br/>
よく見ると、エラー画面には「Fuel\Core\Database_Exception」と書かれていますね。<br/>
なるほど。Namespaceがからんできますか。そういえばそんなことがドキュメントにも書いてありましたね。<br/>
ということで、
<blockquote>try{
DB::update('testtable')->set(array('columnbodydydydydy' => 'hogehoge'))->where('columnid','=',1)->execute();
}catch(\Database_Exception $e){
//前回はDatabase_Exceptionの前にバックスラッシュが無かった
var_dump('Error!');
}</blockquote>
としてみましょう。
<blockquote>string(6) "Error!"</blockquote>
はい、成功です。<br/>
ということで、トランザクション部分を加えた全文を書き直します。
<blockquote>DB::start_transaction();
try{
DB::update('testtable')->set(array('columnbody' => 'hogehoge'))->where('columnid','=',1)->execute();
DB::update('testtable')->set(array('columnbody' => 'mogemoge'))->where('columnid','=',2)->execute();
DB::commit_transaction();
}catch(\Database_Exception $e){
DB::rollback_transaction();
}
$result= DB::select()->from('testtable')->execute();
print '1:'.PHP_EOL;
var_dump($result->as_array());
DB::start_transaction();
try{
DB::update('testtable')->set(array('columnbody' => 'lolololololol'))->where('columnid','=',1)->execute();
DB::update('testtable')->set(array('columnbodydydydydy' => 'wtfwtfwtfwtf'))->where('columnid','=',2)->execute();
DB::commit_transaction();
}catch(\Fuel\Core\Database_Exception $e){
DB::rollback_transaction();
}
$result= DB::select()->from('testtable')->execute();
print '2:'.PHP_EOL;
var_dump($result->as_array());</blockquote>
結果はこうなります。
<blockquote>1:
array(2) {
  [0]=>
  array(2) {
    ["columnid"]=>
    string(1) "1"
    ["columnbody"]=>
    string(8) "hogehoge"
  }
  [1]=>
  array(2) {
    ["columnid"]=>
    string(1) "2"
    ["columnbody"]=>
    string(8) "mogemoge"
  }
}
2:
array(2) {
  [0]=>
  array(2) {
    ["columnid"]=>
    string(1) "1"
    ["columnbody"]=>
    string(8) "hogehoge"
  }
  [1]=>
  array(2) {
    ["columnid"]=>
    string(1) "2"
    ["columnbody"]=>
    string(8) "mogemoge"
  }
}</blockquote>
1回目には問題なくCommitされ、それぞれhogehoge・mogemogeに変更されていますが、2回目は前半のUPDATE文の中で、テーブル名がcolumnbodydydydydyになっているため、SQLエラー→Database_Exception発生→catchされてRollback→2つともUPDATE取り消しということになっていると思います。<br/>
めでたしめでたし。<br/>
<br/>
…にはならなくて、実は複数DB（読み書き分離とか…）構成にしている場合には、これではできないわけなんですね。<br/>
ということでこの後の<br/>
<a href="http://lab.flama.co.jp/archives/488" title="FuelPHPでDBトランザクションを使う方法（複数DB編）">FuelPHPでDBトランザクションを使う方法（複数DB編）</a>へ続きます。<br/>
<br/>
<br/>
余談：
<blockquote>}catch(\Database_Exception $e){</blockquote>
と毎回バックスラッシュ書かなくても、Autoloader使ったり、Classの冒頭で
<blockquote>use \Database_Exception;</blockquote>
したり省略する手段はありますね。<br/>
<br/>
<br/>
-->]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/472/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>立場と義務</title>
		<link>http://lab.flama.co.jp/archives/460</link>
		<comments>http://lab.flama.co.jp/archives/460#comments</comments>
		<pubDate>Sun, 08 Jan 2012 10:09:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[よのなか]]></category>
		<category><![CDATA[情報技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=460</guid>
		<description><![CDATA[我々の社会には法律があります。当たり前です。 自分が知らない法律によって逮捕された場合に、知らなかったことを理由にそれを拒否することができるでしょうか？ もちろん、逮捕の不当性を後から争うことはできます。が、それにしても [...]]]></description>
			<content:encoded><![CDATA[<p>我々の社会には法律があります。当たり前です。<br />
自分が知らない法律によって逮捕された場合に、知らなかったことを理由にそれを拒否することができるでしょうか？<br />
もちろん、逮捕の不当性を後から争うことはできます。が、それにしても「知らなかった」という主張は通るはずがありません。「法の周知が怠られていた」とでも主張しない限り。<br />
もしくは、罰則の無い法律だった場合に、行政指導等が出され、ニュースで取り上げられるなどして実質的なペナルティを受ける場合もあります。<br />
これらは全て、我々の社会で日々起きている当たり前の出来事です。</p>
<p>一方で、我々が知らない法律も多々あります。<br />
通常、自分が直接関係していない業（おもに商売）に関わる法律は、ほとんど知ることがありません。<br />
たとえば、飲食店を経営している人は食品衛生法について知っているでしょうが、私は飲食店で働いたことがないので、その中身をほとんど知りません。<br />
そして、私がお店の人にならない限り、知っている必要はありません。</p>
<p>では飲食店の店員さんが全員、食品衛生法を知っている必要はあるでしょうか？<br />
もちろん、「必ずしも必要ない」ということになります。<br />
・許可／資格を得た人間がいること<br />
・その人間が食品衛生法を知っていること<br />
・設備やその他の従業員に対して食品衛生法に基づいて適切な指導を行なうこと<br />
という前提によって、事業所と従業員全体が合法となるためです。<br />
つまり、誰かが知っており、その人間の影響下にある者は全て「知っていてやっている」状態である、というのが前提になっているわけです。</p>
<p>さて、ようやくここでタイトルのデザイン・プログラムについての話題になります。<br />
Webデザイナーは、自分や自分のプロダクトが影響を受ける法律を知っているでしょうか？</p>
<p>例を挙げると、どのようなデザインであれ「日本赤十字もしくはその許可を得た者」を表す以外の目的で、「白地に赤十字のマーク」を使用できません。<br />
病院や薬局、「ヘルプ」を表すアイコンなどとして使用することはできないわけです。<br />
これは「赤十字使用法（赤十字の標章及び名称等の使用の制限に関する法律）」に定められており、ジュネーブ条約に基づいています。<br />
日本赤十字社もたびたび<a href="http://www.shikoku-np.co.jp/national/medical_health/20080502000322" target="_blank">違法であることを呼びかけ</a>ています。</p>
<p>経験上、この問いかけに対するレスポンスはだいたい次のようものに分かれます。</p>
<p>１）「知らなかった」「俺そういうのわからない」「俺は判断できない」<br />
冒頭でも挙げましたが、その言い訳は通用しません。<br />
「ある立場にはそれに応じた義務が付随する」という、非常に一般的な話だからです。<br />
その立場に居続けたいのであれば義務を果たす、嫌であれば辞める、どちらかしかありません。</p>
<p>２）「これはこういう意図の広告表現なので違法とかそういうのとは違う」<br />
広告業界団体のガイドラインにも「関連法規を遵守しなくてはならない」ということは当たり前のように書かれています。なぜ書かれているかを説明する必要はないでしょう。<br />
意図が最重要なのは意図する人の頭の中だけであって、世に出る場合には世の中の優先順位に組み込まれるのが当たり前です。</p>
<p>３）「お客さんがこれにしろと譲らないので〜」<br />
「赤十字使用法」にせよ業界団体ガイドラインにせよ、罰則はありません。<br />
最終的には、違法なプロダクトをリリースすることをOKした人の責任です。その責任を負うのがその立場にある人の義務です。<br />
もちろん、ほとんどの場合には、そのような判断がされることは無いでしょう。<br />
が、実際には「なんか下っ端がうるせえことを言ってるんだけど黙ってさっさと作らせろよ」ということを言う人もいるので、「知っていながら世に出る」ということもあります。</p>
<p>３’）「お金をもらってる側だからしょうがない」<br />
実際には、この件が問題になった場合、高確率で「作った側」が責任を問われます。<br />
なぜならば、このような関係では多くの場合、「作った側」がその違法性を伝えた証拠が無いためです。</p>
<p>４）「そういうことはお客さんに言いづらいので〜」<br />
意識する／せざるにかかわらず、「何かあった場合には自分が全ての責任を負う」のを認めることとイコールになるのです。それは言ってしまえば「自分の社会的立場を賭けて違法行為の責任を負う」ということです。負えますかね？</p>
<p>５）「人命にかかわることでもなし、そこまでやらなくても〜」<br />
だからこそ、あえて「赤十字使用法」を例に出したわけです。</p>
<p>だからこそ我々は、言うべきこと・残すべき記録・決まらないと先へ進ませないということをウザがられながらもやるわけです。<br />
もちろん、責任問題はお金の問題だというのもあります。<br />
「日本は訴訟社会じゃないから〜」という人も多くて驚きますが、平成22年の簡易裁判所での民事訴訟件数は130万件強あります。1年間の出生数（100万人強）より多い数です。<br />
これもまた「知らない」だけで、実際には日本でも訴訟はポピュラーな出来事です。</p>
<p>最後に個人的な思いですが、誰もが「知らない」「わからない」「俺じゃない」「言えない」と言いながらそれぞれの立場に居ようとする、そんな社会は、めぐりめぐって自分の命にもかかわりかねません。<br />
これはモラルの問題ではないのです。理想を語っているのでもありません。<br />
2011年に我々が見たものは、そういうものではありませんでしたか？</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/460/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeIgniterで動的にModelを読み込む方法</title>
		<link>http://lab.flama.co.jp/archives/444</link>
		<comments>http://lab.flama.co.jp/archives/444#comments</comments>
		<pubDate>Thu, 29 Dec 2011 03:31:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=444</guid>
		<description><![CDATA[CodeIgniterでは、Controller内で $this->load->model('Sample'); とすると、application/models/sample.phpに記述した"Sample"クラスが読み [...]]]></description>
			<content:encoded><![CDATA[CodeIgniterでは、Controller内で
<blockquote>$this->load->model('Sample');</blockquote>
とすると、application/models/sample.phpに記述した"Sample"クラスが読み込まれます。
Sampleクラス内のメソッドをController内で実行させる場合、
<blockquote>$this->Sample->function();</blockquote>
と記述します。<br/>
<br/>
通常はこれだけで問題がないわけですが、では例えば次のような条件を全て満たす仕組みはどのようにして実現するのでしょうか？<br/>
<ul>
<li>Controller内のパラメータで読み込むModelを切り替える</li>
<li>Controller内にはModel名をハードコードしない</li>
<li>Modelはapplication/modelsディレクトリ内に設置したファイルにのみ記述する</li>
</ul>
<br/>
対象のModel名が動的に切り替わるということは、上記例のように"Sample"を静的に記述できないということになります。Modelの呼び出しについては
<blockquote>$modelname='Hogehoge';
$this->load->model($modelname);</blockquote>
とすることができます。<br/>
しかし、このままではメソッドの呼び出しができません。<br/>
<br/>
このような場合に、非常に単純な解決策があります。<br/>
ユーザーガイドの「Models」＞「Loading a Model」に、このような例が紹介されています。<br/>
<a href="http://codeigniter.com/user_guide/general/models.html#loading">http://codeigniter.com/user_guide/general/models.html</a>
<blockquote>$this->load->model('Model_name', 'fubar');
$this->fubar->function();</blockquote>
<br/>
第2引数を渡すと、その文字列をモデル名として使用できるのでした。<br/>
この例だけ見るとモデルをリネームする機能のようにしか見えないわけですが、この方法を先ほどの例とミックスさせると、第1引数を動的に渡しても第2引数のクラス名で固定できるのです。
<blockquote>$modelname='Hogehoge';
$this->load->model($modelname, 'fubar');
$this->fubar->function();
</blockquote>
<br/>
と、この方法で、Modelは動的に（ファイルごと）切り替えることが可能となります。
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/444/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>二葉亭四迷は「I love you.」を「死んでもいいわ」と訳したか？（あるいはTwitterで広まる都市伝説）</title>
		<link>http://lab.flama.co.jp/archives/398</link>
		<comments>http://lab.flama.co.jp/archives/398#comments</comments>
		<pubDate>Mon, 14 Nov 2011 04:52:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[情報技術]]></category>
		<category><![CDATA[都市伝説]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=398</guid>
		<description><![CDATA[二葉亭四迷は「I love you.」を「死んでもいいわ」と訳したのか？検証してみました。]]></description>
			<content:encoded><![CDATA[<p>直接技術ネタというわけではないんですが、情報技術ネタということで…。</p>
<p>ちょっと前から見かけるようになった話がありまして、</p>
<blockquote><p>夏目漱石は“I love you.”を「月が綺麗ですね」と訳した。二葉亭四迷は「死んでもいいわ」と訳した。</p></blockquote>
<p>というものです。</p>
<p>夏目漱石の話はこれ有名でして、昔から国文学専攻の人だったら必ず聞くんじゃないでしょうか。学生時代、私も国文学科の知りあいから聞いて、さすが文豪！と感動したものです。<br />
ただし英語教師時代のエピソードということで、本当にあった話かどうかわからないとされていますが。</p>
<p>さて、問題は二葉亭四迷の件です。<br />
夏目漱石とはほぼ同世代の人ですし、ここまで対比されて広まるからには、昔から有名であってしかるべきだと思うのですが、聞いたことがなかったのです。</p>
<p>なぜ突然この話を目にするようになったかというとこれは結構明らかで、Twitterで繰り返しつぶやかれているからです。<br />
<a href="http://twitter.com/#!/search/%E6%AD%BB%E3%82%93%E3%81%A7%E3%82%82%E3%81%84%E3%81%84%E3%82%8F" target="_blank">http://twitter.com/#!/search/%E6%AD%BB%E3%82%93%E3%81%A7%E3%82%82%E3%81%84%E3%81%84%E3%82%8F</a></p>
<p>では最近になって誰かが何かに書いたとか発言したとか、そういうことでもあったんでしょうか？<br />
ググってみると、「〜らしい」「〜んだって」と、伝聞が多いですね。</p>
<p>ここでネガティブな発想に襲われたのです。これ、本当なのかな？と。</p>
<p>かろうじて出典を挙げている人が発見できました。ツルゲーネフの「片恋」だそうです。<br />
ほほう。それではと思ってAmazonで探してみたことろ、二葉亭四迷訳本は1955年の岩波文庫を最後に絶版になっているのです。そりゃ伝聞にもなります。探せばあるかもしれませんが。</p>
<p>ここでさらにネガティブな発想に襲われました。これって都市伝説じゃないのかな？と。</p>
<p>この時代の文献は国立国会図書館の「<a href="http://kindai.ndl.go.jp/" target="_blank">近代デジタルライブラリー</a>」で見ることができます。<br />
問題の個所は第16章、明治29年の版だとp.103、大正5年の版だとp.100です。</p>
<blockquote><p>（略）私は何も彼も忘れて了って、握ってゐた手を引寄せると、手は素直に引寄せられる、それに随れて身躰も寄添ふ、シヨールは肩を滑落ちて、首はそつと私の胸元へ、炎えるばかりに熱くなつた唇の先へ來る…<br />
「死んでも可いわ…」とアーシヤは云つたが、聞取れるか聞取れぬ程の小聲であつた。<br />
私はあはやアーシヤを抱うとしたが…ふとガギンの事を憶出すと（略）</p></blockquote>
<p>あったじゃないか！やっぱり都市伝説なんかじゃなかったんだね！と一瞬思ったのですが、そこまで素直にはなれないわけでして。</p>
<p>ではこの「死んでも可いわ…」の原文は本当に「I love you.」もしくはロシア語で「Я люблю тебя」なのか？というわけです。</p>
<p>ではまず英語版をあたってみましょう。<br />
<a href="http://www.ibiblio.org/eldritch/ist/lear.htm#acia" target="_blank">http://www.ibiblio.org/eldritch/ist/lear.htm#acia</a><br />
（英語版は“Asya”というタイトルになっているはずなんですがこの版はなぜか“Acia”になっています）<br />
場所（章番号）がわかっているので比較的早く見つかりますね。<br />
上に挙げた個所の英語訳はこうなっています。</p>
<blockquote><p> I forgot everything, I drew her to me, her hand yielded unresistingly, her whole body followed her hand, the shawl fell from her shoulders, and her head lay softly on my breast, lay under my burning lips. . . .<br />
&#8220;Yours&#8221;. . . she murmured, hardly above a breath.<br />
My arms were slipping round her waist. But suddenly the thought of Gagin flashed like lightning before me. </p></blockquote>
<p>ふむ。「&#8221;Yours&#8221;&#8230;」ですね。</p>
<p>ではがんばってロシア語版をあたってみます。<br />
<a href="http://ilibrary.ru/text/1097/p.16/index.html" target="_blank">http://ilibrary.ru/text/1097/p.16/index.html</a><br />
これはなかなか難題ですが、章番号があるのでかろうじて可能です。<br />
章の頭からの段落数と、会話文の形式から判断すると、おそらくこの個所だろうと思われます。</p>
<blockquote><p>— Ваша&#8230; — прошептала она едва слышно.</p></blockquote>
<p>「Ваша&#8230;」を翻訳してみると、「あなたの…」となります。<br />
<a href="http://translate.google.co.jp/#ru|ja|%D0%92%D0%B0%D1%88%D0%B0..." target="_blank">http://translate.google.co.jp/#ru|ja|%D0%92%D0%B0%D1%88%D0%B0&#8230;</a><br />
となるとこれはもう明らかで、英語版の「&#8221;Yours&#8230;&#8221;」はほぼロシア語の直訳だということがわかります。</p>
<p>さて、結論です。<br />
「二葉亭四迷は“I love you.”を『死んでもいいわ』と訳したか？」<br />
答えは、（ツルゲーネフの「片恋」では）Noでした。<br />
しかし、この文脈で、直訳すれば「あなたの…」となるところを、「死んでも可いわ…」と訳した二葉亭四迷はやはりすばらしいことに間違いありません。</p>
<p>……ただおそらく、当時二葉亭四迷がこのセリフで意図し、読者が感じ取っただろうイメージは、「君のためなら死ねる」とか「死ぬほど好き」とかではなく、「心中」なんでしょうね。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/398/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPの日本語変数名と文字コード</title>
		<link>http://lab.flama.co.jp/archives/355</link>
		<comments>http://lab.flama.co.jp/archives/355#comments</comments>
		<pubDate>Wed, 05 Oct 2011 14:42:04 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=355</guid>
		<description><![CDATA[冒頭で宣言しますが、今回のネタはあくまでPHPの仕様に対する実験であり、実際に使っちゃうと脆弱性を盛り込んでしまうネタなので、充分ご注意ください。 PHPの変数・配列のキーには2バイト文字が使えます。 もちろん仕様上「使 [...]]]></description>
			<content:encoded><![CDATA[冒頭で宣言しますが、今回のネタはあくまでPHPの仕様に対する実験であり、実際に使っちゃうと脆弱性を盛り込んでしまうネタなので、充分ご注意ください。<br/>
<br/>
PHPの変数・配列のキーには2バイト文字が使えます。<br/>
もちろん仕様上「使えることになっている」ということではなく、結果的に使えることになったというのが正しい言い方かもしれません。<br/>
<a href="http://php.net/manual/ja/language.variables.basics.php" target="_blank">PHPリファレンス：基本的な事</a><br/>
<br/>
使う意味があるか、と問われれば、ありません。<br/>
では、あえて使う意味が発生するとしたらどのようなシチュエーションか、考えてみます。<br/>
<br/>
たとえば以下のような場合。<br/>
<br/>
<blockquote>好きな果物：
&lt;input type="checkbox" name="data[fruits][]" value="1"/>りんご
&lt;input type="checkbox" name="data[fruits][]" value="2"/>バナナ
&lt;input type="checkbox" name="data[fruits][]" value="3"/>パイナップル</blockquote>
というようなパラメータをPOSTした場合、受け取るPHP側では
<blockquote>$_POST['data']['fruits']</blockquote>
という配列に入ります。<br/>
このようなFormのお約束として、「入力内容の確認画面」があったり、保存したデータを（人間の目にとってわかりやすく）見る、という用途があります。<br/>
どこかに「'fruits'は'好きな果物'」「data[fruits][]==1であれば'リンゴ'」というような対照表を持っておく）のが正しいお作法なわけですが、配列のキーに2バイト文字が使えるということであれば、たとえばこのような書き方ができるわけです。
<blockquote>&lt;input type="checkbox" name="data[好きな果物][]" value="リンゴ"/>リンゴ
&lt;input type="checkbox" name="data[好きな果物][]" value="バナナ"/>バナナ
&lt;input type="checkbox" name="data[好きな果物][]" value="パイナップル"/>パイナップル</blockquote>
（こう書いちゃえOKということではありませんので重ねて念のため）<br/>
<br/>
この方法で、HTML側とPHP側の文字コードがUTF-8で一致していれば、POST後、foreachなどでkeyとvalueの両方を2バイト文字列としていきなり使えます。<br/>
しかし逆に、入力される文字コードを変換する必要がある場合には、いちいちキーを取り出して変換する処理を書く必要があります。「変数の中身」の文字コードを変換するには<a href="http://www.php.net/manual/ja/function.mb-convert-variables.php" target="_blank">mb_convert_variables</a>などを使えば良いですが、「配列のキーを含めて」文字コードを変換する方法が無いためです。<br/>
（力技は思いつかないこともないですけれども…）<br/>
<br/>
さてここまで実験してみて、実はおもしろいことが判明しました。<br/>
配列のキーにSJISを使っていて、PHPがUTF-8である場合、特定の文字でキー文字列がブチ切られるのです。<br/>
どの時点でブチ切られているかというと、これはもう$_POSTに入った時点でそうなっています。まず間違いなく文字化けでしょう。<br>
SJISで文字化けというと、毎度おなじみの0x5c問題です。「ソ能十表予暴貼構…」というアレですね。今回もそんなことだろうと元々の文字を確認してみました。ところが、キー内の文字列は、「希望」「頭脳」「講評」…。全て0x5cではないのです。<br/>
しかし根本的な原因としては変わらないだろう、ということで、SJISの2バイト目に注目してみます。
<blockquote>希望 … 0x8a 0xf3 0x96 0x5d
頭脳 … 0x93 0xaa 0x94 0x5d
講評 … 0x8d 0x75 0x95 0x5d</blockquote>
ビンゴ。全て2バイト目が「0x5d」でした。0x5dは何かというと、「]」です。つまり、配列キー文字列の終端だと認識されてしまっているわけですね。これで、リファレンスに書いてあったちょっと妙な説明が理解できます。<br/>
<a href="http://php.net/manual/ja/language.variables.basics.php" target="_blank">PHPリファレンス：基本的な事</a>
<blockquote>注意: ここで言うところの文字とはa-z、A-Z、127から255まで (0x7f-0xff)のバイトを意味します。</blockquote>
つまり「何入れてもかまわんけど文字コードで扱うからね」ということになるかと思います。意図的に使用された場合はもちろん、今回のように意図せずして使用した場合でも、0x5dに限らず言語構造で使用する文字に合致したら使えないというわけです。<br/>
<br/>
あたりまえだろ、と言われればそれまでなのですが、リファレンスを見ても、「予約語一覧」はあっても「予約文字一覧」は見当たらないので…。（あったらごめんなさい）<br/>
<br/>
ということで、コード中の静的な記述ならまだしも、外部からの入力値などの2バイト文字を変数名や配列キーに使うのはあまり現実的ではない、という結論になるかと思います。<br/>
（まんま脆弱性になりますし）<br/>
<br/>
<br/>
ちなみに、じゃあこの種の文字化けは回避不可能なのかというと、策はあります。
<blockquote>mbstring.http_input=SJIS-win
mbstring.http_output=SJIS-win
mbstring.internal_encoding=UTF-8
mbstring.encoding_translation On</blockquote>
で$_POSTの中身は化けなくなります。ということはつまり、PHPの処理順序は、「POSTされたデータを受け取る→設定に従って文字コードを変換→変数として解釈→変数にセット」ということになっているんだなあ、と改めて思うわけです。よく考えるとそういう順序でないと困るわけですが。<br/>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/355/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Firefox6でLocationヘッダがキャッシュされる？</title>
		<link>http://lab.flama.co.jp/archives/345</link>
		<comments>http://lab.flama.co.jp/archives/345#comments</comments>
		<pubDate>Wed, 28 Sep 2011 18:59:59 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Firefox]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=345</guid>
		<description><![CDATA[ちゃんと検証していないので取り急ぎメモです。 ・URLは/example1/とする（example1.phpをmod_rewriteで書き換え） ・/example1/にアクセスされた場合、Cookieの内容を見て、 　 [...]]]></description>
			<content:encoded><![CDATA[<p>ちゃんと検証していないので取り急ぎメモです。</p>
<p>・URLは/example1/とする（example1.phpをmod_rewriteで書き換え）<br />
・/example1/にアクセスされた場合、Cookieの内容を見て、<br />
　・画面Aを表示する<br />
　・/example2/へリダイレクト<br />
　のどちらかの処理を行なう<br />
・/example2/では画面Bを表示する<br />
・/example2/の画面B内からFormを/example1/へPOSTしCookie発行<br />
・/example1/の画面Cを表示</p>
<p>お察しの通り、よくあるログイン画面です。<br />
ところが/example1/→/example2/に何度かリダイレクトされた後、/example2/の画面Bからログインしようとしたところ、/example2/へリダイレクトしてしまうわけです。</p>
<p>まず始めにCookieが正しく発行されていないことを疑ったわけですが、これはすぐ正常発行が確認できました。</p>
<p>そこで、/example2/→/example1/の処理の冒頭で停止させてCookieの中身を表示させてみよう、と思ったところ、処理が始まる前に/example2/にリダイレクトしてしまうのです。<br />
処理が始まる前ということは、/example1/のプログラム側の問題ではないということになるわけで、mod_rewriteの動きを疑う流れになると思うのですが、RewriteRuleをコメントアウトしてもリダイレクトが収まりません。</p>
<p>さてこれは何だろうと悩んだわけですが、ふと、同じ挙動をChromeで繰り返してみても再現しません。<br />
となるとこれはブラウザの問題である可能性が高くなるわけで、Firefoxのアドオンを全てOffにして、再度やりなおしてみました。が、やはり変化はなく、さて、あと消せるものは何かあったかなと設定パネルを眺めていたところ、そういえばキャッシュは消してなかったなと気付き、全消ししてみたところ、サクっと正常に動作したというわけです。</p>
<p>結果として、FirefoxではLocationヘッダでのリダイレクトについてもキャッシュしている可能性がある（もしくはキャッシュする場合がある可能性がある）ということになると思います。</p>
<p>さて、そもそもLocationヘッダはキャッシュしていいもんなんでしょうか？<br />
原典を見てみましょう。<a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html" target="_blank">RFC 2616</a>です。</p>
<blockquote><p>10.3.2 301 Moved Permanently<br />
The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs.  Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise.<br />
The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).<br />
If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.<br />
Note: When automatically redirecting a POST request after receiving a 301 status code, some existing HTTP/1.0 user agents will erroneously change it into a GET request.</p>
<p>10.3.3 302 Found<br />
The requested resource resides temporarily under a different URI. Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests.  This response is only cacheable if indicated by a Cache-Control or Expires header field.<br />
The temporary URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).</p></blockquote>
<p>これを見ると、<br />
・301：「別のものを指定していない限り」キャッシュ可能<br />
・302：Cache-ControlかExpiresが指定されている場合のみキャッシュ可能<br />
となっています。（「別のもの」って何？）<br />
ということは、301でリダイレクトしたらキャッシュされても文句は言えないわけです。<br />
そもそも「Moved Permanently」なわけですし。</p>
<p>ここで、あー、と思い出しました。<br />
そういえば、何を思ったのか、リダイレクトを301で書いていたのでした…。</p>
<p>ということで、FirefoxはStatus301ヘッダをキャッシュしている可能性があり、かつそれはRFC的には正しい挙動であるということになるかと思います。</p>
<p>自分が悪いからしょうがないというオチなんですが、確かにキャッシュすれば遷移は速くなるというブラウザ側の都合も納得しつつ、これはキャッシュしてほしくないところだなーと…。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/345/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPのechoとprintの違い</title>
		<link>http://lab.flama.co.jp/archives/329</link>
		<comments>http://lab.flama.co.jp/archives/329#comments</comments>
		<pubDate>Sun, 18 Sep 2011 14:19:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=329</guid>
		<description><![CDATA[先に宣言しておきます。今回は駄ネタです。 php echo print 違いと検索してみても、だいたいはリファレンス通りの説明が書いてあります。 「echoとprintってどっち使ったらいいんですか？」と聞かれても、だい [...]]]></description>
			<content:encoded><![CDATA[先に宣言しておきます。今回は駄ネタです。<br/>
<br/>
<a href="http://www.google.co.jp/search?gcx=w&sourceid=chrome&ie=UTF-8&q=php+echo+print+%E9%81%95%E3%81%84" target="_blank">php echo print 違い</a>と検索してみても、だいたいはリファレンス通りの説明が書いてあります。<br/>
「echoとprintってどっち使ったらいいんですか？」と聞かれても、だいたいの人は「好きな方使えば？」と答えるんじゃないでしょうか。<br/>
<br/>
さて今回は結論を先に書きますが、これを問われた時の私の答えは、
「個人的にはprintにしておくことをおすすめします」です。
もちろん好みの問題ではなくて、（異論はあると思いますが）実用的な面での結論です。<br/>
<br/>
まずリファレンスを見てみましょう。<br/>
<br/>
<a href="http://php.net/manual/ja/function.echo.php" target="_blank">echo</a>
<blockquote>echo() は実際には関数ではありません (言語構造です)。</blockquote>
「言語構造である」と書かれても「なんか基本的なところで動くのね」というように見えてしまいますが（そりゃもちろんそうなのですが）、悪い面を言うと「実行結果が根本的なエラーとして扱われる場合がある」ということになります。<br/>
<br/>
では<a href="http://php.net/manual/ja/function.print.php" target="_blank">print</a>はどうかというと、これがまたPHPリファレンスの謎なところで、printの項には無く、echoの項で触れられています。<br/>
<blockquote> (いくつかの他の言語構造と異なり) echo() は関数のように動作しません。</blockquote>
ここで間接的に触れられている「関数のように動作する」言語構造のひとつがprintです。
もちろん関数ではないので通常の関数とは挙動が異なりますが、比較的関数に近い挙動なので、実行結果が関数と同じような結果になったりします。<br/>
<br/>
例を挙げましょう。<br/>
<blockquote>print print "hoge";</blockquote>
これは hoge1 になります。hogeのprintが実行され、かつその返り値(TRUE)がprintされるのでこのような結果になるわけです。<br/>
ところが、<br/>
<blockquote>echo echo "hoge";</blockquote>
これはsyntax errorになります。<br/>
しかも2〜3回食らわすとSegmentation faultが発生して、Webサーバのプロセスが死にます。
わざわざそんなこと書く場面なんて無いよ、とつっこまれると思いますが、コピペミスとか、ボーっとしている時には結構やらかしてしまう部類のものだと思うのです。しかも、少なくともNetBeansではこんなのを書いても警告が出ません。<br/>
<br/>
普通に考えると、いきなりsyntax errorが出て画面が表示されなくなったら（エラーログ見れば行数まで指摘されているわけですが）、びっくりしてソースを見直しますよね？で、こんなのを書くくらいだからボサーっとしている状態なわけです。<br/>
しかもechoなどという基本的な記述に真っ先に疑いをかけることはしないでしょうから、しばらくソースを眺めて時間を無駄にするだろうと思うのです。<br/>
<br/>
これが、画面表示上「hoge1」などとなっていれば、「あれ？Typoしたか？」ということでとりあえずすぐその記述個所を確認すると思うのですね。<br/>
<br/>
ということで、冒頭の結論の意図は、極めて現実的な問題として、「本当の言語的違いはどうでもいいが、ミスった時にわかりづらくなる可能性があるのでechoは使いたくない」という理由によるものです。<br/>
仕様レベルの挙動の違いを把握していても、役に立つのは正直ZendのCertificationくらいじゃないかと思うので、実際の現場で時間を無駄にしないためのルールとして、このような結論に達したわけです。<br/>
まじめな方々には「ちゃんと違いを把握していれば云々〜」と怒られるかもしれませんけれども。<br/>
<br/>
・・・<br/>
<br/>
蛇足ですが、リファレンスのechoとprintの説明はさらに問題があって、「結局()って要るの？要らないの？」という疑問が出てくると思うのです。<br/>
リファレンスではどちらも<br/>
<blockquote>括弧は必要ありません。 </blockquote>
と書いてあるのですが(<a href="#329*1">*1</a>)、これでは「省略可能ということなんだなー」と読めてしまいます。実際には()を付けると動作しない場合があるので、ここでの「必要ありません」は「不要です」という意味なのです。
例えば
<blockquote>void echo ( string $arg1 [, string $... ] )</blockquote>
と書いてあるからといって<br/>
<blockquote>echo("hoge","hoge");</blockquote>
と書くとまたもやsyntax errorになります。<br/>
これは<br/>
<blockquote>echo "hoge","hoge";</blockquote>
と書かないと動作しません。<br/>
ページ内の記述例では一切()を使っていないわけですが、リファレンス内のリンクもecho()・print()と書いてありますし、説明書ややたらたくさんある「PHPの書き方講座」のようなサイトを見るとprint(〜)と書いてあるものも結構あるようですし、長いことPHPを書いている人でも「()って付けた方がいいんじゃないんですか？」と聞かれたらそうそう即答できないんじゃないかなと。「どっちでもOK」と言ってしまいそうですよね。<br/>
<br/>
<br/>
<a name="329*1" id="329*1"></a>
*1<br/>
元の英文に<br/>
<blockquote>you are not required to use parentheses with it.</blockquote>
と書いてあるのでそのまま訳したんだと思いますが、日本語の「必要ない」は「あってもなくても良い」というニュアンスが出てしまうので、ここは「不要」と訳した方が良かったんじゃないかと思うのです。
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/329/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>形態素解析に使う辞書は何が適切なのか？</title>
		<link>http://lab.flama.co.jp/archives/314</link>
		<comments>http://lab.flama.co.jp/archives/314#comments</comments>
		<pubDate>Fri, 26 Aug 2011 19:55:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[実験・検証]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=314</guid>
		<description><![CDATA[久々にMeCabを使おうと思ったんですが、そういえば辞書の違いによる結果の違いはどれくらいあるんだろう？と思い立って検証してみることにしました。 MeCabで一般的に使われる辞書は ・IPA辞書 ・unidic ・NAI [...]]]></description>
			<content:encoded><![CDATA[<p>久々に<a href="http://mecab.sourceforge.net/" target="_blank">MeCab</a>を使おうと思ったんですが、そういえば辞書の違いによる結果の違いはどれくらいあるんだろう？と思い立って検証してみることにしました。</p>
<p>MeCabで一般的に使われる辞書は<br />
・<a href="http://sourceforge.jp/projects/ipadic/" target="_blank">IPA辞書</a><br />
・<a href="http://www.tokuteicorpus.jp/dist/" target="_blank">unidic</a><br />
・<a href="http://sourceforge.jp/projects/naist-jdic/" target="_blank">NAIST辞書</a><br />
の3つです。</p>
<p>解析結果は入力する文章の傾向によってかなり左右されることが過去わかっているので、いくつか文体の異なるテキストを用意して解析させてみました。</p>
<p>１）新聞記事<br />
まず、辞書を作成するために多くの新聞記事が利用されています。よって、新聞記事に近い文体の文章は、どの辞書でもかなり近い結果になります。</p>
<p>２）エンタメ誌記事<br />
ほぼ同じですが、「教科書的でない語」の分解に若干差が見られます。<br />
例：IPA辞書・NAIST辞書「修羅場」unidic「修羅／場」</p>
<p>３）専門誌記事（食品）<br />
一部の語に差が見られます。<br />
例：IPA辞書・NAIST辞書「小麦粉」unidic「小麦／粉」&#8230; IPA辞書・NAIST辞書「乳製品」unidic「乳／製品」<br />
数詞の扱いにも若干差があります。<br />
例：IPA辞書「2011年」unidic・NAIST辞書「2／0／1／1／年」</p>
<p>４）専門誌記事（女性向け商品）<br />
複数の連続するカナの名詞を1語と見なすか否かに差があります。<br />
例：IPA辞書・unidic「ヒロイン／メイク／シリーズ」NAIST辞書「ヒロインメイクシリーズ」 &#8230; IPA辞書・NAIST辞書「アイラッシュカーラー」unidic「アイラッシュ／カーラー」<br />
また該当記事にURLが含まれていたのですが、特にドメイン部分の認識は差があります。<br />
例：IPA辞書「http／://／ameblo／.／jp／/」unidic・NAIST辞書「http／:／/／/／ameblo／.／j／p／/」</p>
<p>５）ブログ記事<br />
主に顔文字の扱いが異なります。<br />
例：IPA辞書「(≧∇≦)」unidic・NAIST辞書「(／≧∇≦)」&#8230; IPA辞書・unidic「(^。^;)」NAIST辞書「(／^／。／^／;／)」</p>
<p>６）企業IR系文書<br />
unidicに分割多めな傾向があります。<br />
例：IPA辞書・NAIST辞書「株式会社」「オンライン」「NTT」unidic「株式／会社」「オン／ライン」「N／T／T」</p>
<p>７）お役所文書（省庁通達）<br />
辞書作成の際に使用されているのかもしれませんが、あまり差がありません。名詞にはほぼ違いが見られませんが、一部いわゆる活用形の分割が異なるようです。<br />
例：IPA辞書・NAIST辞書「主たる」「において」unidic「主／たる」「に／おい／て」</p>
<p>８）英文（若干フォーマルな文書）<br />
いじわるではありますが、日本の伝統芸能について書かれた英文（日本語のローマ字表記が混ざったもの）を分解させてみました。<br />
圧倒的にIPA辞書の精度が高いようです。NAIST辞書は「is」「as」などの短い語を1文字づつに分解する傾向にあるようです。unidic辞書は所々英単語を抽出していますが、抽出される語とされない語の違いが、結果からはよくわかりません。</p>
<p>こうして見てみると、「分解する」という点ではunidicの性能が高いことが分かります。今回の検証ではあまり見られませんでしたが、標記ゆれの許容も幅が広いようですし。<br />
もともと形態素解析エンジンの役割はそれぞれのエンジンの目的・意図に従って「分解する」ことであって、使われる際にどちらが都合が良いかという観点ではないわけです。</p>
<p>しかし、形態素解析を「サクっと走らせてそのまま使いたい」という用途の場合、（特に名詞の場合に）ある語を「別々の語」として認識するか「ひとつの語」として認識するか、ということは、分解後の利用に影響を与えることになります。</p>
<p>今回検証してみた限りでは、IPA辞書がわりと汎用的に「そのまま使う」のに向いているような結果でした。解析させる文章の傾向によっても変わると思うので、どの辞書が適しているか、想定文章をそれぞれ解析させてみて決めるのが良いのではないかと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/314/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon EC2でシステム時刻が変更できない場合</title>
		<link>http://lab.flama.co.jp/archives/311</link>
		<comments>http://lab.flama.co.jp/archives/311#comments</comments>
		<pubDate>Thu, 18 Aug 2011 05:35:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Amazon]]></category>
		<category><![CDATA[CentOS]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=311</guid>
		<description><![CDATA[EC2に限ったことではありませんが、XenではゲストOS（Domain-U）の時刻がホストOS（Domain-0）によって管理されるのがデフォルトのようです。 明らかに時計がズレたゲストOS上でも時刻修正が反映されない  [...]]]></description>
			<content:encoded><![CDATA[<p>EC2に限ったことではありませんが、XenではゲストOS（Domain-U）の時刻がホストOS（Domain-0）によって管理されるのがデフォルトのようです。<br />
明らかに時計がズレたゲストOS上でも時刻修正が反映されない<br />
（ホストOSの時計によってさらに訂正されてしまう）ので、<br />
dateコマンドなどでも時刻が修正されません。</p>
<p>ということで、時計合わせは次の２つの手順で行ないます。<br />
１）ゲストOSの時計をホストOSから独立させる<br />
２）ntpサーバにより外部の時計を参照する</p>
<p>１）</p>
<blockquote><p>echo &#8217;1&#8242;> /proc/sys/xen/independent_wallclock</p></blockquote>
<p>として時計を（ホストOSから）独立させます。<br />
また、再起動後のために/etc/sysctl.confに</p>
<blockquote><p>xen.independent_wallclock = 1</p></blockquote>
<p>と追加しておきます。</p>
<p>２）<br />
物理サーバを使用しているとそれほど大幅に時計がズレることはあまり経験しませんが、<br />
仮想サーバでは、時計がズレやすい傾向があるようなので、<br />
時計を切り離した後は、必ずntpdを設定しておきます。</p>
<blockquote><p>yum install -y ntp<br />
ntpdate -b -u ntp.nict.jp<br />
/etc/init.d/ntpd start<br />
/sbin/chkconfig ntpd on
</p></blockquote>
<p>（/etc/ntpd.confの設定内容については割愛）<br />
同期の状況は</p>
<blockquote><p>ntpq -p</p></blockquote>
<p>でチェックします。</p>
<p>参考：<br />
<a href="https://forums.aws.amazon.com/thread.jspa?threadID=67855" tartget="_blank">https://forums.aws.amazon.com/thread.jspa?threadID=67855</a><br />
「ゲストOSではntpを使わなくていいと思っていたがTokyo Regionで5分以上ずれ…」<br />
という質問（Tokyo Regionとそれ以外で違いがあるのか？）には答えられておらず、<br />
個人的にはそこがかなり気になるのですが、結果的には「ずれてたらゲストOSでntp使ってください」ということになっているようです。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/311/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>swfmill 0.3.1 インストール失敗問題対策</title>
		<link>http://lab.flama.co.jp/archives/304</link>
		<comments>http://lab.flama.co.jp/archives/304#comments</comments>
		<pubDate>Thu, 11 Aug 2011 05:24:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[携帯]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=304</guid>
		<description><![CDATA[PCではFlashから外部APIを叩いて情報を取得、ということができますが、日本の携帯ではそのあたりが禁じられているので、いわゆる「Flashアプリ」を作る際にはswfmillが結構な割合で使用されています。 これはsw [...]]]></description>
			<content:encoded><![CDATA[<p>PCではFlashから外部APIを叩いて情報を取得、ということができますが、日本の携帯ではそのあたりが禁じられているので、いわゆる「Flashアプリ」を作る際には<a href="http://swfmill.org/" target="_blank">swfmill</a>が結構な割合で使用されています。<br />
これはswf←→xmlの変換を行なうサーバアプリケーションで、つまりテンプレートxmlを用意しておけば、ユーザーごとに異なる中身のFlashを提供することができるわけです。</p>
<p>さて、このswfmillですが、結構長い間、0.2.12に<a href="http://dsas.blog.klab.org/archives/51174693.html" target="_blank">KLabパッチ</a>をあてて使用されていました（0.2.12はSJISが扱えない＋FlashLiteがSJISだったため）。</p>
<p>ところが0.3.1がリリースされてKLabパッチが取り込まれたため、さてこれを使おうとすると、インストールできません。<br />
正確には、configureは通るのにmakeが通りません。<br />
バグ報告を見ると、0.3.1リリースの数日後（2010/7）には上がっているものの、動きは無いようです。<br />

https://bugs.launchpad.net/swfmill</p>

<p>検索してみると、ソースファイルを書き換える例がいくつか出てきます。特に商用では正直ソースを書き換えるのはあまりやりたくないわけですが、そうも言ってられず。<br />
makeのエラーからソースをたどり、数ヶ所程度の書き換えでmakeが通るようになりました。</p>
<p>しかし、この時私の目の前にはまだまだサーバが何台も残っていたわけです。まさか全部手作業で書き換えるのはありえない、というわけで、パッチを書いてみました。<br />
<a href='http://lab.flama.co.jp/wp-content/uploads/2011/08/swfmill.0.3.1.v2.patch.zip'>swfmill.0.3.1.v2.patch</a><br />
swfmill-0.3.1.tar.gzを展開したswfmill-0.3.1上で</p>
<blockquote><p>patch -p0 < swfmill.0.3.1.v2.patch</p></blockquote>
<p>を実行後、</p>
<blockquote><p>./configure &#038;&#038; make &#038;&#038; make install</p></blockquote>
<p>でmakeが通ると思います。<br />
※2011/8/25追記：<br />
makeが通ってできたバイナリで一部commandが正常動作しないようでしたので公開を停止しました。<br />
※2011/8/27追記：<br />
patchを修正・再UPしました。</p>
<p>※このパッチはAmazonEC2上のCentOS5.6でのみ動作確認済みです。他の環境では動作確認していません。<br />
※このパッチを使用した結果について一切の責任を負いません。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/304/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CentOS5.6 + remi + mysql インストール</title>
		<link>http://lab.flama.co.jp/archives/302</link>
		<comments>http://lab.flama.co.jp/archives/302#comments</comments>
		<pubDate>Tue, 09 Aug 2011 17:04:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CentOS]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=302</guid>
		<description><![CDATA[CentOS5.6でremiレポジトリを使っている場合、 yum install -y mysql としてしまうと、mysqlが5.0系(base/update由来)と5.5系(remi由来)の両方が入ってしまうことがあ [...]]]></description>
			<content:encoded><![CDATA[<p>CentOS5.6でremiレポジトリを使っている場合、<br />
yum install -y mysql<br />
としてしまうと、mysqlが5.0系(base/update由来)と5.5系(remi由来)の両方が入ってしまうことがあります。<br />
こうなるとphp-mysqlなどのバージョンが混乱して正常に作動しなくなるようでして。</p>
<p>yum install mysql<br />
として、インストール候補一覧が出てy/N選択待ちになったところで、インストールしようとしているバージョンをメモっておきます。<br />
[N]で終了させて、<br />
yum install -y mysql-5.5.15<br />
というようにまずmysqlだけインストールします。<br />
その後、<br />
yum install -y php-mysql （その他もろもろ）<br />
とすると、意図したバージョンに揃ってくれます。</p>
<p>もう複数バージョンでインストールされてしまっている、という場合は、<br />
yum remove mysql<br />
としていったん消してからやり直すことになります。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/302/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CentOS5.6でPHP（php53を使うべきかremiを使うべきか）</title>
		<link>http://lab.flama.co.jp/archives/299</link>
		<comments>http://lab.flama.co.jp/archives/299#comments</comments>
		<pubDate>Sat, 23 Jul 2011 09:00:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=299</guid>
		<description><![CDATA[CentOS5.6が出て3ヶ月ほど経ったので、 そろそろ新規にサーバを発注すると5.6が入ってくるようになりました。 で、CentOS（というかその元になっているRed Hat Enterprise Linux）でのPH [...]]]></description>
			<content:encoded><![CDATA[<p>CentOS5.6が出て3ヶ月ほど経ったので、<br />
そろそろ新規にサーバを発注すると5.6が入ってくるようになりました。</p>
<p>で、CentOS（というかその元になっているRed Hat Enterprise Linux）でのPHPはここしばらく5.1系が入っておりました。<br />
しかし、5.1→5.2→5.3の間では微妙な規模の機能変更・追加があったため、<br />
開発サイドの気持ちとしては、今後のことを考えると5.3にしておきたい、ということなわけです。</p>
<p>では5.5までPHP5.3はソースインストールしていたのかというと、<br />
（そうする場合も多かったとは思いますが）<br />
みんないわゆる「野良レポジトリ」を頼ることになったわけで、<br />
たとえば<a href="http://blog.famillecollet.com/">remi</a>などを<br />
yumのレポジトリに追加してupdateするとphpが5.3になるというわけですね。</p>
<p>＃ソース自体がコミュニティによって書かれてるわけで、<br />
＃「野良レポジトリ」って言い方はどうなのよという話ですが。</p>
<p>さて、そんな状況の中、RHELの5.6ではPHPを5.1.x→5.3.xにせずに、<br />
・php：5.1.x<br />
・php53：5.3.x<br />
という2つのパッケージに分離されました。<br />
そのまま移行するには影響が大きすぎるという判断なんでしょうかね。</p>
<p>これによって自動的にCentOS5.6でもphp53というパッケージが生まれたわけですが、<br />
・php53-pearが無い<br />
・php53-mcryptが無い<br />
のです。これは地味に痛い。<br />
pearは細かいupdateでphp53に対応するわけですが、<br />
mcryptは場合によっては無きゃダメと言われてしまうことがあるので困ってしまうわけです。</p>
<p>今回の記事は「php53とremiとどっち使ったらいいですか？」と聞かれたので書いてみているわけですが、<br />
最終的には…</p>
<p>・野良レポジトリを使って良い状況かどうか<br />
→よければremiにしておく<br />
・必要なライブラリがあるかどうか<br />
→php53に無ければremi確定<br />
・今後ライブラリを追加する可能性があるか<br />
→ある日突然「○○っての入れて」とphp53に無いライブラリを入れろと言われる予感がする場合には最初からremi導入の努力を最初にしておく</p>
<p>というロジックで選びます。<br />
ふざけてるわけではなく、商用でのこういう選択条件は、<br />
（批判をするつもりは毛頭ありませんが）<br />
技術よりも会社のポリシーとか担当者／決済者の気持ちとか、<br />
そういったことになることが結構多いわけです。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/299/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Amazon EC2でSSHはできるのにSFTPができない</title>
		<link>http://lab.flama.co.jp/archives/281</link>
		<comments>http://lab.flama.co.jp/archives/281#comments</comments>
		<pubDate>Thu, 30 Jun 2011 03:09:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Amazon]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=281</guid>
		<description><![CDATA[最近はAmazon EC2をかなりちょくちょく使っています。 一番多い用途は、実運用ではなく、古いOS等でのテスト環境を作成するためだったりします。 ということで、今日も今日とて、CentOS5.3のAMIを見つけてきて [...]]]></description>
			<content:encoded><![CDATA[<p>最近はAmazon EC2をかなりちょくちょく使っています。<br />
一番多い用途は、実運用ではなく、古いOS等でのテスト環境を作成するためだったりします。</p>
<p>ということで、今日も今日とて、CentOS5.3のAMIを見つけてきてインスタンスを作成したわけです。</p>
<p>SSHで必要な環境に整えて、さて必要なファイルをUPしよう、とSFTPでアクセスしたのですが、<br />
接続直後に切断されてしまいます。<br />
クライアント側のログを見ると、接続は確立しているのにすぐCloseしてしまっているようです。<br />
接続が確立しているということは、認証鍵は機能しているようなので、<br />
これはサーバ側のログを見てみるべきでしょう。</p>
<p>ということで /var/log/messages を見てみます。<br />
sshd[1001]: error: subsystem: cannot stat /usr/lib/openssh/sftp-server: No such file or directory</p>
<p>驚愕の事実発覚。<br />
SFTPはSSHDによって、サブシステムとして起動するわけですが、これが存在しないと。</p>
<p>sshd_configを見てみましょう。<br />
<code><br />
vi /etc/ssh/sshd_config</p>
<p>Port 22<br />
Protocol 2<br />
HostKey /etc/ssh/ssh_host_rsa_key<br />
HostKey /etc/ssh/ssh_host_dsa_key<br />
UsePrivilegeSeparation yes<br />
KeyRegenerationInterval 3600<br />
ServerKeyBits 768<br />
SyslogFacility AUTH<br />
LogLevel INFO<br />
LoginGraceTime 120<br />
PermitRootLogin yes<br />
StrictModes yes<br />
RSAAuthentication yes<br />
PubkeyAuthentication yes<br />
IgnoreRhosts yes<br />
RhostsRSAAuthentication no<br />
HostbasedAuthentication no<br />
PermitEmptyPasswords no<br />
ChallengeResponseAuthentication no<br />
PasswordAuthentication no<br />
PrintLastLog no<br />
TCPKeepAlive yes<br />
AcceptEnv LANG LC_*<br />
Subsystem sftp /usr/lib/openssh/sftp-server<br />
UsePAM yes<br />
</code><br />
OpenSSH自体は存在するようなので、とりあえずsftp-serverのありかを探してみます。<br />
find / -type f -name sftp-server<br />
すると次の場所にあるようです。<br />
/usr/libexec/openssh/sftp-server<br />
（当たり前といえば当たり前な在りかですね）</p>
<p>先ほどのsshd_configのSubsystemを<br />
#Subsystem sftp /usr/lib/openssh/sftp-server<br />
Subsystem sftp /usr/libexec/openssh/sftp-server<br />
と書き換えて、<br />
/etc/init.d/sshd restart<br />
でSFTPが起動するようになりました。</p>
<p>まーこれがCommunityAMIの落とし穴でもあり醍醐味でもあるということでしょうかね。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/281/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery Form Plugin の挙動不審</title>
		<link>http://lab.flama.co.jp/archives/272</link>
		<comments>http://lab.flama.co.jp/archives/272#comments</comments>
		<pubDate>Wed, 22 Jun 2011 15:45:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=272</guid>
		<description><![CDATA[jQuery From Plugin というjQueryプラグインがあります。 http://jquery.malsup.com/form/ で、ここのajaxSubmitを使って、Form記述は普通にしたまま、Form [...]]]></description>
			<content:encoded><![CDATA[jQuery From Plugin というjQueryプラグインがあります。<br/>
<a href="http://jquery.malsup.com/form/">http://jquery.malsup.com/form/</a><br/>
<br/>
で、ここのajaxSubmitを使って、Form記述は普通にしたまま、Formの動きをAjax化しようとしたわけです。<br/>
<br/>
サンプルを見るとこんな感じに書いてあります。<br/>

http://jquery.malsup.com/form/#json<br/>


http://jquery.malsup.com/form/#ajaxSubmit<br/>

<br/>
Form markup:
<blockquote>&lt;form id="jsonForm" action="json-echo.php" method="post"> 
    Message: &lt;input type="text" name="message" value="Hello JSON" /> 
    &lt;input type="submit" value="Echo as JSON" /> 
&lt/form></blockquote>

JavaScript:
<blockquote>// prepare the form when the DOM is ready 
$(document).ready(function() { 
    var options = { 
        target:        '#output2',   // target element(s) to be updated with server response 
        beforeSubmit:  showRequest,  // pre-submit callback 
        success:       showResponse  // post-submit callback 
 
        // other available options: 
        //url:       url         // override for form's 'action' attribute 
        //type:      type        // 'get' or 'post', override for form's 'method' attribute 
        //dataType:  null        // 'xml', 'script', or 'json' (expected server response type) 
        //clearForm: true        // clear all form fields after successful submit 
        //resetForm: true        // reset the form after successful submit 
 
        // $.ajax options can be used here too, for example: 
        //timeout:   3000 
    }; 
 
    // bind to the form's submit event 
    $('#myForm2').submit(function() { 
        // inside event callbacks 'this' is the DOM element so we first 
        // wrap it in a jQuery object and then invoke ajaxSubmit 
        $(this).ajaxSubmit(options); 
 
        // !!! Important !!! 
        // always return false to prevent standard browser submit and page navigation 
        return false; 
    }); 
}); </blockquote>
<br/>
で、json-echo.phpの中身はこうなっていると。<br/>

Server code in json-echo.php:<br/>
<blockquote><?php  echo '{ "message": "' . $_POST['message'] . '" }';  ?></blockquote>
<br/>
この通りやると確かに動くわけです。<br/>
しかし、ちょっと違和感があります。<br/>
<br/>
json-echo.phpの記述を見る限り、これはおそらく（PHPのデフォルト設定であれば）text/htmlとして返されるはずです。<br/>
サンプルページのJSONも、HTTPヘッダを拾ってみると、text/htmlで返されています。
しかし、JSONを返しているわけですから、ここはちゃんとapplication/jsonで返そうよ、と思って
<blockquote><?php 
header("Content-type: application/json");
echo '{ "message": "' . $_POST['message'] . '" }'; 
?></blockquote>
とすると、エラーになるのです。（ブラウザによって反応が変わりますが）<br/>
<br/>
で、AJAX側をこのように変えるとエラーにならずに動作します。<br/>
<br/>
Form markup:
<blockquote>&lt;form id="jsonForm" action="#" method="post"> 
    Message: &lt;input type="text" name="message" value="Hello JSON" /> 
    &lt;input type="submit" value="Echo as JSON" /> 
&lt/form></blockquote>
JavaScript:
<blockquote>// prepare the form when the DOM is ready 
$(document).ready(function() { 
    // bind form using ajaxForm 
    $('#jsonForm').ajaxForm({ 
        // dataType identifies the expected content type of the server response 
        dataType:  'json', 
         ,url: 'json-echo.php'
        // success identifies the function to invoke when the server response 
        // has been received 
        success:   processJson 
    }); 
});</blockquote>
<br/>
やったことと言えば、Form内のactionをそのままajaxオプションurlに移動しただけですが、
どうも、FormのactionにURLが書いてあるかどうかによって挙動が変わってるみたいですね。



]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/272/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeIgniterのimage_libでImageMagickを使った場合のバグ的挙動</title>
		<link>http://lab.flama.co.jp/archives/262</link>
		<comments>http://lab.flama.co.jp/archives/262#comments</comments>
		<pubDate>Wed, 08 Jun 2011 19:05:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=262</guid>
		<description><![CDATA[なんか似たようなエントリが続いていて恐縮ですが、 同じようなことをしばらく続けているとやはりそういうことになるわけでして。 今回はバグと言えばバグだし、「こういう機能だ」と言われればそれまで、というものです。 さて、Co [...]]]></description>
			<content:encoded><![CDATA[なんか似たようなエントリが続いていて恐縮ですが、<br/>
同じようなことをしばらく続けているとやはりそういうことになるわけでして。<br/>
今回はバグと言えばバグだし、「こういう機能だ」と言われればそれまで、というものです。<br/>
<br/>
さて、CodeIgniterにはimage_libというライブラリがありまして、<br/>
これがgdやImageMagickのラッパになっているわけです。<br/>
デフォルトがgdなわけですが、引数でImageMagickと渡してやるだけで使えることになっています。<br/>
<br/>
で、やろうとしたことは、<br/>
・アップロードで受け取ったデジカメなどで撮った画像を定められた大きさの正方形に加工<br/>
というものです。<br/>
画像処理の流れは<br/>
・縦長か横長かを判定<br/>
・余分な部分をカット<br/>
ということになるはずです。<br/>
縦長／横長を判定するのは、まず短辺が指定のサイズになるよう縮小／拡大する必要があるためですね。<br/>
判定結果は、<br/>
<blockquote>$config['maintain_ratio'] = TRUE;
$config['height']	= 50;
$config['width']	 = 50;
$config['master_dim'] = &#8216;width&#8217;;
$this->load->library(&#8216;image_lib&#8217;, $config); 
$this->image_lib->resize();
</blockquote>
のmaster_dimをheight/widthどっちに指定するかに使います。<br/>
<br/>
次にcrop()を使うわけですが、このメソッドの数値の指定はちょっと癖があります。<br/>
この部分のドキュメントは<br/>
<blockquote>切り抜きメソッドは、次のように切り取る場所を指定する X および Y 軸 (ピクセル) を設定する必要があるのを除いて、 リサイズメソッドと大体同じように動作します:
</blockquote>
と書かれています。<br/>
さらっと読むと「0〜X, 0〜Y」が切り抜き範囲なのかなと思ってしまうのですが、<br/>
実はこれは逆で、「X〜, Y〜」が切り抜き範囲なのです。<br/>
（0,0は画像左上端です）<br/>
ある大きさの画像を「左上端から50&#215;50で切り抜きたい」とした場合、<br/>
オプションへの数値が渡しようがないように見えます。<br/>
<blockquote>$config['x_axis']	= 50;
$config['x_axis']	 = 50;
$this->load->library(&#8216;image_lib&#8217;, $config); 
$this->image_lib->crop();
</blockquote>
では、「X=50, Y=50から画像終端まで」の切り抜きになってしまうからです。<br/>
<br/>
で、ソースを見てみることにしました。<br/>
<br/>
PHPでImageMagickを直接に使う場合、PECLのimageickライブラリを入れることが結構あるかと思いますが、CodeIgniterのimage_libの内部ではexecを叩いています。<br/>
つまり、<br/>
<blockquote>$this->load->library(&#8216;image_lib&#8217;, $config); 
</blockquote>
とする時のオプション$configは、そのままconvertコマンドへ渡されるわけです。<br/>
<br/>
ということは、先ほどのx_axis, y_axisの指定方法は、<br/>
CodeIgniterの問題ではなくImageMagickのオプションの指定方法の問題です。<br/>
ImageMagickをコマンドラインで叩く場合には、<br/>
<blockquote>convert -resize 50&#215;50+25+25 file_org file_dist
</blockquote>
というようにオプションを指定します。上記の例の場合は、<br/>
・50&#215;50にリサイズした上でX=25, Y=25から画像の終端までを切り抜く<br/>
ということになります。<br/>
<br/>
となると、「じゃあ0〜X, 0〜Yに切り取るのはどーするんだ？」ということになりますね。<br/>
covertコマンドで叩く場合、上記の例を0〜X, 0〜Yで切り抜くには<br/>
<blockquote>convert -resize 50&#215;50-10-10 file_org file_dist
</blockquote>
とします。この場合は<br/>
・50&#215;50にリサイズした上で、画像左上端から10&#215;10を切り抜く<br/>
ということになります。<br/>
反転させる場合にはマイナス指定、というのは、こういうものではよくある指定ですよね。<br/>
<br/>
さて、ではCodeIgniterで<br/>
<blockquote>$config['x_axis']	= -50;
$config['x_axis']	 = -50;
$this->load->library(&#8216;image_lib&#8217;, $config); 
$this->image_lib->crop();
</blockquote>
のように指定してみるとどうなるか。<br/>
…これは動作しません。image_libライブラリの580行目に、その答えがあります。<br/>
<blockquote>$cmd .= &#8221; -crop &#8220;.$this->width.&#8221;x&#8221;.$this->height.&#8221;+&#8221;.$this->x_axis.&#8221;+&#8221;.$this->y_axis.&#8221; \&#8221;$this->full_src_path\&#8221; \&#8221;$this->full_dst_path\&#8221; 2>&#038;1&#8243;;
</blockquote>
まさかのプラス決め打ち！！右下側切り抜くことしか想定されていないとは！<br/>
<br/>
…で、あまりキレイではありませんができるだけ元を残してこんな感じに修正。<br/>
<blockquote>&#8212; system/libraries/Image_lib.php	2011-03-28 16:25:12.000000000 +0900
+++ application/libraries/Image_lib.php	2011-06-08 23:52:47.000000000 +0900
@@ -577,7 +577,17 @@
 
 		if ($action == &#8216;crop&#8217;)
 		{
-			$cmd .= &#8221; -crop &#8220;.$this->width.&#8221;x&#8221;.$this->height.&#8221;+&#8221;.$this->x_axis.&#8221;+&#8221;.$this->y_axis.&#8221; \&#8221;$this->full_src_path\&#8221; \&#8221;$this->full_dst_path\&#8221; 2>&#038;1&#8243;;
+			if($this->x_axis<0){
+				$x_axis = $this->x_axis;
+			}else{
+				$x_axis = &#8220;+&#8221;.$this->x_axis;
+			}
+			if($this->y_axis<0){
+				$y_axis = $this->y_axis;
+			}else{
+				$y_axis = &#8220;+&#8221;.$this->y_axis;
+			}
+			$cmd .= &#8221; -crop &#8220;.$this->width.&#8221;x&#8221;.$this->height.$x_axis.$y_axis.&#8221; \&#8221;$this->full_src_path\&#8221; \&#8221;$this->full_dst_path\&#8221; 2>&#038;1&#8243;;
 		}
 		elseif ($action == &#8216;rotate&#8217;)
 		{
</blockquote>
で、ちゃんと意図した通りに切り抜いてくれました。<br/>
system/libraries/Image_lib.php をapplication/libraries/Image_lib.php としてコピーして修正すれば上書き実行されるのでその点は便利。<br/>
<br/>
このライブラリ、ExpressionEngineのコードだと冒頭コメントで宣言されているんですが、
大丈夫なのかExpressionEngine…。<br/>
バグ報告くらい上がってそうだと思ったんですが、<br/>
CodeIgniterの方にも、<br/>
<a href="https://bitbucket.org/ellislab/codeigniter/issues?q=image_lib">https://bitbucket.org/ellislab/codeigniter/issues?q=image_lib</a><br/>
CI Reactorの方にも無いんですよねえ…。<br/>
<a href="https://bitbucket.org/ellislab/codeigniter-reactor/issues?q=image_lib">https://bitbucket.org/ellislab/codeigniter-reactor/issues?q=image_lib</a><br/>
<br/>
もうみんなそういう機能だと思って使ってるんでしょうかね？<br/>

]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/262/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>requireとrequire_onceの違い + CodeIgniter 2.0.1のバグ</title>
		<link>http://lab.flama.co.jp/archives/224</link>
		<comments>http://lab.flama.co.jp/archives/224#comments</comments>
		<pubDate>Fri, 20 May 2011 14:30:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=224</guid>
		<description><![CDATA[CodeIgniter2のファイルヘルパにget_mime_by_extension()というものがあります。ファイル名を投げるとmimeを返す関数です。 しかし、get_mime_by_extension(&#8216 [...]]]></description>
			<content:encoded><![CDATA[CodeIgniter2のファイルヘルパにget_mime_by_extension()というものがあります。ファイル名を投げるとmimeを返す関数です。<br/>
<br/>
しかし、get_mime_by_extension(&#8216;hoge.jpg&#8217;)とするとPHP Warningが出たので、system/helper/file_helper.phpにトレースを入れてテストしてみたところ、
application/config/mimes.phpをロードできていない様子。<br/>
<br/>
そこでこのようなチケットを発見。<br/>
<a href="https://bitbucket.org/ellislab/codeigniter/issue/354/get_mime_by_extension-triggers-php-error">https://bitbucket.org/ellislab/codeigniter/issue/354/get_mime_by_extension-triggers-php-error</a><br/>
<blockquote>Some dirty trick is changing the source Code: require_once -> require</blockquote>
require_onceをrequireにすれば動くよ！とのこと。<br/>
<br/>
ちなみにこの関数のソースは次のようになっています。
<blockquote>if ( ! function_exists(&#8216;get_mime_by_extension&#8217;)){
	function get_mime_by_extension($file){
		$extension = strtolower(substr(strrchr($file, &#8216;.&#8217;), 1));
		global $mimes;
		if ( ! is_array($mimes)){
			if ( ! require_once(APPPATH.&#8217;config/mimes.php&#8217;)){
				return FALSE;
			}
		}
		if (array_key_exists($extension, $mimes)){
			if (is_array($mimes[$extension])){
				// Multiple mime types, just give the first one
				return current($mimes[$extension]);
			}else{
				return $mimes[$extension];
			}
		}else{
			return FALSE;
		}
	}
}</blockquote>
<br/>
requireとrequire_onceの違いは、ドキュメントをさらっと読むだけでは、それぞれ「毎回読み込む」「1回しか読み込まない」としか読み取れません。なによりドキュメントがひどい。<br/>
require_once()<br/>
<a href="http://php.net/manual/ja/function.require-once.ph">http://php.net/manual/ja/function.require-once.ph</a>p<br/>
<blockquote>_once の振る舞い、およびそれが _once なし版とどのように異なるのかについての情報は、 include_once() のドキュメントを参照ください。</blockquote>
↓<br/>
include_once()<br/>
<a href="http://www.php.net/manual/ja/function.include-once.php">http://www.php.net/manual/ja/function.include-once.php</a><br/>
<blockquote>この関数の動作についての情報は include() のドキュメントを参照ください。</blockquote>
↓<br/>
include()<br/>
<a href="http://www.php.net/manual/ja/function.include.php">http://www.php.net/manual/ja/function.include.php</a><br/>
<blockquote>読み込まれるファイルで定義された関数がある場合、 これらは、return()の前後によらず メインファイルで使用できます。
 このファイルが二度読み込まれた場合、PHP 5は関数が定義済みであるため 致命的なエラーを発生します。
一方、PHP 4は return()の後に定義された関数については、 エラーを発生しません。 ファイルが読み込み済みであるかどうかを調べ、 
読み込まれるファイルの内容を条件分岐で返すかわりに include_once()を使用することを推奨します。</blockquote>
えーと…「_once の振る舞い、およびそれが _once なし版とどのように異なるのかについての情報」はどこへ行ってしまったんでしょうか？<br/>
_onceの話が出てくるのはこの数行だけなんです。<br/>
<br/>
これでは、「何回かinclude/requireする可能性のある個所では_onceにしとけばいいんだな」としか読み取れないでしょう。<br/>
<br/>
しかし両者の違いは、こんなサンプルコードでも分かるはずです。
<blockquote>hoge.php
&lt;?php
return &#8220;hoge&#8221;;</blockquote>
<br/>
<blockquote>test.php
&lt;?php
var_dump(require_once((dirname(__FILE__).&#8221;/hoge.php&#8221;)));
var_dump(require_once((dirname(__FILE__).&#8221;/hoge.php&#8221;)));
var_dump(require((dirname(__FILE__).&#8221;/hoge.php&#8221;)));</blockquote>
<br/>
test.phpの実行結果は
<blockquote>string(4) &#8220;hoge&#8221;
bool(true)
string(4) &#8220;hoge&#8221;</blockquote>
となります。<br/>
つまり、2回目以降のrequire_onceは、指定したファイルの中身ではなく、boolean値を返します。<br/>
つまりこれは、いくつかあるincludeの挙動のうち、「return記述の無いPHP実行ファイルをincludeした場合の返り値」と同じ挙動になるわけです。<br/>
<br/>
このことについてドキュメントには明記されておらず、しいて言えば、<br/>
include()<br/>
<a href="http://www.php.net/manual/ja/function.include.php">http://www.php.net/manual/ja/function.include.php</a><br/>
内の「例5 include()とreturn()文」のコード例に示唆されているだけです。<br/>
と同時に、
<blockquote>include() は、ファイルを見つけられない場合に warning を発行します。
一方 require() の場合は、同じ場合に fatal error を発行する点が異なります。
</blockquote>
とあります。さらに、<br/>
require()<br/>
<a href="http://www.php.net/manual/ja/function.require.php">http://www.php.net/manual/ja/function.require.php</a>
<blockquote>require() は include() とほぼ同じですが、失敗した場合に E_COMPILE_ERROR レベルの致命的なエラーも発生するという点が異なります。 
つまり、スクリプトの処理がそこで止まってしまうということです。
一方 include() の場合は、警告 (E_WARNING) を発するもののスクリプトの処理は続行します。</blockquote>
ということは、require_onceを単純にIF文に突っ込むだけでは（そもそもこの記述はIDEに怒られると思いますが）判定は成り立たない、ということになります。<br/>
<br/>
CI2.0.2では、この関数は次のように記述されています。
<blockquote>if ( ! function_exists(&#8216;get_mime_by_extension&#8217;)){
	function get_mime_by_extension($file){
		$extension = strtolower(substr(strrchr($file, &#8216;.&#8217;), 1));
		global $mimes;
		if ( ! is_array($mimes)){
			if (defined(&#8216;ENVIRONMENT&#8217;) AND is_file(APPPATH.&#8217;config/&#8217;.ENVIRONMENT.&#8217;/mimes&#8217;.EXT)){
				include(APPPATH.&#8217;config/&#8217;.ENVIRONMENT.&#8217;/mimes&#8217;.EXT);
			}elseif (is_file(APPPATH.&#8217;config/mimes&#8217;.EXT)){
				include(APPPATH.&#8217;config/mimes&#8217;.EXT);
			}
			if ( ! is_array($mimes)){
				return FALSE;
			}
		}
		if (array_key_exists($extension, $mimes)){
			if (is_array($mimes[$extension])){
				// Multiple mime types, just give the first one
				return current($mimes[$extension]);
			}else{
				return $mimes[$extension];
			}
		}else{
			return FALSE;
		}
	}
}</blockquote>
多少PATHなどが変わった影響はありますが、ファイル存在判定と読み込み後のデータ存在判定を分離したこと、requireをincludeに変えたことで、処理が停止することが無くなった、という具合に修正されています。<br/>
<br/>
じゃあ2.0.2を使えばいいのね、というわけにもいかないのが悩ましいところで、2.0.2は若干バギーだったため、2.0.3のリリースが急がれているようです。日本語版も2.0.2を飛ばして2.0.3に向かうとのこと。<br/>
<br/>
とりあえずsystem/helper/file_helper.phpを直すか、get_mime_by_extension()を使わないか、という選択肢になりますかね…。<br/>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/224/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CpdeIgniterでコントローラをサブフォルダに置く場合</title>
		<link>http://lab.flama.co.jp/archives/220</link>
		<comments>http://lab.flama.co.jp/archives/220#comments</comments>
		<pubDate>Wed, 18 May 2011 09:08:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[実験・検証]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=220</guid>
		<description><![CDATA[開発をしていて、後のメンテナンス性などを考えると、各ソースファイルはできればディレクトリに分けて配置したいなと思うことがあります。 CodeIgniterでは、コントローラ・モデル・ビューともにサブディレクトリに配置する [...]]]></description>
			<content:encoded><![CDATA[<p>開発をしていて、後のメンテナンス性などを考えると、各ソースファイルはできればディレクトリに分けて配置したいなと思うことがあります。</p>
<p>CodeIgniterでは、コントローラ・モデル・ビューともにサブディレクトリに配置することができます。<br />
<a href="http://codeigniter.jp/user_guide_ja/general/controllers.html#subfolders" target="_blank">http://codeigniter.jp/user_guide_ja/general/controllers.html#subfolders</a></p>
<p>しかし実際には、コントローラだけは、application/controllers直下のディレクトリ内にソースファイルが存在しなければ動作しません。<br />
たとえば、<br />
application/controllers/api/get/hoge.phpを<br />
/api/get/hoge<br />
と呼び出すことはできないわけです。</p>
<p>となると、このようなURLを作りたいと思った場合に、直球で考えると、application/controllers/apiディレクトリにgetコントローラを作ってメソッドを全てぶらさげないといけないのか！？と思ってしまうわけですが、これはルーティングの仕事なのだろうと思います。</p>
<p>上の例でいくと、<br />
application/controllers/api_get/<br />
というディレクトリを作っておいて、<br />
application/config/routes.php<br />
に<br />
$route['api/get/(:any)'] = &#8220;api_get/$1&#8243;;<br />
とすれば、<br />
/api/get/hoge<br />
で<br />
application/controllers/api_get/hoge.php<br />
を呼び出せるようになるわけですね。</p>
<p>メソッドの数が少なければ（＆コード量が少なければ）getコントローラ1つでまかなえるとは思うのですが、最初っからそれなりの数になってしまうことが予想される場合や、後から機能追加が予想される場合には、ソースごと分けたいですよね。</p>
<p>CakePHPなどだとバッキバキにルーティング設定をしたりするようですが、CodeIgniterでのルーティング設定は基本的に「indexメソッドをURLから取る」というシンプルな目的に使われることが多く（自分だけかもしれないですが）それほど使わない印象があるので、メモった次第です。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/220/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacPorts+Codeigniterで突然表示ができなくなった場合</title>
		<link>http://lab.flama.co.jp/archives/208</link>
		<comments>http://lab.flama.co.jp/archives/208#comments</comments>
		<pubDate>Sat, 02 Apr 2011 17:29:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=208</guid>
		<description><![CDATA[MacOSX+Codeigniterで突然表示ができなくなった場合、と言ってもおそらくいろいろあるとは思うのですが、メモとして。 まず何をしていたかというと、OAuthのテストをしようしていて、 curl・php-cur [...]]]></description>
			<content:encoded><![CDATA[<p>MacOSX+Codeigniterで突然表示ができなくなった場合、と言ってもおそらくいろいろあるとは思うのですが、メモとして。</p>
<p>まず何をしていたかというと、OAuthのテストをしようしていて、<br />
curl・php-curlがうまく動かないという現象がありまして、<br />
どうやらcurl-ca-bundleがおかしいとエラーがでていました。<br />
port clean curl-ca-bundle すれば良いという情報もあったのですがこれでは復旧せず、<br />
結局 port selfupdate をかけて正常に port install curl が入りました。</p>
<p>ところがこの後、CodeIgniterが全然動かない<br />
という奇妙な現象に陥りました。</p>
<p>Apacheのerror_logを見てみたところ次のようなありさま。</p>
<blockquote><p>
dyld: lazy symbol binding failed: Symbol not found: __mysqlnd_end_psession<br />
  Referenced from: /opt/local/lib/php/extensions/no-debug-non-zts-20090626/mysql.so<br />
  Expected in: flat namespace</p>
<p>dyld: Symbol not found: __mysqlnd_end_psession<br />
  Referenced from: /opt/local/lib/php/extensions/no-debug-non-zts-20090626/mysql.so<br />
  Expected in: flat namespace</p>
<p>[Sun Apr 03 02:17:00 2011] [notice] child pid 214 exit signal Trace/BPT trap (5)<br />
dyld: lazy symbol binding failed: Symbol not found: __mysqlnd_end_psession<br />
  Referenced from: /opt/local/lib/php/extensions/no-debug-non-zts-20090626/mysql.so<br />
  Expected in: flat namespace</p>
<p>dyld: Symbol not found: __mysqlnd_end_psession<br />
  Referenced from: /opt/local/lib/php/extensions/no-debug-non-zts-20090626/mysql.so<br />
  Expected in: flat namespace</p>
<p>[Sun Apr 03 02:20:05 2011] [notice] child pid 335 exit signal Trace/BPT trap (5)<br />
dyld: lazy symbol binding failed: Symbol not found: __mysqlnd_end_psession<br />
  Referenced from: /opt/local/lib/php/extensions/no-debug-non-zts-20090626/mysql.so<br />
  Expected in: flat namespace</p>
<p>dyld: Symbol not found: __mysqlnd_end_psession<br />
  Referenced from: /opt/local/lib/php/extensions/no-debug-non-zts-20090626/mysql.so<br />
  Expected in: flat namespace
</p></blockquote>
<p>さてこれでMacPortsのMySQL関連がどこかおかしくなったことはなんとなくわかりますが、ググってみても情報が出てこないのです。</p>
<p>こんな時には基本に立ち返るというわけで、</p>
<blockquote><p>port upgrade mysql5-server</p></blockquote>
<p>upgrade対象無し。</p>
<blockquote><p>port uninstall mysql5-server</p></blockquote>
<p>php5-mysqlがエラーを吐いている様子。</p>
<blockquote><p>port uninstall php5-mysql</p></blockquote>
<p>uninstallできないとなると…</p>
<blockquote><p>port deactivate php5-mysql</p></blockquote>
<p>deactivateは出来たようですね。</p>
<blockquote><p>port install php5-mysql</p></blockquote>
<p>なにもエラーなく終了しました。</p>
<blockquote><p>/opt/local/apache2/bin/apachectl restart</p></blockquote>
<p>なにごともなく表示復旧しました…。</p>
<p>phpMyAdminが動いてCodeIgniterが動かない、というのはなぜだろう？<br />
ということで後でソースを見てみることにします。<br />
今日は取り急ぎここまでということで。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/208/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>震災・計画停電に対するサーバ会社各社の声明まとめ</title>
		<link>http://lab.flama.co.jp/archives/204</link>
		<comments>http://lab.flama.co.jp/archives/204#comments</comments>
		<pubDate>Mon, 14 Mar 2011 05:36:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=204</guid>
		<description><![CDATA[こちらも参照 http://japan.cnet.com/news/society/35000414/ とりあえず弊社が使用・関連している会社・サービスから。 さくらインターネット http://www.sakura.n [...]]]></description>
			<content:encoded><![CDATA[<p>こちらも参照<br />
<a href="http://japan.cnet.com/news/society/35000414/">http://japan.cnet.com/news/society/35000414/</a></p>
<p>とりあえず弊社が使用・関連している会社・サービスから。</p>
<p>さくらインターネット<br />
<a href="http://www.sakura.ne.jp/news/archives/20110314-003.news">http://www.sakura.ne.jp/news/archives/20110314-003.news</a></p>
<p>AWS（Amazonクラウド）<br />
<a href="http://status.aws.amazon.com/">http://status.aws.amazon.com/</a><br />
（現時点では個別の発表は見当たらない）</p>
<p>Google Apps<br />
<a href="http://www.google.com/appsstatus#hl=ja">http://www.google.com/appsstatus#hl=ja</a></p>
<p>iSLE (GMO)<br />
<a href="http://home.isle.ne.jp/news/2011/110314.html">http://home.isle.ne.jp/news/2011/110314.html</a></p>
<p>@ymc (GMO)<br />
<a href="http://www.ymc.ne.jp/news/#20110314">http://www.ymc.ne.jp/news/#20110314</a></p>
<p>ラピッドサイト<br />
<a href="http://www.rapidsite.jp/news/2011/index.html#20110314">http://www.rapidsite.jp/news/2011/index.html#20110314</a></p>
<p>ニフティクラウド<br />
<a href="http://niftycloud.cocolog-nifty.com/blog/2011/03/post-e6cb.html">http://niftycloud.cocolog-nifty.com/blog/2011/03/post-e6cb.html</a><br />
<a href="http://niftycloud.cocolog-nifty.com/blog/2011/03/post-7eff.html">http://niftycloud.cocolog-nifty.com/blog/2011/03/post-7eff.html</a></p>
<p>i2ts<br />
<a href="http://www.i2ts.com/news/2011031101.html">http://www.i2ts.com/news/2011031101.html</a><br />
<a href="http://www.i2ts.com/news/2011031401.html">http://www.i2ts.com/news/2011031401.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/204/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Appsのアカウント移行でGoogle Analyticsにログインできない</title>
		<link>http://lab.flama.co.jp/archives/201</link>
		<comments>http://lab.flama.co.jp/archives/201#comments</comments>
		<pubDate>Mon, 31 Jan 2011 10:30:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Google Apps]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://lab.flama.co.jp/?p=201</guid>
		<description><![CDATA[Googleアカウントがマルチアカウント可能になったのに伴って、 Google Appsのアカウントも2010年末から移行が開始されています。 Appsの方のアカウント移行は具体的に何かというと、 これまでAppsでは使 [...]]]></description>
			<content:encoded><![CDATA[<p>Googleアカウントがマルチアカウント可能になったのに伴って、<br />
Google Appsのアカウントも2010年末から移行が開始されています。<br />
Appsの方のアカウント移行は具体的に何かというと、<br />
これまでAppsでは使用できなかったAnalyticsやBookmark、Readerなどのもろもろのサービスが<br />
そのままAppsのアカウントで使用できるようになる、というわけです。</p>
<p>ところがこれまで、GoogleアカウントではGoogle Appsと同じメールアドレスで登録することができていた（ややこしいですが）わけでして、そのようなGoogleアカウントを持っていた人にとっては、Google Appsのアカウント移行が後回しになったのです。<br />
で、事前のアナウンス通りに2010年末から以降が開始されたのですが、これが結構中途半端なことになっていて、いくつかのサービスでアカウントが壊れたような状態になってしまっていました。</p>
<p>しかしこれが使えないというのもまた実際問題困ってしまうことがあるので、各サービスごとに不具合を解消する手だてをとってみました。以下はそのまとめ（時系列）です。<br />
お約束ですが、やった結果どのようになっても責任は取れません。</p>
<p>Google Appsダッシュボード<br />
・自分のアカウントを含めて「移行を開始」する<br />
・Google Appsからログアウト</p>
<p>Analytics<br />
・別アカウントを用意し、全てのプロファイルに管理者権限で追加</p>
<p>Bookmark・Readerなど<br />
・エクスポートして保存しておく</p>
<p>Googleアカウント<br />
・全てのサービスを解除<br />
・アカウントクローズ</p>
<p>（この間最大24時間放置）</p>
<p>Google Appsダッシュボード<br />
・自分のアカウントが「移行済み」になっていることを確認<br />
・「コア Google Apps スイート」以外のサービスを有効にする</p>
<p>Bookmark・Readerなど<br />
・サービスによってはログイン時に「アクティベートしろ」と言われる（あいまい）<br />
・ReaderについてはDLしておいたxmlファイルをインポートする</p>
<p>…と、ここまできたところで、だいたいのサービスにログインができるようになっていたのですが、<br />
Analyticsだけはログインしてもエラーが発生します。<br />
調べてみると同じような人が結構いるようですが日本語では結局情報が無く、<br />
Analyticsフォーラムの英語版で発見。<br />
<a href="http://www.google.com/support/forum/p/Google+Analytics/thread?tid=0b017663252c211c&#038;hl=en">http://www.google.com/support/forum/p/Google+Analytics/thread?tid=0b017663252c211c&#038;hl=en</a></p>
<blockquote><p>1. From the Google Analytics home page, click Product<br />
2. On the Product page, under Product Family ->Analysis and Optimization, click Website Optimizer<br />
3. Activate the Website Optimizer feature.<br />
4. Finally, go back to the Google Analytics homepage and you will be able to create and access analytics accounts! Woohoo! :-)</p></blockquote>
<p>ウェブサイトオプティマイザーにログインしてみると、Analyticsでエラーは出なくなりました。<br />
が、もちろんプロファイルは全て空。</p>
<p>そこで、Analyticsに別アカウントでログインし、元のアドレスをプロファイルごとに追加してやればAnalyticsが使えるようになります。</p>
<p>Bookmarkにはファイルから直接のインポート機能が無いので、<br />
http://www.google.com/support/toolbar/bin/answer.py?hl=ja&#038;answer=43305<br />
などを使用してブラウザなどをいったん経由させる必要がありますね。</p>
<p>Google Appsで利用しているメールアドレスでGoogleのサービスをどこまで利用しているかによって、この方法で解決するかどうか変わるかもしれません。<br />
また、Google側での「移行」処理がいつまで行われるかによってはこの情報もすぐに要らないものになるのでしょうけれども…。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/201/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symbian Foundation</title>
		<link>http://lab.flama.co.jp/archives/162</link>
		<comments>http://lab.flama.co.jp/archives/162#comments</comments>
		<pubDate>Thu, 18 Nov 2010 04:06:40 +0000</pubDate>
		<dc:creator>mimori</dc:creator>
				<category><![CDATA[技術]]></category>
		<category><![CDATA[携帯]]></category>
		<category><![CDATA[機械]]></category>

		<guid isPermaLink="false">http://restinpeace.jp/?p=162</guid>
		<description><![CDATA[本にも期待していることを書いていた Symbian Foundationが事実上終了ということで、SymbianはまたOSの立場になってしまいましたね…。 http://www.itmedia.co.jp/enterpr [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.co.jp/gp/product/4844361082?ie=UTF8&#038;tag=chilloutordie-22&#038;linkCode=as2&#038;camp=247&#038;creative=1211&#038;creativeASIN=4844361082">本</a>にも期待していることを書いていた Symbian Foundationが事実上終了ということで、SymbianはまたOSの立場になってしまいましたね…。<br />
<a href="http://www.itmedia.co.jp/enterprise/articles/1011/10/news012.html">http://www.itmedia.co.jp/enterprise/articles/1011/10/news012.html</a><br />
<a href="http://ascii.jp/elem/000/000/570/570261/">http://ascii.jp/elem/000/000/570/570261/</a></p>
<p>メーカー側の事業として見たら、既存の端末にいかほど導入されているか、ということよりも、Androidのように、これからどれくらい導入されていくか（しかもその見込みが明らかにそれなりに期待できる）という方に傾くでしょうから、しょうがないなとは思うのですが。</p>
<p>オープンソースになったあたりから、既存の端末をベースに発展ができるかと期待していたのですが、ハイエンド機向けにはMeeGoもあるし、当面はちょっと難しいことになりそうですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/162/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress Plugin : Ultimate Google Analytics</title>
		<link>http://lab.flama.co.jp/archives/153</link>
		<comments>http://lab.flama.co.jp/archives/153#comments</comments>
		<pubDate>Sat, 23 Oct 2010 07:58:59 +0000</pubDate>
		<dc:creator>mimori</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[技術]]></category>

		<guid isPermaLink="false">http://restinpeace.jp/?p=153</guid>
		<description><![CDATA[http://wordpress.org/extend/plugins/ultimate-google-analytics/ WordPressでGoogleAnalyticsを使う場合にほぼオンリーワンなプラグインです [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://wordpress.org/extend/plugins/ultimate-google-analytics/" target="_blank">http://wordpress.org/extend/plugins/ultimate-google-analytics/</a><br />
WordPressでGoogleAnalyticsを使う場合にほぼオンリーワンなプラグインですが、<br />
すでにGAタグが入っていると動作しません。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/153/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>いま何を注目してますか？</title>
		<link>http://lab.flama.co.jp/archives/148</link>
		<comments>http://lab.flama.co.jp/archives/148#comments</comments>
		<pubDate>Mon, 11 Oct 2010 08:05:37 +0000</pubDate>
		<dc:creator>mimori</dc:creator>
				<category><![CDATA[携帯]]></category>

		<guid isPermaLink="false">http://restinpeace.jp/?p=148</guid>
		<description><![CDATA[…そんなん聞かれても、とは思うのですが、最近かなり聞かれるので、 とりあえず気になっていることをまとめてみる次第です。 注視しているもの： ・docomoのSIMロック解除がどのように実施されるのか →iモードとの接続を [...]]]></description>
			<content:encoded><![CDATA[<p>…そんなん聞かれても、とは思うのですが、最近かなり聞かれるので、<br />
とりあえず気になっていることをまとめてみる次第です。</p>
<p>注視しているもの：</p>
<p>・docomoのSIMロック解除がどのように実施されるのか<br />
→iモードとの接続をどうするのか。</p>
<p>・Android<br />
→今後出るであろうケータイでの採用について。</p>
<p>・キャリア公式サイト制度<br />
→どう方向転換するか。</p>
<p>気にしているもの：</p>
<p>・KDDIの社長さんが替わるのでauの戦略がどうなるか<br />
→新機軸打ち出さないわけにはいかないだろうし、かといって物理的な制約もいっぱいあるわけで。</p>
<p>・auが10/18に発表するという「禁断のアプリケーション」<br />
→どの方向に禁断なのか、ということによって、何に顔を向けているのかが現れるのではないかと。</p>
<p>・Baiduなどの海外勢<br />
→携帯を重視してアプローチしているようなので。</p>
<p>・周波数帯<br />
→まだ先ですがターニングポイントになると思うので。</p>
<p>・Symbian Foundation<br />
→Sony EricssonとSamsungが手を引きぎみなので。</p>
<p>がっかりしているもの：</p>
<p>・Flash Lite 4<br />
→FlashPlayerとの統合の話は出ていたのに…。</p>
<p>ケータイに関してはほとんどの場合、技術は後から動くので、こういうことを日々気にして生きています。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/148/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>日本製ケータイは無くなるのか</title>
		<link>http://lab.flama.co.jp/archives/145</link>
		<comments>http://lab.flama.co.jp/archives/145#comments</comments>
		<pubDate>Mon, 11 Oct 2010 06:30:12 +0000</pubDate>
		<dc:creator>mimori</dc:creator>
				<category><![CDATA[携帯]]></category>

		<guid isPermaLink="false">http://restinpeace.jp/?p=145</guid>
		<description><![CDATA[日経に「日本製ケータイがなくなる日」という記事があって （リンクするなと書いてあるのでリンクしません。リンクできない公開ページって何？） 「無くなるんですか？」という質問を何度かもらったわけです。 記事の内容を読むと、  [...]]]></description>
			<content:encoded><![CDATA[<p>日経に「日本製ケータイがなくなる日」という記事があって<br />
（リンクするなと書いてあるのでリンクしません。リンクできない公開ページって何？）<br />
「無くなるんですか？」という質問を何度かもらったわけです。</p>
<p>記事の内容を読むと、<br />
・世界的にシェア低い<br />
・スマートフォンに押されている<br />
・Android使えば世界に打って出られるんじゃないか？<br />
・VAIOみたいなブランドを打ち出すことは可能なんじゃないか？<br />
というような内容でした。</p>
<p>個人的には、メーカーがどうこうというのは正直どうでもいいんじゃないかと思っています。だってお金になると思ったら誰だってやるわけですよ。</p>
<p>スマートフォンじゃないケータイでAndroidが出せるかどうかなんて、キャリア次第なわけです。そもそも、日本の携帯電話メーカーにはキャリアからお金が出ていたわけで、受託開発で余計なもの入れられないというのは携帯電話とか関係なくあたりまえの話なわけです。<br />
半ば受託開発で作られた製品と、自社開発して売り込まれるパッケージとはポジションが違うわけで、受託開発で固まっている市場にパッケージが切り込む、という図式はどの業種にでも見ることができるはずです。</p>
<p>なのでどちらかというと、フルスクラッチvsパッケージという構図や、日本ではフルスクラッチ開発されたシステムが好まれる傾向にある云々（本当かどうかは微妙ですが）などというあたりの話とリンクして論じられてもいいものではないかなーと思うわけです。</p>
<p>記事中に「米国のテレビ産業のようになってしまうかもしれない」というドコモの人のコメントが出てましたが、アメリカのTVメーカー潰したのは日本のメーカーなわけで、これと同じように他国のメーカーが日本の携帯電話製造に参入して潰しちゃうかもね、という文脈なんでしょう。<br />
少なくとも現時点では、海外メーカーはフルスペックのケータイをほとんど出していません。日本国内向けに作らなくてはならないので。そのこと自体が参入障壁として問題にされてもいます。<br />
なのでこの発言は、参入障壁を作っている側の人の発言と見ると、面白いものがあります。ある種各方面への脅しとも受け取れるわけで（笑）。</p>
<p>ケータイに関する報道はほとんどが機種中心に語られています。<br />
機種（＋メーカー）が最も目に見えるところであるのは確かですが、そこを話の中心にしてしまうと、実際に関わっている重要な要素が全部見えなくなってしまうと思うのです。<br />
今回の記事はそうした報道の中では非常にすばらしいものではありますが、なぜ上記のような問題が正面切って取り上げられないのか、常々疑問に思っていたりします。（受けが悪いんだろうか…？）</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/145/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>新聞社のWebサイトとFlash</title>
		<link>http://lab.flama.co.jp/archives/137</link>
		<comments>http://lab.flama.co.jp/archives/137#comments</comments>
		<pubDate>Tue, 13 Jul 2010 15:34:22 +0000</pubDate>
		<dc:creator>mimori</dc:creator>
				<category><![CDATA[よのなか]]></category>

		<guid isPermaLink="false">http://restinpeace.jp/?p=137</guid>
		<description><![CDATA[最近、大きい選挙があると、新聞社のサイトでは、開票結果がのきなみFlashを使った表示になっています。 ところが、前回のイギリスの総選挙の際に、BBCの開票結果がFlashを使っていないことに気付きました。 http:/ [...]]]></description>
			<content:encoded><![CDATA[<p>最近、大きい選挙があると、新聞社のサイトでは、開票結果がのきなみFlashを使った表示になっています。<br />
ところが、前回のイギリスの総選挙の際に、BBCの開票結果がFlashを使っていないことに気付きました。<br />
<a href="http://news.bbc.co.uk/2/shared/election2010/liveevent/" target="_blank">http://news.bbc.co.uk/2/shared/election2010/liveevent/</a><br />
（選挙が終わってだいぶ経つのにちゃんとこれを残しておくのもすばらしいと思いますが）<br />
思えば、まだFlashがもやっとしたムービーにしか使われていなかったころ、BBCでは実用的な表示にいちはやく取り入れていた記憶があります。<br />
Flashを使わなくても動きのある表示ができるような環境が整ったことや、PC以外での表示も考えて、Flashを使わない方向に舵を切ったのだなあ、と感慨深い気持ちになっていたわけです。</p>
<p>そんな時、日本でも選挙がはじまりました。<br />
はたして、2010年のこの段階で、日本の各新聞社はどのようにこの流れをとらえているんだろう？と気になってみていました。</p>
<p>が、結果は…大手サイトはおしなべてFlashで開票結果を表示していました。<br />
使っちゃいけないと言うつもりはありませんが、考え方の違いは大きいなと思う次第です。<br />
Flashでそれを表示することは、おそらく当事者からするとプロ意識なのでしょう。実績を重んじる姿勢であったり、ごく古い環境にある閲覧者への配慮であったり。と同時に、事実をわかりやすく伝えるという使命に最大限注力した、ということなのだと思います。</p>
<p>しかし、それは世の中に情報を発信することのプロとしては、どうでしょう？<br />
iPhoneを挙げるまでもなく、現にFlashを再生できないデバイスが数百万台以上存在するという事実についてはどう考えているのでしょうか？<br />
BBCの判断には、世の中の流れを敏感に察知してそれを自ら示す、というプロ意志が感じられるのです。そしてそれが本当のプロ意識ではないかと思うのです。</p>
<p>たとえば「IEの古いバージョンを使っているユーザーが不都合が無いように」というような話はよく聞きますが、情報を発信するプロ意識があるのであれば、それがいかに危険な状態であるかを閲覧者に警告するくらいでも良いはずです。<br />
ただやみくもに分かりやすく角のたたない立場に徹しているとしたら、それは単純に自分のやりたいことをやっているに過ぎません。</p>
<p>相手が求めることをするのが相手のためになるわけではない、というと誰もが否定しないと思いますが、実際に当事者になった場合、プロ意識という言葉によってかえってメリットを失う結果になっていることは多いと感じています。<br />

<a href='http://lab.flama.co.jp/archives/137/13-22-14-02' title='13 22 14 02'><img width="150" height="150" src="http://lab.flama.co.jp/wp-content/uploads/2010/07/13-22-14-02-150x150.jpg" class="attachment-thumbnail" alt="13 22 14 02" title="13 22 14 02" /></a>
<a href='http://lab.flama.co.jp/archives/137/13-22-12-58' title='13 22 12 58'><img width="150" height="150" src="http://lab.flama.co.jp/wp-content/uploads/2010/07/13-22-12-58-150x150.jpg" class="attachment-thumbnail" alt="13 22 12 58" title="13 22 12 58" /></a>
<a href='http://lab.flama.co.jp/archives/137/13-22-12-25' title='13 22 12 25'><img width="150" height="150" src="http://lab.flama.co.jp/wp-content/uploads/2010/07/13-22-12-25-150x150.jpg" class="attachment-thumbnail" alt="13 22 12 25" title="13 22 12 25" /></a>
<a href='http://lab.flama.co.jp/archives/137/13-22-11-56' title='13 22 11 56'><img width="150" height="150" src="http://lab.flama.co.jp/wp-content/uploads/2010/07/13-22-11-56-150x150.jpg" class="attachment-thumbnail" alt="13 22 11 56" title="13 22 11 56" /></a>
</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/137/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>同媒体異画質バナーの謎</title>
		<link>http://lab.flama.co.jp/archives/135</link>
		<comments>http://lab.flama.co.jp/archives/135#comments</comments>
		<pubDate>Mon, 05 Jul 2010 13:14:51 +0000</pubDate>
		<dc:creator>mimori</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[よのなか]]></category>

		<guid isPermaLink="false">http://restinpeace.jp/?p=135</guid>
		<description><![CDATA[とある大手メディアサイトを見ていると、レクタングルバナーとして某政党のイメージバナーが出ていました。 これ自体は全くどうでもいい話なわけですが、気になったのは別の部分です。 同じ団体のバナーが先々週くらいにも出ていたので [...]]]></description>
			<content:encoded><![CDATA[<p>とある大手メディアサイトを見ていると、レクタングルバナーとして某政党のイメージバナーが出ていました。<br />
これ自体は全くどうでもいい話なわけですが、気になったのは別の部分です。</p>
<p>同じ団体のバナーが先々週くらいにも出ていたのですが、この時とくらべて、画質が非常に悪いのです。<br />
前回のバナーは、実はレクタングルの位置にはありましたが、その横幅のまま縦に長いものでした。形が違うのでレギュレーションが違うのかもしれませんが、普通に考えると大きいバナーの方が容量の制限は厳しいはずで、実際のバナーの画質はその逆になっているのです。</p>
<p>実は、これで思い出したことがあります。</p>
<p>とある会社のとある案件で、初めてのルートでのバナーを出すことになった際、他のルートでは問題なく受領されたバナー画像が、ある特定のルートでは拒否されたことがあります。もちろん、バナーが表示されるメディアが同じであれば、入稿仕様は同一です。</p>
<p>ではなぜこのような違いが生じるのかというのは単純な問題で、広告主が原稿をメディアに渡すまでの間には様々な人が関与する中で、この仕様が「規則」であるのか、「目安」であるのか、という解釈の相違が発生するのです。<br />
「規則だからこれに100%適合していなければ受け取らない」という人と、実情を知って「だいたい合っているからとりあえず受け取る」という人の２種類の人がいて（前者は少ないとは思いますが）、互いに「ダメな人」「お役所仕事」と言い合っていたりします。</p>
<p>大手メディアサイトになればなるほど、1Byteの違いがネットワーク負荷にかかわってきますので、そういった面では、画像の容量を増やされると困ります。<br />
しかし、広告としての面では、あまりにひどいクオリティの画像が画面を占めても、見た目として困るわけです。</p>
<p>ダメかお役所かという問題はさておいて、この相違によって影響を受けるのはまず広告主と広告を見る人、つまり「お客さん」と「お客さんのお客さん」になるわけで、この感じ自体がお客さんを無視した状態だなーと思う次第です。</p>
<p>仕様は当然のことながら容量をわずかに上回ることは想定されていたりもしますし、メディアは広告主のために、現時点での仕様が厳しすぎるのであれば拡張を検討する意志があります。<br />
しかし、間にいる人たちが何も言わなければ、メディアが新たな広告スペースを作り出さない限りそのままとなります。Webサイトの場合はリニューアルするまでそのまま、ということになります。<br />
仕様がアップデートされるのは、確かに仕事としてはめんどくさいことかもしれません。しかし、これもまた商売なので、逃げられるわけではないでしょう。</p>
<p>Webでの広告は、たとえば効果測定がきっちり数字で出るとか、一見システマチックに見えるにもかかわらず、実はものすごく人に左右されることがあって、しかもそれがそれほどお客さん（＝広告主＋そのお客さん）に得にならないことがあるので、その辺がアヤシげに見えてしまうところなのになあ、と思う次第です。</p>
]]></content:encoded>
			<wfw:commentRss>http://lab.flama.co.jp/archives/135/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

