<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
<title>Suinasia(Tips)</title>
<subtitle>「Tips」なエントリー</subtitle>
<link rel="alternate" type="text/html" href="http://suin.asia/tag/Tips"/>
<link rel="self" type="application/atom+xml" href="http://suin.asia/feed/atom/tag/Tips"/>
<author>
<name>suin</name>
</author>
<updated>2012-02-04T13:28:48Z</updated>
<id>http://example.com/atom1.xml</id>
<entry>
<title>[XOOPS Cube]プリロードでブロックの内容を取得するサンプル</title>
<link href="http://suin.asia/2011/08/17/xoops_preload_get_block_contents"/>
<summary>&lt;p&gt;プリロードでブロックの内容を取得するサンプルです。ブロックのタイトルすべてに「&lt;a href=&quot;http://www.warna.info/archives/1620/&quot;&gt;だぷー&lt;/a&gt;」を付けます&lt;/p&gt;
&lt;p class=&quot;photo&quot;&gt;&lt;a href=&quot;https://pica...</summary>
<published>2011-08-16T15:00:00Z</published>
<updated>2011-08-16T15:00:00Z</updated>
<id>http://suin.asia/2011/08/17/xoops_preload_get_block_contents</id>
<category term="XOOPS" label="XOOPS" scheme="http://suin.asia/tag/XOOPS" />
<category term="プリロード" label="プリロード" scheme="http://suin.asia/tag/%E3%83%97%E3%83%AA%E3%83%AD%E3%83%BC%E3%83%89" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>プリロードでブロックの内容を取得するサンプルです。ブロックのタイトルすべてに「<a href="http://www.warna.info/archives/1620/">だぷー</a>」を付けます</p>
<p class="photo"><a href="https://picasaweb.google.com/lh/photo/mlSjOsrw-AUwUldsYH6ilQ?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/-qTuu6EqRc1I/Tkni-NP2bSI/AAAAAAAABgU/YicdOMr-c04/s800/%2525E3%252582%2525B9%2525E3%252582%2525AF%2525E3%252583%2525AA%2525E3%252583%2525BC%2525E3%252583%2525B3%2525E3%252582%2525B7%2525E3%252583%2525A7%2525E3%252583%252583%2525E3%252583%252588%2525202011-08-16%25252012.24.04.png" height="314" width="187" /></a></p>
<script src="https://gist.github.com/1148371.js?file=gistfile1.aw"></script>]]>
</content>
</entry>
<entry>
<title>Concrete5:サイトタイトル日英対応のTips</title>
<link href="http://suin.asia/2011/07/01/concrete5_switch_title_for_each_language"/>
<summary>&lt;p&gt;Concrete5若葉マークのsuinです。サイトのタイトルを日英で切り替える方法を紹介します。&lt;/p&gt;

&lt;p&gt;ます、前提としてConcrete5(5.4.0.5)は多言語対応機能がないみたいです。ググった範囲ですが。
(本気で日英対応しようと思ったら&lt;a href=&quot...</summary>
<published>2011-07-01T04:09:50Z</published>
<updated>2011-07-01T04:09:50Z</updated>
<id>http://suin.asia/2011/07/01/concrete5_switch_title_for_each_language</id>
<category term="concrete5" label="concrete5" scheme="http://suin.asia/tag/concrete5" />
<category term="tips" label="tips" scheme="http://suin.asia/tag/tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>Concrete5若葉マークのsuinです。サイトのタイトルを日英で切り替える方法を紹介します。</p>

<p>ます、前提としてConcrete5(5.4.0.5)は多言語対応機能がないみたいです。ググった範囲ですが。
(本気で日英対応しようと思ったら<a href="http://www.hodajuku.org/">XOOPSCubeホダ塾ディストリ</a>、<a href="http://modx.jp/">MODx</a>がいんじゃないかな...(´・ω・｀))さておき、多言語対応ない状況下で日英サイトを作る場合は次のようなサイトマップ構成にするのが定石みたいです。確かな情報じゃなくてすみません、なんせ初心者なので。</p>

<pre>
├── en
│   ├── page1
│   ├── page2
│   └── page3
└── ja
    ├── page1
    ├── page2
    └── page3
</pre>

<p>次に、サイトタイトル日英対応とはどういうものか簡単に説明します。日本語ページ(/ja以下)では「○○研究室」、英語ページ(/en以下)では「xxx Laboratory」といったように、サイトのタイトルを切り替える仕組みです。&lt;title&gt;タグはもちろん、&lt;h1&gt;タグに現れるタイトルを切り替えます。</p>

<p>最後に、サイトタイトル日英対応の実装方法を説明します。直感からするとテーマのテンプレートをいじるだけでできそうですが、titleタグをレンダリングしている<code>Loader::element('header_required')</code>が簡単にオーバーライドできないようなので、ちょっとまどろっこしい対応になります。</p>

<p>/config/site.phpに英語の時だけSITE定数を定義する処理を実装します。SITE定数はtitleタグに表示されるサイトタイトルとなります。Concrete5の仕様として、SITE定数が定義することでサイトタイトルをオーバーライドできるみたいです。なので、日本語ページのときは、管理画面で設定したサイトタイトルをそのままつかうことになります。コードの例としては次のようになります。</p>

<pre class="php" name="code">
function is_english()
{
	$requestUri = '/'.trim($_SERVER['REQUEST_URI'], '/').'/';
	return ( strpos($requestUri, '/en/') !== false );
}

if ( is_english() === true )
{
	define('SITE', 'English Site Title');
}
</pre>

<p>これで、サイトタイトルが現れる部分は一括して日英対応できるはずです。Concrete5のView、もうちょっと拡張性に融通がきくようになるといいなぁ〜</p>]]>
</content>
</entry>
<entry>
<title>HTML5でファイル複数同時アップロード</title>
<link href="http://suin.asia/2011/01/23/html5_input_multiple"/>
<summary>HTML5でファイル複数同時アップロード</summary>
<published>2011-01-23T13:05:40Z</published>
<updated>2011-01-23T13:03:51Z</updated>
<id>http://suin.asia/2011/01/23/html5_input_multiple</id>
<category term="HTML5" label="HTML5" scheme="http://suin.asia/tag/HTML5" />
<category term="PHP" label="PHP" scheme="http://suin.asia/tag/PHP" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<category term="試してみた" label="試してみた" scheme="http://suin.asia/tag/%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p><a href="http://www.w3.org/TR/2011/WD-html-markup-20110113/input.file.html">W3CのHTML5草稿</a>によると、<code>&lt;input type=&quot;file&quot;...&gt;</code>タグにmultiple属性が追加されたようです。この属性がセットされた<code>&lt;input type=&quot;file&quot;...&gt;</code>は、複数のファイルを選択してアップロードできるようになります。複数のファイルを選択する方法はOSによって異なります。Windowsではctrl+クリック、MacOSではCommand+クリック。あるいは、Shift+クリックで範囲選択することができます。</p>

<h3>試せる環境を用意する</h3>

<p>multiple属性に対応しているブラウザとしては、Webkit系のGoogle Chrome、Safariがあるみたいです。今回は、Safari 5.0.3(MacOSX 10.6.5上)で試してみました。</p>

<p>ファイルアップロードが正しくアップロードされたか確認するためにPHPのプログラムを用意しました。そのソースコードは次のようになっています。<code>&lt;input type=&quot;file&quot;...&gt;</code>にセットされたファイルは、PHPではその情報がグローバル変数<code>$_FILES</code>に代入されます。下のプログラムでは、<code>$_FILES</code>の内容を出力します。</p>

<pre class="php" name="code">
&lt;html&gt;
&lt;head&gt;&lt;/head&gt;
&lt;body&gt;
&lt;form action=&quot;&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
Files:&lt;input type=&quot;file&quot; name=&quot;files[]&quot; multiple&gt;
&lt;input type=&quot;submit&quot; value=&quot;submit&quot;&gt;
&lt;/form&gt;
&lt;pre&gt;
&lt;?php
if ( $_SERVER['REQUEST_METHOD'] === 'POST' )
{
	var_dump($_FILES);
}
?&gt;
&lt;/pre&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

<h3>試してみる</h3>

<p>用意したプログラムをSafari5で開いてみます。multipleだからといって特に変わった表示にはならないようです。</p>
<p class="photo"><img src="http://lh4.ggpht.com/_dG0BBWAhWis/TTwmHf96yfI/AAAAAAAABWg/LSkJELoFqMw/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-01-23%2021.44.07%EF%BC%89.png" /></p>

<p>次に、Shiftを押しながらファイル複数選択を試みます。すると、選択されたファイルはハイライトされて、ブラウザ上でちゃんと複数選択が機能しているのがわかります。</p>
<p class="photo"><a href="http://picasaweb.google.com/lh/photo/-Nspnq-f_LQlpNUFf8o29g?feat=embedwebsite"><img src="http://lh3.ggpht.com/_dG0BBWAhWis/TTwmHMSu0CI/AAAAAAAABWU/CVE9__LIBfU/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-01-23%2021.30.42%EF%BC%89.png" height="354" width="400" /></a></p>

<p>ファイル選択のダイアログが閉じると、「6ファイル」と選択したファイル数が画面に出ました。</p>
<p class="photo"><a href="http://picasaweb.google.com/lh/photo/Z37M-QDSBwuriVnYpQVPEQ?feat=embedwebsite"><img src="http://lh4.ggpht.com/_dG0BBWAhWis/TTwmHGBvxJI/AAAAAAAABWY/HQM62O9XySA/s288/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-01-23%2021.31.08%EF%BC%89.png" height="38" width="288" /></a></p>

<p>最後に、送信して<code>$_FILES</code>の内容を確認してみます。ちゃんとサーバにもファイルが送信されていることが確認できました。</p>
<p class="photo"><a href="http://picasaweb.google.com/lh/photo/kd3zsfiELrvOwmJwbYwGrg?feat=embedwebsite"><img src="http://lh3.ggpht.com/_dG0BBWAhWis/TTwmHTDZt8I/AAAAAAAABWc/ya-f6emGc5o/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-01-23%2021.31.22%EF%BC%89.png" height="372" width="400" /></a></p>


<h3>はまりどころ</h3>
<p>単に、<code>&lt;input type=&quot;file&quot;...&gt;</code>に<code>muliple</code>属性を付けただけでは複数ファイルアップロードできないようです。<code>name</code>属性にカギカッコを付け、明示的に配列にする必要があるようです。</p>

<h3>HTML5すげぇ</h3>
<p>些細な機能追加だけど、ある意味 革命的な機能だよねー。
今までファイル複数選択を実装しようとしたら、FlashやSilverLightを使わないと無理だったし。
ウェブアプリの開発現場で、たまに複数アップロードの対応をお願いされることがあったけど、
Flashなどで対応するとコストが増すので、<code>&lt;input type=&quot;file&quot;...&gt;</code>を複数個配置するような
対処してきたし。しかし、HTML5が普及していけば、こうした要望には低コストで
答えることができるし、ユーザの満足度も高まるんじゃないかな。
さすが、ウェブアプリに尖ったHTML5。びっくり。</p>

<p>#あ、気づいたら日本語でブログ書いてた。英語で書くって決めたのに。この手の日本語リソースなさそうだし、まいっか。</p>]]>
</content>
</entry>
<entry>
<title>CSS3で何の変哲もない画像をiPhone,iOS風のアイコンに変身させる</title>
<link href="http://suin.asia/2011/01/14/make_iphone_ios_icon_with_css3"/>
<summary>CSS3を使って、図1のような普通の画像を、図2のようにiPhone,iOS風のアイコンに変身させるTipsを紹介します。</summary>
<published>2011-01-14T09:40:00Z</published>
<updated>2011-01-14T09:37:15Z</updated>
<id>http://suin.asia/2011/01/14/make_iphone_ios_icon_with_css3</id>
<category term="CSS" label="CSS" scheme="http://suin.asia/tag/CSS" />
<category term="iPhone" label="iPhone" scheme="http://suin.asia/tag/iPhone" />
<category term="iOS" label="iOS" scheme="http://suin.asia/tag/iOS" />
<category term="HTML" label="HTML" scheme="http://suin.asia/tag/HTML" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>CSS3を使って、図1のような普通の画像を、図2のようにiPhone,iOS風のアイコンに変身させるTipsを紹介します。
とりあえず、デモが見たい人は<a href="http://dl.dropbox.com/u/949822/SuinAsia/20110114/index.html">こちら</a>。
このTipsを紹介するにあたって、参考にしたサイトが<a href="http://graphicpeel.com/cssiosicons">こちら</a>になります。</p>

<p class="photo"><img src="http://dl.dropbox.com/u/949822/SuinAsia/20110114/1.png" /><br />
図1</p>
<p class="photo"><img src="http://dl.dropbox.com/u/949822/SuinAsia/20110114/demo.png" /><br />
図2</p>

<h3>iPhone, iOSのアイコンの特徴</h3>

<ul>
<li>角丸</li>
<li>グロス（上半分の反射）効果がある。グロスはグラデーションが効いている。</li>
<li>上ボーダーが白(反射)</li>
<li>下ボーダーが黒(影)</li>
<li>うっすらとアイコンの影が背面にある</li>
<li>タップしたとき、アイコンの明るさが暗くなる(dark light効果)</li>
</ul>

<h3>CSS3でやること</h3>

<p>下の画像をiPhone,iOS風のアイコンに近づけるために、上の各特徴を次の方法で再現していきます。</p>

<p class="photo"><img src="http://dl.dropbox.com/u/949822/SuinAsia/20110114/1.png" /></p>

<ul>
<li>角丸: border-radiusを使って角丸を表現する</li>
<li>グロス: span.grossをアイコン画像に重ね、border-radiusで緩やかなカーブを表現する。また、gradiantを使ってグラデーションを表現する。</li>
<li>上ボーダーが白: box-shadowを使って、上ボーダーを白くする</li>
<li>下ボーダーが黒: box-shadowを使って、下ボーダーを黒くする</li>
<li>アイコン背面の影: box-shadowを使って、うっすらとした影を表現する</li>
<li>タップ時のdark light: グレーで塗りつぶしたspan.dark-lightをアイコンに重ねておき、:activeのとき一定の透過率で表示する</li>
</ul>

<h3>実装方法</h3>

<p>HTMLは次のような構成になります。</p>

<pre name="code" class="html">
&lt;a href=&quot;#&quot; class=&quot;icon&quot;&gt;
&lt;span class=&quot;gross&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;shadow&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;dark-light&quot;&gt;&lt;/span&gt;
&lt;/a&gt;
</pre>

<p class="photo"><img src="http://dl.dropbox.com/u/949822/SuinAsia/20110114/node.png" /></p>

<ul>
<li>a.icon: アイコン画像表示用</li>
<li>span.gross: グロス表現用</li>
<li>span.dark-light: タップ時のdark light効果用</li>
<li>span.shadow: アイコン背面の影用</li>
</ul>

<p>スタイルシートは次のようになります。</p>
<pre name="code" class="css">
.icon {
	display: block;
	height: 89px;
	width: 89px;

	background: transparent url('1.png') no-repeat;

	-webkit-border-radius: 10px; /* Safari, Chrome */
	-moz-border-radius: 10px; /* Firefox */
	border-radius: 10px; /* CSS3 */

	-webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.7);
	-moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.7);
	-o-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.7);
	box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.7);
	}

.icon:active,
.icon:focus {
	outline: none;
	-moz-outline-style: none;
	}

.icon:active .dark-light,
.icon:active .gross {
	-ms-filter: "alpha(opacity=50)";
	filter: alpha(opacity=50);
	opacity: 0.5;
	}

.dark-light {
	display: block;
	height: 89px;
	width: 89px;
	background: #000;
	cursor: pointer;

	-ms-filter: "alpha(opacity=0)";
	filter: alpha(opacity=0);
	opacity: 0;

	-webkit-border-radius: 10px; /* Safari, Chrome */
	-moz-border-radius: 10px; /* Firefox */
	border-radius: 10px; /* CSS3 */
	}

.gross {
	display: block;
	position: absolute;
	z-index: 5;
	width: 89px;
	height: 50px;
	cursor: pointer;
	
	/* Opera */
	background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIHgxPSIwJSIgeTE9IjAlIiB4Mj0iMCUiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2JhKDI1NSwyNTUsMjU1LDAuNyk7IiAvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiYSgyNTUsMjU1LDI1NSwwLjIpOyIgLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCBmaWxsPSJ1cmwoI2dyYWRpZW50KSIgaGVpZ2h0PSIxMDAlIiB3aWR0aD0iMTAwJSIgLz48L3N2Zz4=);
	/* Safari, Chrome */
	background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, 0.7)), to(rgba(255, 255, 255, 0.2)));
	/* Firefox */
	background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.2));
	/*Internet Explorer 6,7 and 8*/
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#B3FFFFFF, endColorstr=#33FFFFFF, GradientType=0);
	/*Internet Explorer 8 only*/
	-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#B3FFFFFF, endColorstr=#33FFFFFF, GradientType=0)";

	/* Safari, Chrome */
	-webkit-border-top-right-radius: 10px;
	-webkit-border-top-left-radius: 10px;
	-webkit-border-bottom-right-radius: 60px 10px;
	-webkit-border-bottom-left-radius: 60px 10px;

	/* Firfox */
	-moz-border-radius-topright: 10px;
	-moz-border-radius-topleft: 10px;
	-moz-border-radius-bottomright: 60px 10px;
	-moz-border-radius-bottomleft: 60px 10px;

	/* CSS3 */
	border-top-right-radius: 10px;
	border-top-left-radius: 10px;
	border-bottom-right-radius: 50px 12px;
	border-bottom-left-radius: 50px 12px;

	
	-webkit-box-shadow: inset 0px 2px 1px rgba(255, 255, 255, 0.7); /* Safari, Chrome */
	-o-box-shadow: inset 0px 2px 1px rgba(255, 255, 255, 0.7); /* Opera */
	-moz-box-shadow: inset 0px 2px 1px rgba(255, 255, 255, 0.7); /* Firefox */
	box-shadow: inset 0px 2px 1px rgba(255, 255, 255, 0.7);
	}

.shadow {
	display: block;
	position: absolute;
	z-index: 5;
	width: 89px;
	height: 89px;
	cursor: pointer;

	-webkit-border-radius: 10px; /* Safari, Chrome */
	-moz-border-radius: 10px; /* Firefox */
	border-radius: 10px; /* CSS3 */

	-moz-box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
	-webkit-box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
	box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
	
	}
</pre>

<h3>デモとか</h3>

<a href="http://dl.dropbox.com/u/949822/SuinAsia/20110114/index.html">デモ</a>はこちら。

<h3>対応ブラウザとか</h3>

<p>IEなど、CSS3に対応していないブラウザでは、一部の表現が正しく現れません。見た人は、ブラウザのバージョンと見た目を報告してもらえると助かります。</p>]]>
</content>
</entry>
<entry>
<title>Concrete5の管理者パスワードを忘れたとき再設定する方法</title>
<link href="http://suin.asia/2010/03/15/how_to_recover_admin_password_at_concrete5"/>
<summary>XOOPS以外のCMSはあまり使ってないですが、CMSとして統一感・完成度が高いConcrete5を試してみました。MAMPで構築したローカル環境にConcrete5をインストールしたのですが、うっかり管理者のパス</summary>
<published>2010-03-15T14:43:12Z</published>
<updated>2010-03-15T14:13:51Z</updated>
<id>http://suin.asia/2010/03/15/how_to_recover_admin_password_at_concrete5</id>
<category term="Concrete5" label="Concrete5" scheme="http://suin.asia/tag/Concrete5" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>XOOPS以外のCMSはあまり使ってないですが、CMSとして統一感・完成度が高いConcrete5を試してみました。MAMPで構築したローカル環境にConcrete5をインストールしたのですが、うっかり管理者のパスワードを忘れてしまいました。</p>
<p>通常、パスワードを忘れた場合、メールでリマインドできるようです。が、あいにくローカル環境ということもあり、メール送信が動かない…。</p>
<p>もしや、データベースに生パスワードが保存されているのでは？と思いデータベースを見てみました。すると、UsersテーブルにuPasswordというカラムがあるじゃないですか。しめたと思って、中身を見てみたらばっちり暗号化されていました。さすがに、最近のCMSはパスワードを生で保存しておくなんてことはしないようです。</p>
<p>PHPをやっている人ならこの暗号化は、md5()だとわかったので、<code>md5('admin')</code>を実行して、それをuPasswordに保存してadmin@adminでログインを試みました。それでも、依然としてログインできません。パスワードが間違っているといいます。</p>
<p>この手の物は、たいていパスワードにprefixを付けている可能性があるので、ソースをおってみると、案の定<code>PASSWORD_SALT</code>が付け加えられたmd5()されてました。</p>
<h3>謎がすべてとけたところで、再設定方法</h3>
<ol>
<li>/Applications/MAMP/htdocs/concrete5/config/site.phpを開く。</li>
<li><pre name="code" class="php">
&lt;?php 
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'root');
define('DB_PASSWORD', 'root');
define('DB_DATABASE', 'concrete5');
define('BASE_URL', 'http://localhost');
define('DIR_REL', '/concrete5');
define('PASSWORD_SALT', 'BtL4OCqEYan5yZrDVHUhKcFbNzmp3Q1A7uToifeWMwSv8Xsx0jkG2l6J9RPIg');
?&gt;
</pre>
この中のPASSWORD_SALTの値をコピー。この例だと、BtL...Plgの部分です。</li>
<li>/Applications/MAMP/htdocs/pass.phpを作成。</li>
<li>
<pre name="code" class="php">
&lt;?php

$salt = 'BtL4OCqEYan5yZrDVHUhKcFbNzmp3Q1A7uToifeWMwSv8Xsx0jkG2l6J9RPIg';
$password = 'admin';
echo md5($password . ':' . $salt);

?&gt;
</pre>
pass.phpの中身を上のように書く。$salt = '';の部分はsite.phpでコピーした値を書く。ここでは、「admin」をパスワードとして設定します。adminが嫌なら他のものに変えてOK。</li>
<li>ブラウザでpass.phpにアクセスする。</li>
<li>表示された32文字「65f7ed3aff95ce2394d6458c442eb3b0」などをコピーする。</li>
<li>phpMyAdminで、Concrete5のデータベースを開く。</li>
<li>SQLで下のクエリーを実行する。65f...3b0の部分は先程ブラウザでコピーしたものに変えてください。
<pre name="code" class="sql">UPDATE  `Users` SET  `uPassword` =  '65f7ed3aff95ce2394d6458c442eb3b0' WHERE  `uID` =1;</pre></li>
<li>Concrete5に戻ってログインしてみる。</li>
<li>pass.phpを削除する。</li>
</ul>
<p>パスなどは適宜読みかえてください。</p>]]>
</content>
</entry>
<entry>
<title>jQueryの世界で最も単純なプラグインの作り方サンプル</title>
<link href="http://suin.asia/2010/02/04/the_simplest_plugin_for_jquery"/>
<summary>jQueryは要素セレクターやクロスブラウザ対応が優れたjavascriptのライブラリで、prototype.jsと並んで広く使われています。そのjQueryでは、独自に自前の関数をプラグインという形で作ることが</summary>
<published>2010-02-03T23:29:00Z</published>
<updated>2010-02-03T23:17:00Z</updated>
<id>http://suin.asia/2010/02/04/the_simplest_plugin_for_jquery</id>
<category term="jQuery" label="jQuery" scheme="http://suin.asia/tag/jQuery" />
<category term="javascript" label="javascript" scheme="http://suin.asia/tag/javascript" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>jQueryは要素セレクターやクロスブラウザ対応が優れたjavascriptのライブラリで、prototype.jsと並んで広く使われています。そのjQueryでは、独自に自前の関数をプラグインという形で作ることができます。jQueryプラグインの作り方は検索すれば山ほど出てきますが、その第一歩となるプラグインの基本的な書き方が見つからなかったので記事にしておこうと思います。</p>
<p>次のプラグインは、単に文字色を赤くするだけのものです。<code>myplugin</code>がプラグイン名です。<code>$(this).css('color', 'red');</code>の部分以外がプラグインの骨組みとなり、この部分だけ差し替えれば、全く別のプラグインを作ることができます。</p>
<pre name="code" class="js">
(function($){
	$.fn.myplugin = function() {
		return this.each(function() {
			$(this).css('color', 'red');
		});
	};
})(jQuery);
</pre>
<p>このプラグインの<a href="http://suin.org/jquery/jquery_the_simplest_plugin.html">動作デモ</a></p>]]>
</content>
</entry>
<entry>
<title>XOOPS 一般設定しかない管理画面は一般設定に転送する</title>
<link href="http://suin.asia/2010/01/28/xoops_redirect_to_preference"/>
<summary>モジュールを作っていると、管理画面に一般設定しかないというケースがあります。この場合、管理画面のトップ(/admin/index.php)は空白のページになってしまい、なんとも不格好です。見た目</summary>
<published>2010-01-27T15:59:34Z</published>
<updated>2010-01-27T15:54:23Z</updated>
<id>http://suin.asia/2010/01/28/xoops_redirect_to_preference</id>
<category term="XOOPS" label="XOOPS" scheme="http://suin.asia/tag/XOOPS" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<category term="PHP" label="PHP" scheme="http://suin.asia/tag/PHP" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>モジュールを作っていると、管理画面に一般設定しかないというケースがあります。この場合、管理画面のトップ(/admin/index.php)は空白のページになってしまい、なんとも不格好です。見た目もそうですが、操作性をあげるためにも、管理画面のトップが空白の場合は一般設定に転送してあげましょう。</p>

<p>そして下がそのコード。</p>

<pre name="code" class="php">
require "../../../mainfile.php";

$mid = $xoopsModule->mid();

if ( defined('XOOPS_CUBE_LEGACY') )
{
	$url = sprintf('%s/modules/legacy/admin/index.php?action=PreferenceEdit&confmod_id=%u', XOOPS_URL, $mid);
}
else
{
	$url = sprintf('%s/modules/system/admin.php?fct=preferences&op=showmod&mod=%u', XOOPS_URL, $mid);
}

header('Location: '.$url);
</pre>]]>
</content>
</entry>
<entry>
<title>XOOPS Cube + preload でカスタムブロックを作成する方法</title>
<link href="http://suin.asia/2010/01/25/preload_block"/>
<summary>XOOPSCubeのpreloadでカスタムブロックを作ることができます。</summary>
<published>2010-01-25T09:10:35Z</published>
<updated>2010-01-25T08:30:10Z</updated>
<id>http://suin.asia/2010/01/25/preload_block</id>
<category term="XOOPS" label="XOOPS" scheme="http://suin.asia/tag/XOOPS" />
<category term="プリロード" label="プリロード" scheme="http://suin.asia/tag/%E3%83%97%E3%83%AA%E3%83%AD%E3%83%BC%E3%83%89" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>カスタムブロックは、通常legacyモジュールやaltsysで作ることができます。ここでは、プリロードでカスタムブロックを作ることを紹介します。</p>

<p>その前に、ここで紹介するTipsは、管理画面でカスタムブロックを作るより、はるかに回りくどくPHPの知識が必要な点を注意しておきます。なので、特殊な機能や要件を必要としない限り、カスタムブロックは管理画面で作るべきです。</p>

<p>まず、XOOPS Cubeのプリロードでカスタムブロックを作るメリットはいくつかあります。</p>

<ul>
<li>ファイルとして配布できる</li>
<li>ファイルなので、不要になれば削除するだけ</li>
<li>PHPなどの複雑なロジックが書きやすい（通常のカスタムブロックでもPHPは使えます）</li>
</ul>

<p>特にこの中でも、ファイルとして扱えるメリットは大きいです。たとえば、開発環境で一定の変数を出力したりとデバッグ用途にブロックをプリロードで実装します。あとは、公開するときにプリロードを削除するだけで、データベースを汚したりすることは一切ありません。管理画面で操作するブロックだと、ついつい消し忘れ・消し損ないなんてこともありますが、プリロードだとファイルを確実に削除すれば、消し損なうこともありません。</p>

<a href="http://dl.dropbox.com/u/949822/Downloads/PreloadBlock.class.php" class="download">ダウンロード</a>
<p>次に、プリロードのソースを紹介します。16行目の$indexが、ブロックを表示する位置になります。l, r, cl, cc, crの順に、左・右・中央左・中央中・中央右を意味します。</p>

<p>18行目から22行目はブロックの表示に関する設定です。nameはブロック名で、アルファベット英数ですきな名前を指定します。titleはブロックの題目で、ブロックの上部に表示されます。contentはブロックの内容で、HTMLなどで書くことができます。weightはブロックの並び順で、数値が小さいほど上に、数値が多きほど下にブロックが表示されます。</p>

<pre name="code" class="php">
&lt;?php
/**
 * A simple description for this script
 *
 * PHP Version 5.2.4 or Upper version
 *
 * @package    PreloadBlock
 * @author     Hidehito NOZAWA aka Suin &lt;http://suin.asia/&gt;
 * @copyright  2009 Hidehito NOZAWA
 * @license    http://www.gnu.org/licenses/gpl-2.0.html GNU GPL v2.0
 *
 */

class PreloadBlock extends XCube_ActionFilter
{
	protected $index = 'l';
	protected $block = array(
		'id'      =&gt; -1,
		'name'    =&gt; 'preload_block',
		'title'   =&gt; 'プリロードブロック',
		'content' =&gt; '&lt;i&gt;ブロックの内容&lt;/i&gt;',
		'weight'  =&gt; -1, // 並び順
	);
	protected $indexes = array(
		'l' =&gt; 0,
		'r' =&gt; 1,
		'cl' =&gt; 3,
		'cr' =&gt; 4,
		'cc' =&gt; 5
	);
	protected $blocks = array(
		'l' =&gt; 'xoops_lblocks',
		'r' =&gt; 'xoops_rblocks',
		'cl' =&gt; 'xoops_clblocks',
		'cr' =&gt; 'xoops_crblocks',
		'cc' =&gt; 'xoops_ccblocks'
	);

	public function postFilter()
	{
		if ( $this-&gt;mController-&gt;_mStrategy-&gt;mStatusFlag != LEGACY_CONTROLLER_STATE_PUBLIC )
		{
			return;
		}

		$this-&gt;mRoot-&gt;mDelegateManager-&gt;add('Legacy_RenderSystem.BeginRender', array(&amp;$this, 'beginRender'));
		$this-&gt;mRoot-&gt;mContext-&gt;mAttributes['legacy_BlockShowFlags'][$this-&gt;indexes[$this-&gt;index]]  = true;
		$this-&gt;mRoot-&gt;mContext-&gt;mAttributes['legacy_BlockContents'][$this-&gt;indexes[$this-&gt;index]][] = $this-&gt;block;
	}

	protected function beginRender(&amp;$tpl)
	{
		if ( !empty($tpl-&gt;_tpl_vars['isFileTheme']) )
		{
			uasort($tpl-&gt;_tpl_vars[$this-&gt;blocks[$this-&gt;index]], array(&amp;$this, 'reOrder'));
		}
	}

	protected function reOrder($a, $b)
	{
		if ($a['weight'] == $b['weight'])
		{
			return 0;
		}
		return $a['weight'] &gt; $b['weight'] ? 1 : -1;
	}
}

?&gt;
</pre>

<p>なお、このプリロードはしゃのさんの<a href="http://petitoops.com/modules/chalog/?action=BlogView&id=392">nowプリロード</a>を参考にさせていただきました。</p>]]>
</content>
</entry>
<entry>
<title>MacBook Air + VMware Fusion + Windows XP 実用範囲内</title>
<link href="http://suin.asia/2009/11/29/macbook_vmware_windows_xp"/>
<summary>acユーザの弱点は、まわりがWindowsユーザという点だと思う。 急にWindows環境が必要になることは しばしばある。 そんなときは、VMwareをインストールしておくと便利だ。</summary>
<published>2009-11-29T06:51:13Z</published>
<updated>2009-11-29T06:44:09Z</updated>
<id>http://suin.asia/2009/11/29/macbook_vmware_windows_xp</id>
<category term="Mac" label="Mac" scheme="http://suin.asia/tag/Mac" />
<category term="Windows" label="Windows" scheme="http://suin.asia/tag/Windows" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<category term="おすすめ" label="おすすめ" scheme="http://suin.asia/tag/%E3%81%8A%E3%81%99%E3%81%99%E3%82%81" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>Windows 7発売で、Windows XPのCDが眠っている状況が出て来ると思う。
まだまだWindows XPは現役。眠らせておくのは勿体ない。
Macを持っている場合は、MacにWindows XP環境を完備しておくのもいいだろう。
Mac OS XでWindwos XPなどのOSを実行できるアプリにVMware Fusionというものがあるので、ここでは私がMacBook Airで使ってみた感想を書きたいと思う。</p>

<p class="photo">
<a href="http://picasaweb.google.co.jp/lh/photo/oStPRqdngph9nATkCCvPEA?feat=embedwebsite"><img src="http://lh4.ggpht.com/_dG0BBWAhWis/SxIYsaYc2zI/AAAAAAAAAuc/LRo5GtEdzHA/s400/%E3%83%94%E3%82%AF%E3%83%81%E3%83%A3%202.png" /></a>
</p>

<p>VMwareでWindows XPを使うのはどういう感じかというと、まるでWindows XPがMacのアプリの1つのように動かすというイメージだ。
したがって、次のような利点がある。</p>
<ul>
<li>MacとWindows XPを同時進行で使用できる。</li>
<li>コピー&ペーストができる。</li>
<li>ファイルの共有が簡単にできる。</li>
<li>MacでダウンロードしたファイルがWindowsでしか開けない場合もすぐに開くことができる。</li>
</ul>

<h3>スペック的に大丈夫か?</h3>

<p>気になるのはMacBook AirでVMwareが実用に堪えるかだ。
MacBook Airのスペックは次のとおりであるが、
同時に2つのOSを動かすには若干不安がのこる。</p>

<ul>
<li>プロセッサ : 1.6 GHz Intel Core 2 Duo</li>
<li>メモリ : 2 GB 1067 MHz DDR3</li>
<li>ハードディスク : 1.8 inch 80 GB</li>
</ul>

<h3>実際にVMwareにWindows XPを入れてみた感想</h3>

<p>MacBook Air + VMware Fusionを使い始めて半年くらいになる。
結論から言うと、VMware Fusion + Windows XPは実用範囲内である。
Office Word 2003を起動して文章を作成したり、
Internet Explorerでネットサーフィンする程度はまったく問題なかった。</p>

<p>しかし、次のような問題点は、一工夫必要だ。</p>

<ul>
<li>VMwareでWindows XPを再開するまでに20秒くらいかかる。(普通にWindowsを起動するよりはいいか)</li>
<li>Mac側で起動中のソフトが多いと、Windows XPも重くなる。</li>
</ul>

<p>Windows XPを再開するまでの時間を短縮するのは、あまり効果的な方法がないと思う。
Windowsをサスペンドするときに、不要なソフトは終了しておくなどすると、若干早くなる。</p>

<p>Mac側で起動中のソフトはできるだけ少なくすると、VMwareも軽く動作する。
私の場合、VMwareで長時間作業する場合は、一旦Macを再起動するようにしている。
起動直後にVMwareを実行すると、すいすいと動く。</p>

<p>余談だが、MacBook AirにはDVDドライブがないので、Windowsをインストールする際には外付けのDVDドライブが必要になる。</p>

<p>Macユーザの弱点は、まわりがWindowsユーザという点だと思う。
急にWindows環境が必要になることは しばしばある。
そんなときは、VMwareをインストールしておくと便利だ。</p>

<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_top&bc1=FFFFFF&IS2=1&nou=1&bg1=FFFFFF&fc1=333333&lc1=0088FF&t=suinyeze-22&o=9&p=8&l=as1&m=amazon&f=ifr&asins=B002CJM7RG" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_top&bc1=FFFFFF&IS2=1&nou=1&bg1=FFFFFF&fc1=333333&lc1=0088FF&t=suinyeze-22&o=9&p=8&l=as1&m=amazon&f=ifr&asins=B0012X30H4" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_top&bc1=FFFFFF&IS2=1&nou=1&bg1=FFFFFF&fc1=333333&lc1=0088FF&t=suinyeze-22&o=9&p=8&l=as1&m=amazon&f=ifr&asins=B002TK93ZW" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>]]>
</content>
</entry>
<entry>
<title>iPod touchをCMR-250でどこでもインターネットする方法</title>
<link href="http://suin.asia/2009/10/18/ipod_touch_with_cmr_250"/>
<summary>ipod touchとCMR-250を併用することで、あなたのtouchがiPhoneのようになります。</summary>
<published>2009-10-21T12:30:05Z</published>
<updated>2009-10-18T10:20:41Z</updated>
<id>http://suin.asia/2009/10/18/ipod_touch_with_cmr_250</id>
<category term="iPod" label="iPod" scheme="http://suin.asia/tag/iPod" />
<category term="touch" label="touch" scheme="http://suin.asia/tag/touch" />
<category term="iPhone" label="iPhone" scheme="http://suin.asia/tag/iPhone" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<category term="おすすめ" label="おすすめ" scheme="http://suin.asia/tag/%E3%81%8A%E3%81%99%E3%81%99%E3%82%81" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>iPod touchとiPhoneの大きな違いのひとつに、touchはWiFi(無線LAN)がないとネットが使えないという点がある。touch向けにもオンラインで使えるアプリが多く公開されている。なのに、外出先で使えないなど、場所が限られるというのは実にもったいない。このエントリーでは、モバイル無線ルータを使って、外出先でもネットを使えるようにする方法を紹介する。</p>
<p>モバイル無線ルータは、バッテリーを積んだ無線ルータだ。外出先などでスイッチをONにすれば、瞬く間にあなたがアクセスポイントになる。モバイル無線ルータには<a href="http://www.amazon.co.jp/gp/product/B001212ELY?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=B001212ELY">PHS300</a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=B001212ELY" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />や<a href="http://www.amazon.co.jp/gp/product/B002MZYLJC?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=B002MZYLJC">CMR-250</a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=B002MZYLJC" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />などがある。これらは、<a href="http://emobile.jp/products/lineup_usb.html">イーモバイルのデータカード</a>と組み合わせて使う。なので、イーモバイルが使えるところであれば、どこでもインターネットが使えることになる。私はCMR-250を買ったので、少し紹介したい。</p>
<p>買うときにPHS300とCMR-2500のどちらにするか迷った。このうちCMR-250を選んだ理由は、主に次の通りバッテリー面だ。</p>
<ul>
<li>PHS300よりバッテリーのもちがいい</li>
<li>PHS300はUSB充電できないが、CMR-250はUSB充電可能</li>
<li>CMR-250は予備のバッテリー(<a href="http://www.amazon.co.jp/gp/product/B002HBQMWA?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=B002HBQMWA">NP-120</a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=B002HBQMWA" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />)が手に入る</li>
</ul>
<p>PHS300は試したことがないが、CMR-250のバッテリーのもちに関しては、実用レベルだと言える。通信を行わないアイドリング状態では、3時間以上起動した。(計測を途中で断念したので、もっと起動するかも)常に通信を行う状態でも、2時間ぐらいは使えるという印象だ。</p>
<p>CMR-250のパッケージは下のようである。</p>
<p class="photo"><a href="http://picasaweb.google.co.jp/lh/photo/csVYEN8KTr9faREnL25hGw?feat=embedwebsite"><img src="http://lh6.ggpht.com/_dG0BBWAhWis/StrebXmqTxI/AAAAAAAAAsQ/XazsDg_hFqs/s400/DSCF3179.JPG" /></a></p>
<p>気になるCMR-250の大きさだが、iPod touchと比べると分かりやすい。幅は、touchより長めだが、縦はtouchと同じくらいだ。鞄にいれても荷物にならない程度だ。</p>
<p class="photo"><a href="http://picasaweb.google.co.jp/lh/photo/DNHjGNLG453svnIfPRXMGg?feat=embedwebsite"><img src="http://lh3.ggpht.com/_dG0BBWAhWis/Streb9QJaeI/AAAAAAAAAsU/nD9W29YeBOU/s400/DSCF3181.JPG" /></a></p>
<p>USBポートは側面にある。なので、直接データカードを差し込むと、それが出っ張る。これが嫌な人は、角度を変えられるUSBコネクター(<a href="http://www.amazon.co.jp/gp/product/B0007NXUMA?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=B0007NXUMA">AD-3DUSBW9</a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=B0007NXUMA" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />など)を使うといい。</p>
<p class="photo"><a href="http://picasaweb.google.co.jp/suinyeze/2009?feat=embedwebsite#5393868081704111682"><img src="http://lh6.ggpht.com/_dG0BBWAhWis/StrecT9KjkI/AAAAAAAAAsY/lBnunD7vkGA/s400/DSCF3222.JPG" /></a></p>
<p>こんな感じで、iPod touchがiPhoneのように、どこでもインターネットが使えるようになる。これで、外出先でtwitterしたり、メールを確認したり、touchのGPS機能をつかって現在地を調べたり、ネットラジオを聞いたり、可能性は無限大に広がると思う。</p>
<iframe src="http://rcm-jp.amazon.co.jp/e/cm?lt1=_top&bc1=FFFFFF&IS2=1&nou=1&bg1=FFFFFF&fc1=333333&lc1=004993&t=suinyeze-22&o=9&p=8&l=as1&m=amazon&f=ifr&asins=B002MZYLJC" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>]]>
</content>
</entry>
<entry>
<title>ローカルストレージを使ってiPhoneのcookie健忘症対策: ウェブアプリ開発者の立場から</title>
<link href="http://suin.asia/2009/09/13/iphone_local_strage_for_email_password_remainder"/>
<summary>iPhoneのsafariはcookieが勝手に消える。IDやパスワードの記憶機能もない。その代替策として、ローカルストレージを使用する。</summary>
<published>2009-09-13T07:46:40Z</published>
<updated>2009-09-13T07:43:04Z</updated>
<id>http://suin.asia/2009/09/13/iphone_local_strage_for_email_password_remainder</id>
<category term="iPhone" label="iPhone" scheme="http://suin.asia/tag/iPhone" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<category term="JavaScript" label="JavaScript" scheme="http://suin.asia/tag/JavaScript" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>iPhoneはcookieがしばしば勝手に消えるようだ。そのせいで、セッションが切れる。すると、GmailやDropboxなどのウェブアプリはログアウトしていまい、IDとパスワードを入力し直す手間が出るので、たちまち不便になる。</p>
<p>セッションが落ちるのは仕方がないとする。それでも、IDやパスワードの記憶ぐらいはしておきたい。iPhoneのキーボードでメールアドレスとパスワードを入力するのは、えらく苦痛だからだ。iPhone向けウェブアプリの開発者としては、できるだけユーザの不便を解消してやりたいはずだ。</p>
<p>iPhoneのsafariにはパスワードの記憶機能がない。その代替策として、パスワードなどをcookieに保存する方法が考えるかもしれない。mixiなどもこの方法だ。しかし、上で述べたが、iPhoneのcookieはよく無くなる。そこで、さらにcookieの代替策として、safariのローカルストレージを使う手がある。</p>
<p>ローカルストレージとは？</p>
<p>iPhoneのsafariにはjavascriptで使えるSQLiteが用意されている。ローカルストレージはcookieと違い、有効期限がない。つまり、勝手に消えることは永久的にない。ただし、次のような制約がある。</p>
<ul>
<li>
データベースはドメインごと。したがって、他のドメインのデータベースを参照することはできない。(逆にできたら、セキュリティ的に怖い)</li>
<li>データベースの容量は5MBまで。</li>
</ul>
<p>ローカルストレージの詳細は、分かりやすくまとめている「<a href="http://d.hatena.ne.jp/amachang/20080327/1206607704">Safari 3.1 に実装された「Client-side database storage (SQL API)」とは何か？ - IT戦記:</a>」をご覧いただきたい。</p>
<p>では、具体的にローカルストレージを使った、ID・パスワードの記憶機能の実装を紹介する。コード量は多いが、やっていることは大して複雑ではない。</p>
<p>まずは、HTMLは次のように書く。</p>
<pre name="code" class="html">&lt;form name=&quot;login&quot; action=&quot;login.php&quot; method=&quot;post&quot; onsubmit=&quot;return emai_pass_remaind()&quot;&gt;
&lt;input type=&quot;text&quot; name=&quot;email&quot; value=&quot;&quot; placeholder=&quot;メールアドレス&quot; autocorrect=&quot;off&quot; autocapitalize=&quot;off&quot; /&gt;&lt;br /&gt;
&lt;input type=&quot;password&quot; name=&quot;pass&quot; value=&quot;&quot; placeholder=&quot;パスワード&quot; autocorrect=&quot;off&quot; autocapitalize=&quot;off&quot; /&gt;&lt;br /&gt;
&lt;input type=&quot;checkbox&quot; name=&quot;save_pass&quot; value=&quot;1&quot; /&gt;メアドとパスワードを記憶&lt;br /&gt;
&lt;input type=&quot;submit&quot; value=&quot;送信&quot; /&gt;
&lt;/form&gt;</pre>
<p>つぎに、javascriptは次のように書く。</p>
<pre name="code" class="javascript">// ロード時に、データベースからメアドとパスワードを取得、フォームにセットする関数
window.onload = function() {
  var db = openDatabase('mydatabase', '1.0');

  db.transaction(
    function(tx)
    {
      tx.executeSql(&quot;SELECT email, pass FROM login WHERE id = 1&quot;, [],
        function(tx, rs)
        {
          // ロードに成功したら、フォームに値をセット
          document.login.email.value = rs.rows.item(0).email; // htmlspecialchars?
          document.login.pass.value  = rs.rows.item(0).pass;
          document.login.save_pass.checked = true;
        }
      );
    }
  );
}

// フォーム送信時に、メアドとパスワードをデータベースに保存・削除する関数
function emai_pass_remaind()
{
  // フォームから値を取得
  var email = document.login.email.value;
  var pass  = document.login.pass.value;

  /* ここらへんにvalidationの処理を入れたり... */

  var db = openDatabase('mydatabase', '1.0');

  if ( document.login.save_pass.checked == true )
  {
    db.transaction(
      function(tx) {
        // テーブルがあるかな?
        tx.executeSql(&quot;SELECT count(*) FROM login&quot;, [],
          function(tx, rs) {
            // テーブルあるよ
            if ( rs.rows.item(0) == 0 )
            {
              // テーブル初利用の場合は、追加
              tx.executeSql('INSERT INTO login VALUES(1, ?, ?)', [email, pass], // escape?
                function() {},
                function(error) {
                  alert('save failed: ' + error.message);
                }
              );
            }
            else
            {
              // テーブル初利用じゃない場合は、更新
              tx.executeSql('UPDATE login SET email = ?, pass = ? WHERE id = 1', [email, pass], // escape?
                function() {},
                function(error) {
                  alert('update failed: ' + error.message);
                }
              );
            }
          },
          function(tx, error) {
            // テーブルないよ、テーブルつくろ
            tx.executeSql('CREATE TABLE login (id INTEGER PRIMARY KEY, email TEXT, pass TEXT)', [],
              function() {
              // テーブル初利用だから、追加
                tx.executeSql('INSERT INTO login VALUES(1, ?, ?)', [email, pass], // escape?
                  function() {},
                  function(error) {
                    alert('save failed: ' + error.message);
                  }
                );
              },
              function(error) {
                alert('Database creation failed.' + error.message);
              }
            );
          }
        );
      }
    );
  }
  else
  {
    // チェックボックスにチェックがないときは、テーブル削除
    db.transaction(
      function(tx) {
        tx.executeSql('DROP TABLE login', [],
          function() {},
          function(error) {
            alert('delete failed: ' + error.message);
          }
        );
      }
    );
  }
}</pre>
<p>これで、あなたのウェブアプリも、かなり便利になると思う。</p>]]>
</content>
</entry>
<entry>
<title>preg_match_allのお供にarray_combine</title>
<link href="http://suin.asia/2009/09/10/preg_match_all_with_array_combine"/>
<summary>もし、キーと値の関係にあるデータなら、array_combine()を使うと、手軽に連想配列にすることができる。覚えておくといいかもしれない。</summary>
<published>2009-09-10T04:40:15Z</published>
<updated>2009-09-10T04:34:47Z</updated>
<id>http://suin.asia/2009/09/10/preg_match_all_with_array_combine</id>
<category term="PHP" label="PHP" scheme="http://suin.asia/tag/PHP" />
<category term="Tips" label="Tips" scheme="http://suin.asia/tag/Tips" />
<content type="html" xml:lang="ja" xml:base="http://suin.asia/tag/Tips">
<![CDATA[<p>preg_match_all()でマッチしたものは配列で返される。なので、その配列を整理するのにforeach()をつかったりしてひと仕事することも多い。しかし、もし、キーと値の関係にあるデータなら、array_combine()を使うと、手軽に連想配列にすることができる。覚えておくといいかもしれない。</p>

<pre name="code" class="php">
$html = '
<dl>
<dt>Apple</dt><dd>りんご</dd>
<dt>Orange</dt><dd>みかん</dd>
<dt>Strawberry</dt><dd>いちご</dd>
</dl>
';

preg_match_all('/<dt>(.+)<\/dt><dd>(.+)<\/dd>/U', $html, $matches);

var_dump($matches);

/*
array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(32) "<dt>Apple</dt><dd>りんご</dd>"
    [1]=>
    string(33) "<dt>Orange</dt><dd>みかん</dd>"
    [2]=>
    string(37) "<dt>Strawberry</dt><dd>いちご</dd>"
  }
  [1]=>
  array(3) {
    [0]=>
    string(5) "Apple"
    [1]=>
    string(6) "Orange"
    [2]=>
    string(10) "Strawberry"
  }
  [2]=>
  array(3) {
    [0]=>
    string(9) "りんご"
    [1]=>
    string(9) "みかん"
    [2]=>
    string(9) "いちご"
  }
}
*/

$keys   = $matches[1];
$values = $matches[2];

$words = array_combine($keys, $values); // ここがみそ

var_dump($words);
/*
array(3) {
  ["Apple"]=>
  string(9) "りんご"
  ["Orange"]=>
  string(9) "みかん"
  ["Strawberry"]=>
  string(9) "いちご"
}
*/
</pre>]]>
</content>
</entry>
</feed>
