PostgreSQLで複数のテーブルを結合して処理する方法

2007年11月26日 03:15 PostgreSQLで複数のテーブルを結合して処理する方法

今日は久々に旧ブログから記事を引っ張ってきました。

以下は二年以上前に書いたブログ記事の転載です。


新鮮なネタがないので、ストックの中からPostgreSQLネタでも。
というわけで、PostgreSQLで複数のテーブルを結合して処理する方法のメモです。

「複数のテーブルを結合して集計する」というのがどういう意味かと言うと、例えばまず会員制のショッピングサイトなどでユーザーの情報を管理するDBがあると仮定します。
で、一つ目のテーブル「TABLE1」には下記のように、ユーザーID・ユーザーの氏名・ユーザーのメールアドレス等の基本情報が格納されているとします。

TABLE1
UserID UserName MailAddress
Amethyst 鬼瓦 権三郎 amethyst@amethyst-web.org
Alexandrite 俵田山 兼松 alexandrite@amethyst-web.org
Sapphire 平等院 鳳凰堂 sapphire@amethyst-web.org

次に、二つ目のテーブル「TABLE2」には、各ユーザーの購入商品の情報が格納されているとします。
例えば、注文ID・注文者のユーザーID・商品名・商品価格etc。

TABLE2
OrderID UserID ItemName ItemPrice
1 Amethyst 扇風機 2980
2 Amethyst エアコン 99800
3 Sapphire コーヒーメーカー 2800
4 Amethyst 電気コタツ 5800
5 Alexandrite 上戸彩写真集 4800
6 Sapphire マグカップ 1200
7 Alexandrite エロマンガ 980

さて、上記の注文商品の情報が格納されたTABLE2のデータを元に、注文したユーザー宛に一括で受注確認のメールを送信するプログラムを作りたい時、どうすれば良いでしょうか。

単純に処理しようと思えば、まずTABLE2のデータを一行ずつ取得し、その情報の中からユーザーIDを取得し、次にそのユーザーIDをキーにしてTABLE1からメールアドレスを取得、という流れになります。
perlで書くと、下記のような感じ

#-- TABLE2のデータを取得
$SQLstat1 = $DB->prepare("select OrderID, UserID, ItemName, ItemPrice from TABLE2");
#-- 一行ずつ処理する
while(@DATA = $SQLstat1->execute){
    #-- 取得したデータを変数にセット
    ($OrderID,$UserID,$ItemName,$ItemPrice) = @DATA;
    #-- $UserIDをキーにしてTABLE1のデータを取得
    $SQLstat2 = $DB->prepare("select UserName, MailAddress from TABLE1 where UserID = '$UserID'");
    #-- 取得したデータを変数にセット
    ($UserName,$MailAddress) = $SQLstat->execute;
    #-- 以下にメール送信の処理が入る
    &SendMail;
}

※上記の処理の場合は、実際にはプレースホルダを使った方が良いと思いますが、ここでは処理の流れをわかりやすくするために敢えてこういう記述にしました。

さて、上記のスクリプトの場合は一つ目のselect文の中で何度も別のselect文を発行していることになります。
が、select文にinner joinという句を使うと、一度のSQL文で上記の処理を済ますことができます。
↓こんな感じ。

#-- TABLE2のデータを元にTABLE1からUserIDをキーにしてデータを取得
$SQLstat = $DB->prepare("select TABLE2.OrderID, TABLE2.UserID, TABLE2.ItemName,
 TABLE2.ItemPrice, TABLE1.UserName, TABLE1.MailAddrss
 from TABLE2 inner join TABLE1 on TABLE2.UserID = TABLE1.UserID");
#-- 一行ずつ処理する
while(@DATA = $SQLstat->execute){
    #-- 取得したデータを変数にセット
    ($OrderID,$UserID,$ItemName,$ItemPrice,$UserName,$MailAddress) = @DATA;
    #-- 以下にメール送信の処理が入る
    &SendMail;
}

上記スクリプトの
from TABLE2 inner join TABLE1 on TABLE2.UserID = TABLE1.UserID
の部分がポイントです。
これは「TABLE2とTABLE1を結合するよ。条件として"TABLE2のUserIDとTABLE1のUserIDが同じ"データを結合してね」
ということです。
ちなみに、上記select文で出てくる TABLE2.OrderID とか TABLE1.UserID とかはそれぞれ「TABLE2内のOrderID」「TABLE1内のUserID」を表します。

このinner join句は、select文だけではなくupdate文にも使えますので何かと便利です。
delete文には使った記憶がないのでよくわかりません。多分使えるんじゃないですかね?

関連するブログ記事
スポンサード リンク
カテゴリー
PostgreSQL | perl/CGI
タグ
inner join | perl | PostgreSQL | RDBMS | SQL | コマンドライン | シェル

コメント(25)

 

「お気に入りに追加」「ブックマークに追加」ボタンのまとめ

いわゆる、ブラウザの「お気に入り」「ブックマーク」への追加ボタン・リンクのソースのまとめです。

Internet Explorer の場合

フォームの場合は以下のような感じ。

<form method="GET" action="#">
<input type="button" value="お気に入りに追加"
onClick="window.external.AddFavorite('URI','タイトル');" />
</form>

アンカーテキストの場合は、以下のような感じ。

<a href="javascript:window.external.AddFavorite('URI','タイトル');">お気に入りに追加</a>

FireFox の場合

フォームの場合は以下のような感じ。

<form method="GET" action="#">
<input type="button" value="お気に入りに追加"
onClick="window.sidebar.addPanel('サイト名','URI','')" />
</form>

アンカーテキストの場合は、以下のような感じ。

<a href="javascript:window.sidebar.addPanel('サイト名','URI','')">お気に入りに追加</a>

Opera の場合

<a href="URI" rel="sidebar" title="サイト名">お気に入りに追加</a>

au の EZweb の場合

<a href="device:home/bookmark?url=URI&amp;title=サイト名">お気に入りに追加</a>

DoCoMo の iモード や Softbank のケータイに関しては、資料が見つかりませんでした。

ソーシャルブックマークの場合

ソーシャルブックマークに関しては、はてなブックマークをはじめ、日本国内のサービスだけでも20種類くらいあるみたいです。

これら全てに対応したボタンを表示するのはちょっと辛いですが、それらを統合してひとつのボタンで対応できる、「AddClips」というサービスがあるので、こちらを利用すると良いかと思います。

「設置したボタンを通じて、どのソーシャルブックマークサービスに何回登録されたか」というデータも見ることができるので、非常に便利です。


参考: JavaScriptでFirefox使用者の閲覧しているページをブックマークするにはどうすればよいのでしょうか? - 教えて!goo

関連するブログ記事
カテゴリー
JavaScript | モバイル(携帯電話・ケータイ)Web
タグ
AddClips | au | a要素 | Firefox | form要素 | input要素 | Internet Explorer | JavaScript | Opera | xhtml | はてな | はてなブックマーク | ソーシャルブックマーク | ブックマーク | モバイル

コメント(22)

 

perl の CGI や PHP でファイルをアップロードする方法

フォームからファイルをアップロードして、そのファイル自体をサーバーに保存したり、あるいはファイルの内容をデータベースに反映したりするようなスクリプトも、作る機会がかなり多いので、手順をメモしておきます。

フォームの html

ファイルをアップロードさせるフォームの場合、通常の form 要素とは違って、enctype 属性をつける必要があります。

<form method="POST" action="upload.cgi" enctype="multipart/form-data">
  <!-- ここにフォームの内容が入る -->
  <input type="file" name="uploadfile" value="" size="20" />
  <input type="submit" value="アップロード" />
</form>

enctype 属性の他に注意する点としては、必ず POST メソッドを指定することが挙げられます。
GET メソッドではファイルのアップロードはできません。

アップされたファイルの受け取り方 (perl の場合)

僕自身は昔、まだ CGI.pm が perl の標準モジュールじゃなかった頃に作ったコードで、アップされたファイルの内容を受け取る処理をすることが多いですが、今は CGI.pm が標準モジュールとして最初から入っているので、これを使うのが手っ取り早いでしょう。

下記サイトが参考になります。

アップされたファイルの受け取り方 (PHP の場合)

PHP の場合は、非常に簡単です。
定義済変数 $_FILES に、アップロードされたファイルの情報が自動的に入ります。

例えば、

<form method="POST" action="upload.cgi" enctype="multipart/form-data">
  <input type="file" name="uploadfile" value="" size="20" />
</form>

のように、アップロードするファイルの入力欄の名前を uploadfile とした場合、変数 $_FILES は以下のように参照できます。

$_FILES['uploadfile']['name']
元のファイル名
$_FILES['uploadfile']['type']
ファイルの MIME-Type
$_FILES['uploadfile']['size']
ファイルのサイズ (バイト単位)
$_FILES['uploadfile']['tmp_name']
アップロードされたファイルのテンポラリ(一時)ファイルの名前(パス)

後は、サーバー上でファイルを保存するなら、 $_FILES['uploadfile']['tmp_name'] をどこかにコピーすれば良いし、ファイルが CSV 等で、その中身を見て何らかの処理をするなら、$_FILES['uploadfile']['tmp_name'] を開いて中身を読めば良いわけです。

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
CGI | CGI.pm | enctype属性 | form要素 | input要素 | MIME | perl | PHP | xhtml | アップロード

コメント(137)

 

SEO対策として使われる、perl の CGI や PHP に GET で渡す値を「/」(スラッシュ)で区切る方法

よく「CGI や PHP は SEO に不利だ!」なんてことが言われますが、これは技術的なことをよく理解していない人に向けて、難しいことを極端に省略した説明なので、大きな誤解を孕んでいます。

正確には、

http://www.abe-tatsuya.com/aaa.cgi?v1=bbb&v2=ccc

のようなURIの、CGI や PHP に値を GET メソッドで渡す「?v1=bbb&v2=ccc」といった部分が問題なわけです。
こういった値を渡さない、シンプルな URI であれば、拡張子が何であろうが関係はないはずです。

なので、逆に CGI や PHP でなく、拡張子が .html であっても、

http://www.abe-tatsuya.com/aaa.html?v1=bbb&v2=ccc

のような URI なら、同様に検索エンジン側から「これは動的なURIだ」と判断されて、低く評価されるはずです。
(アクセス解析目的とか、ページ側で JavaScript 等で何かの処理をする際に、こういう手法を取ることはあり得ますよね)

で、そういった CGI や PHP 等に、GET メソッドで値を渡した結果によって表示する内容を変えるようなコンテンツの場合、検索エンジンから低く評価されることを避けるために、下記のような URI で処理することが多いです。

http://www.abe-tatsuya.com/aaa/bbb/ccc

最初の例との違いは、以下の通りです。

  1. 「aaa.cgi」の拡張子「.cgi」がない
  2. 「ここからが GET メソッドで渡す値ですよ」という意味の記号「?」がなく、代わりに「/」で区切っている
  3. GET メソッドで渡す値の名前(「v1=」「v2=」)がない
  4. GET メソッドで渡す値の区切りの記号「&」がなく、代わりに「/」で区切っている

これで、一見して動的な URI ではなく、単なるディレクトリ内にあるファイルの URI のように見せることができるわけです。

これを実現するためにやらないといけないことは、

  1. 「aaa」という拡張子のないファイルが、CGI または PHP のスクリプトであることをサーバーに教えてあげる
  2. 「aaa」のスクリプト内で、「/」区切りで渡される値を受け付ける処理を書く

大きく分けて、この二点です。

拡張子のないファイルを CGI や PHP として動作させる方法

「aaa」のような拡張子のないファイルを、CGI または PHP として動作させるには、.htaccess を使います。

特定のファイルに対するアクセス制限や、.htaccess で特定のファイルのみにBasic認証を設定する方法の応用で、

<Files aaa>
ForceType cgi-script
</Files>

と書けば、「aaa」というファイルが CGI として実行されます。

PHP として実行したい場合は、

<Files aaa>
ForceType application/x-httpd-php
</Files>

と書けば、「aaa」というファイルが PHP として実行されます。

perl の CGI や PHP で、「/」(スラッシュ)で区切られた値を受け取る方法

とりあえず「aaa」のようなファイル名のスクリプトが動くようになりました。
次は「/bbb/ccc」のような、一見ただのディレクトリへのリクエストのように見える URI を、スクリプトに渡される値として処理するための方法です。

これには、環境変数 PATH_INFO を参照します。

例えば、perl の CGI である「http://www.abe-tatsuya.com/aaa」に対して、「/bbb/ccc」という値を渡す、つまり、「http://www.abe-tatsuya.com/aaa/bbb/ccc」という URI にアクセスさせる場合、「aaa」というスクリプトの中で、$ENV{'PATH_INFO'}を参照すると、その内容は「/bbb/ccc」となります。

なので例えば、「aaa」という CGI スクリプトの最初のほうに、

#-- PATH_INFO を「/」で分けて配列に格納
@params = split(/\//,$ENV{'PATH_INFO'});
shift(@params);

等とすれば、$params[0],$params[1]... の順番に、「/」区切りで渡された値が入ります。

PHP の場合は、$_SERVER['PATH_INFO']を参照すれば、同様に処理できます。

// PATH_INFO を「/」で分けて配列に格納
$params = split("/",$_SERVER['PATH_INFO']);
array_shift($params);

これで、perl と同様に、$params[0],$params[1]...の順番に、「/」区切りで渡された値が入ります。

後は、渡された値に応じて、出力内容を変えるように色々とスクリプトを書けば OK です。

関連するブログ記事
カテゴリー
.htaccess | PHP | SEO(検索エンジン最適化) | perl/CGI
タグ
.htaccess | CGI | ForceType | GETメソッド | PATH_INFO | perl | PHP | SEO | 環境変数

コメント(304) | トラックバック(1)

 

ケータイの端末識別情報を取得する方法

「IDとパスワードを使ってログインする」というステップを省略するために、PC用のWeb上のサービスやシステムでは Cookie を使うことがよくあります。

ところがPCと違ってケータイは、Cookieに対応していない端末が多数を占めます。
そのため、ケータイ向けのWeb上のサービスやシステムを作る際、ログインを簡略化するために、「サブスクライバID」とか「端末シリアル番号」とか「固体識別情報」とか呼ばれるものを使うことが、よくあります。

これは、それぞれの携帯電話個別に、電話番号とは別に割り振られた固有のIDのようなもので、多分 mixi の「かんたんログイン」とかも、これを取得して認証しているはず。

DoCoMo と Softbank は未確認ですが、少なくとも au の場合は、機種変更をしても、この番号は引き継がれるので、ケータイ所有者個人を識別するためにはかなり有効です。

ただし、どこのキャリアかは知りませんが、「解約して使われなくなった端末識別情報が、別の誰かに割り振られることがある」なんてことを聞いたことがあるので、この端末識別情報に頼りすぎたログイン認証システムは、安全ではないかもしれないことも付記しておきます。

DoCoMo の iモード端末の固体識別情報

html の a要素や form要素に utn属性 をつけることによって、そのリンクや送信ボタンをクリックした際に、サーバーに固体識別情報が送信されます。
なお、送信される前に端末側には「固体識別情報を送信しますか?」みたいな確認ダイアログが表示され、同意した場合のみ送信されます。

<!-- a要素の場合 -->
<p><a href="http://www.abe-tatsuya.com/login.cgi" utn>ログイン</a></p>

<!-- form要素の場合 -->
<form method="POST"
action="http://www.abe-tatsuya.com/login.cgi" utn>
  <input type="submit" value="ログイン" />
</form>

本当は valid な xhtml にするために、utn="utn" としたいところなんですが、ケータイというのは機種ごとに仕様が異なっていたりして、「utn="utn"」という書き方だと正常に動作してくれない機種なんかもありそうで怖いので、DoCoMo の utn属性の説明ページの通りに書いています。
全機種の動作確認ができる機会も、まずないですし……。

このエントリーのコメントでご指摘頂いた通り、i-mode HTML/XHTML 比較表を見ると、「utn="utn"」という書き方で大丈夫なようです。
コメント頂いたyurikoさん、ありがとうございました。

で、サーバー側に送られてくる固体識別情報はどこに含まれているかというと、User-Agent ヘッダに含まれています。

非FOMA端末の場合、固体識別情報を含んだ User-Agent は以下のようになります。

DoCoMo/1.0/X503i/c10/ser***********

「ser***********」の「***********」の部分には、11桁の英数字が入り、これが固体識別情報に当たります。

perl でこれを取得しようとすると、以下のような感じでしょうか(普段自分が使ってるソースは、他のサブルーチンから渡される変数を色々使ってて、ブログに掲載しても可読性が低いと思われるので新たに書きました。以下のソースは動作確認を全くしてません)。

if($ENV{'HTTP_USER_AGENT'} =~ /^DoCoMo\/1\.0\/.*\/(ser\w{11})$/){
	#-- 固体識別情報を変数に代入
	$mobile_id = $1;
}

FOMA端末の場合は「携帯電話の製造番号」と「FOMAカードの製造番号」の二種類の固体識別情報が取得できます。
「携帯電話の製造番号」の方は、機種変更をしたら変わってしまうと思うんですが、「FOMAカードの製造番号」の方は、多分機種変更をしても、FOMAカードが同一であれば変わらないはず。

FOMA端末の、固体識別情報を含んだ User-Agent は以下の通り。

DoCoMo/2.0 YYYY(c10;serXXXXXXXXXXXXXXX; iccxxxxxxxxxxxxxxxxxxxx)

「serXXXXXXXXXXXXXXX」の部分が携帯電話の製造番号で、「XXXXXXXXXXXXXXX」には15桁の英数字が入ります。
「iccxxxxxxxxxxxxxxxxxxxx」の部分がFOMAカードの製造番号で、「xxxxxxxxxxxxxxxxxxxx」には20桁の英数字が入ります。

用途にもよりますが、基本的には FOMAカードの製造番号を取得した方が便利ですかね。
FOMAカードの製造番号を取得する perl のスクリプトは以下(上の同じく、以下のソースは動作確認を全くしてません)。

if($ENV{'HTTP_USER_AGENT'} =~ /^DoCoMo\/2\.0 .*; (icc\w{20})\)$/){
	#-- 固体識別情報を変数に代入
	$mobile_id = $1;
}

au の EZweb 端末のサブスクライバID

au の場合は、自動的にサブスクライバIDと呼ばれる X_UP_SUBNO ヘッダを、サーバーに送信しています。

ただし、ユーザー側がこのヘッダを「通知しない」という設定にしている場合は、送信しません。
通知設定に関しては、au 公式サイトのお知らせにあります。

サーバーに送信される X_UP_SUBNO ヘッダは、以下のようなフォーマットになっています。

xxxxxxxxxxxxxx_**.ezweb.ne.jp

最初の「xxxxxxxxxxxxxx」の部分が14桁の数字で、端末固有の番号にあたるようです。
※参考: モバイルCGI研究(EZweb編)環境変数リファレンス [CGIぽん]

サブスクライバIDを取得する perl スクリプトは以下の通り(同様に以下のソースは動作確認を全くしてません)。

if($ENV{'HTTP_X_UP_SUBNO'} =~ /^(\d{14})_\w{2}\.ezweb\.ne\.jp$/){
	#-- サブスクライバIDを変数に代入
	$mobile_id = $1;
}

Softbank 端末の端末シリアル番号

Softbank の端末の場合、ユーザーが「ユーザーID通知」または「製造番号通知」の設定を on にしていれば、端末シリアル番号というものが User-Agent に含まれます。

端末の世代によって、フォーマットが異なってややこしいですが、ソフトバンクの公式サイトのユーザーエージェントについての説明によると、以下のようなパターンがあるらしいです。

#-- SoftBank 6-5 Series
J-PHONE/4.0/J-SH51/SN************ SH/0001a Profile/MIDP-1.0 Configuration/CLDC-1.0
Ext-Profile/JSCL-1.1.0

#-- SoftBank 3G Series (Vodafone時代の端末)
Vodafone/1.0/V904SH/SHJ001/SN************ Browser/VF-NetFront/3.3 Profile/MIDP-2.0 
Configuration/CLDC-1.1
#-- SoftBank 3G Series (Softbank時代の端末)
SoftBank/1.0/910T/TJ001/SN************ Browser/NetFront/3.3 Profile/MIDP-2.0 
Configuration/CLDC-1.1

「SN************」の部分が端末シリアル番号で「************」には11~15桁の英数字が入るようです。

端末シリアル番号を取得する perl スクリプトは、ちょっといいかげんですが以下のような感じ(同様に以下のソースは動作確認を全くしてません)。

if($ENV{'HTTP_USER_AGENT'} =~ /^(J\-PHONE|Vodafone|Softbank)\/.*\/(SN\w{11,15}) .*/){
	#-- 端末シリアル番号を変数に代入
	$mobile_id = $2;
}

端末識別情報に頼りすぎないこと

ログイン認証を端末識別情報に依存しすぎたせいで、「機種変更したらログインできない」なんていう事態に陥ったサービスを知っています。

また、たまたま携帯事業者側の都合で、全く同じ番号の端末識別情報が複数の端末に割り振られた、なんてケースも聞いたことがあります。

ケータイは文字入力が不便なインターフェイスなので、ログインの簡略化のために端末識別情報を使うのは、ユーザーの利便性向上のためにも、良いことだとは思うのですが、認証をこれだけに頼るのは、ちょっと危険かもしれません。

関連するブログ記事
カテゴリー
perl/CGI | モバイル(携帯電話・ケータイ)Web
タグ
au | a要素 | Cookie | DoCoMo | form要素 | HTTPヘッダ | perl | User-Agent | utn属性 | xhtml | X_UP_SUBNO | アクセス制限 | サブスクライバID | ソフトバンク | モバイル | 固体識別情報 | 正規表現 | 環境変数 | 端末シリアル番号

コメント(10)

 

PHP でファイルの MIME-Type を判別する方法

相変わらず、perlやPHPでファイルのダウンロード確認ダイアログを表示させる方法と、その関連記事であるperl の CGI や PHP でよく出力する Content-type ヘッダ一覧 (MIME-type)へのアクセスが、うちのブログでは毎日アクセス上位2位を占めているので、さらに補完エントリーを書いてみます。

ファイルをダウンロードさせるスクリプトを書く際に、最初からそのファイルの MIME-Type が解っている場合は良いのですが、色んな種類のファイルをひとつのスクリプトでダウンロードさせる場合には、各ファイル個別に MIME-Type を判別して、Content-type ヘッダとして出力する必要があります。

perl の場合は多分、自分で MIME-Type 判別用の関数を作るとか、何らかのモジュールを使うとか、perl スクリプトから file コマンドとかそれに類する UNIX コマンドを呼び出すとかしないと無理なんじゃないかと思うんですが、PHP の場合は非常に簡単で、mime_content_type() という関数一つで事足りるようです。

// MIME-Typeを判別したいファイル
$source = '/home/tatsuya/data/img/00003.jpg';

// MIME-Type を判別
$mime_type = mime_content_type($source);

これで、「$mime_type」に、指定したファイルの MIME-Type が代入されます。

なので、perlやPHPでファイルのダウンロード確認ダイアログを表示させる方法で書いたようなダウンロードスクリプトを書く場合には、

// ダウンロードさせる元ファイル
$source = '/home/tatsuya/data/img/00004.jpg';
// MIME-Type を判別
$mime_type = mime_content_type($source);
// 保存時のファイル名
$filename = 'kagaminerin.jpg';

// HTTP ヘッダ送信
header("Content-type: {$mime_type}");
header("Content-Disposition: attachment; filename=\"{$filename}\"");
// ファイルを読み込んで出力
readfile($source);

こんな感じになります。

後は、GET や POST で受け取った値を元に $source$filename を変える処理を事前に作っておけばOKでしょう。

mime_content_type() 関数についての注意事項

PHP マニュアルの mime_content_type の項目を見ると、以下のように書いてあります。

この関数は非推奨です。PECL 拡張モジュール Fileinfo が、同等の機能 (それ以上のもの) をもっときれいな方法で提供しています。

ですので、PECL 拡張モジュールをインストールできる権限がある場合や、既にサーバーに Fileinfo 拡張モジュールが入っている場合は、この finfo_file 関数を使って MIME-Type を判別した方が良いかと思います。

関連するブログ記事
カテゴリー
PHP
タグ
Content-Disposition | Content-type | Fileinfo | finfo_file | HTTPヘッダ | MIME | mime_content_type | PECL拡張モジュール | PHP | RFC | ダウンロード

コメント(6)

 

メール受信時に perl スクリプトを起動して自動処理させる方法

メールが届くと同時に何らかのアクションを起こすプログラムというのは、かなり作る機会の多い部類に入るかと思います。

ここ数年で特に多いものだと、ケータイ向けサイトの案件で、空メールを受信したら自動でユーザー登録用のフォームのアドレスを書いたメールを、空メール送信者に送る、みたいなものとか、ブログやSNSの日記なんかを、ケータイメールで投稿できるようにする処理とかですね。
そして王道の自動返信メールとか。

後、途中で飽きちゃったんですが、昔、送られてくるメールの内容を自分で学習して言葉を覚えて、文章を生成して返信する bot (人工無脳)を趣味で作ってたことがあります。

で、実際こういう「メールを受け取ったら何らかの処理を自動で行なう」という機能を実現するには、どうすれば良いかというと、

  1. 特定のメールアカウントにメールが届いた際に、何らかのプログラムが起動するように設定する
  2. そのプログラムを書く

という二つのステップが必要になります。

まずは、この1ステップ目の「特定のメールアカウントにメールが届いた際に、何らかのプログラムが起動するように設定する」方法について、簡単にまとめてみます。

aliases を使う場合

aliases の設定と使い方についてのメモにも書きましたが、下記のようにすることで、特定のアカウントに届いたメールを、パイプを使って直接何らかのプログラムに渡して実行することができます。

entry: "|/home/tatsuya/entry.pl"

上記の例では、「entry」というメールアカウントにメールが届いた際に、自動的に「/home/tatsuya/entry.pl」という perl スクリプトが起動するように設定しています。

~/.forward を使う場合

サーバーの各ユーザーアカウント毎に、個別に設定が可能な ~/.forward を使う場合は(レンタルサーバーを使う場合はこちらの方が利用する機会が多いかもですね)、~/.forward に以下のように書けばOKです。

"|exec /home/tatsuya/entry.pl"

procmail を使う場合

届いたメールに対して、自動でマッチング処理等を行なって、結果によって行なう処理を振り分けてくれる便利な存在である procmail を使う場合は、~/.procmailrc に以下のように書きます。

:0 :
* ^To: entry
| /home/tatsuya/entry.pl

^To: entry」の部分は正規表現が使えるので、メールのヘッダ(FromやSubject等)に対して細かい条件を設定して振り分けることで、一つのメールアカウントで様々な処理を行なうことができるのも良いですね。

メールを処理する perl スクリプトの書き方

さて、続いて第2ステップ「そのプログラムを書く」の部分です。

aliases、~/.forward、procmail の三種類の設定方法を紹介しましたが、どの方法を用いても、「指定したプログラムの標準入力に、受け取ったメールの内容を渡す」というのは同じです。

つまり、受け取る側の perl スクリプトでは、標準入力の内容を読めば良いだけです。

while(<STDIN>){
	#-- 「$_」にメールの内容(ヘッダも本文も添付ファイルも全て)が
	#-- 一行ずつ代入されていくので、正規表現とかを使って色々処理する
}

これだけです。

後は、「メール送信者のアドレスをデータベースに登録しておいて、ユーザー登録用のURIを生成してメールを返信する処理を書く」とか、「メール送信者のアドレスからユーザーIDを引っ張ってきて、メール本文の内容をそのユーザーIDの日記に投稿させる」とか、「本文を形態素解析して、内容を bot (人工無脳)に覚えさせる」とか、色々とやれば良いわけです。

関連するブログ記事
カテゴリー
Linux/UNIX | perl/CGI
タグ
.forward | aliases | perl | procmail | sendmail | SMTP | UNIX | ケータイメール | コマンドライン | メール | モバイル | レンタルサーバー | 人工無脳

コメント(14) | トラックバック(3)

 

ケータイサイトのフォーム入力の文字種別を指定する方法

ケータイはPCと比較して、文字入力関連のインターフェイスが非情に不便です。

それはもちろん、携帯電話という端末の特性上、仕方が無い部分でもあるかもしれませんが、ちょっとした工夫でユーザーに与える文字入力へのストレスを軽減することが出来ます。

例えば、何かの入力フォームで、半角数字のみを入力してもらうテキスト入力欄があったとします。

そこで何の工夫も無く、

<input type="text" name="userid" value="" size="7" maxlength="6" />

みたいな感じでやっちゃうと、ユーザーがその入力欄に文字を入力しようとすると、最初に全角かなモードでテキスト入力のウィンドウが開いちゃいます。
これを、最初から半角数字モードで開くようにするだけで、ユーザーが感じるストレスは結構軽くなるんじゃないでしょうか。

各携帯電話のキャリアでは、このようなテキスト入力欄に対して、文字入力の種別を指定するための、input要素向けの独自属性を用意しています。
が、DoCoMo、au、Softbankそれぞれ別の属性になってますので、複数キャリア対応のサイトの場合は、全ての属性を列記しないといけません。

DoCoMoのiモードの場合 (istyle属性)

<input type="text" name="userid" value="" size="7" maxlength="6" istyle="4" />

という風に、istyle属性を追加することで、入力してもらう文字種別を指定できます。

istyle属性の値の対応は以下の通り。

istyle="1"
全角かなモード
istyle="2"
半角カナモード
istyle="3"
半角英字モード
istyle="4"
半角数字モード

auのEZwebの場合 (format属性)

<input type="text" name="userid" value="" size="7" maxlength="6" format="*N" />

という風に、format属性を追加することで、入力してもらう文字種別を指定できます。

format属性の値の対応は以下の通り。

format="*A"
半角英字(大文字)モード
format="*a"
半角英字(小文字)モード
format="*N"
半角数字モード
format="*X"
半角英数(大文字)モード
format="*x"
半角英数(小文字)モード
format="*M"
全角かなモード
format="*m"
全角英字モード

ちなみに、「*A」「*a」「*N」等の頭の「*(アスタリスク)」は、「文字数の制限なし」という意味です。

「常に五桁の数字だけを入力してもらいたい」という場合は format="5N"という風に、「*(アスタリスク)」の代わりに、指定した入力文字数を指定すれば、入力する文字数も制限できます。

ただし、「五桁以内の数字を入力してもらいたい」という場合には、この指定方法は使えない端末が多いです。
四桁とか三桁の数字を入力してOKを押しても、端末側でエラーを返してしまいます。
あくまでも「文字数が固定の場合」のみに利用できる方法です。

Softbankの場合 (mode属性)

<input type="text" name="userid" value="" size="7" maxlength="6" mode="numeric" />

という風に、mode属性を追加することで、入力してもらう文字種別を指定できます。

mode属性の値の対応は以下の通り。

mode="hiragana"
全角かなモード
mode="katakana"
全角カナモード
mode="alphabet"
半角英字モード
mode="numeric"
半角数字モード

DoCoMo、au、Softbankの主要3キャリアに対応させるには

上記を踏まえて、DoCoMo、au、Softbankの主要3キャリアに対応したテキスト入力欄を作ろうと思うと、以下のようになります。

まず、全角かなも半角英数も混在するような、何でもOKな入力欄の場合。

<input type="text" name="f1" value="" size="10" maxlength="128"
 istyle="1" format="*M" mode="hiragana" />

続いて、メールアドレス等の半角英数(+記号)だけを入力してもらいたい場合。

<input type="text" name="f2" value="" size="10" maxlength="128"
 istyle="3" format="*x" mode="alphabet" />

そして、電話番号や連番のID等、半角数字のみを入力してもらいたい場合。

<input type="text" name="f3" value="" size="10" maxlength="128"
 istyle="4" format="*N" mode="numeric" />

以上のようになります。
とりあえず、この3つだけ覚えておけば、ほとんど事足りるかな?

ケータイサイトのフォーム入力の文字種別を指定する方法の続きを読む

関連するブログ記事
カテゴリー
モバイル(携帯電話・ケータイ)Web
タグ
au | DoCoMo | format属性 | form要素 | input要素 | istyle属性 | mode属性 | xhtml | ソフトバンク | モバイル

コメント(48) | トラックバック(6)

 

「アンチ・セカンドライフ」と「アンチ・セカンドライフ・ブーム」は分けて考えなきゃいけない

今月の頭に、企業向けにセカンドライフ関連のコンサルティングなんかをしていらっしゃる会社の社長さんのお話を聞く機会がありました。

ええ、あの「セカンドライフ」です。
ただいま巷で大流行中の(ということになっている)アレです。(あ、ブームは一段落ってことになったのかな?)

話を聞いていて、色々と考えさせられるところがあったので「考えをまとめてブログに書いとかなきゃな~」と思ってたんですが、なかなか考えが綺麗にまとまらず、気づけば半月経っちゃってました。

おかげで、他にもブログに書くネタは沢山あるのに、そっちが気になってブログの更新も止まってしまったという有様。あーあ。

正直まだ全然まとまってないんですが、とりあえずアウトプットしとかないと、このままこのブログの更新が永遠に止まってしまいそうなので、とりとめもなく書いてしまいます。

とりあえず、結論は、

「アンチ・セカンドライフ」と「アンチ・セカンドライフ・ブーム」を同一にとらえちゃってたオレ

ということ。

どういうことかと言うと、まず前提として、僕自身は今まで「なんか色んなメディアとかでセカンドライフがブームになってるような取り上げられ方してるけど、実際のとこどうよ? 海外ではどうだか知らないけど、正直日本で流行ってないっしょ?」的な印象を持っていた(いや今も持っている、かな)わけですね。

で、そういう自分を「アンチ・セカンドライフ」派としてカテゴライズしていました。

そもそも「セカンドライフ・ブーム」って何?

実際、僕の周辺では「セカンドライフ始めたんだけど、楽しくってさー!」ってな声を聞いたことがありません。

これは現実のオフラインだけでなく、オンライン上の、僕がよく見てるブログであったりニュースサイトであったりとか。
どちらかというと「セカンドライフ・ブーム」に懐疑的な意見ばかりが目につきます。

ところが一方で、電通・トヨタ・日産・ヤマハ等など、誰もが知っている大企業がどんどんセカンドライフに参入しているし、書店のPC・ネット関連のコーナーにはセカンドライフ本が並んでいるというこの現実。

正直、気味が悪いというか、凄まじい違和感を感じます。

なんでこんな状態なのかというと、一昔前に「ブログだSNSだ、CGMだ」なんてことをWeb業界の(前述の大企業と比べて)ちっぽけな企業や個人が騒いでるときに、「そんなもんが流行るわけがないだろ」と一蹴していたり、企業の規模が大きいが故に小回りが効かなくて、結果的にブログやSNSのブームに乗り遅れてしまった、そんな大企業が「次こそは我々がブームの担い手になってやる!」という意気込みで、セカンドライフに目をつけて、ブームを起こそうと力を入れてる、なんてことがよく語られます。

まあ実際、この「作られたブーム感」は真性のものだと思うので(真性の作られたブームって変な言葉だ……)、その通りなんじゃないでしょうか。

そうじゃなくても、消費者にそういう風にとらえられちゃう時点で、駄目ですよね。

で、そういう風にとらえた人たちはみんな「アンチ・セカンドライフ」派になるわけです。
「作られたブームに踊らされてたまるか!」ってなわけです。

でもセカンドライフの世界は魅力的だ

「作られたブーム感」のせいで、セカンドライフに対してネガティブなイメージしか持たない人は、沢山います。
軽くググってみると、懐疑的な意見が沢山引っかかります。

僕自身もそうでした。

けど、冒頭で書いた社長さん(もともと3DCG関連の仕事をしていらっしゃったらしい)の話を聞いていると、「ああ、この手の3DCG関連の業界の人にとっては、作られたブームだとかそんなことは関係なく、セカンドライフは本当に夢が実現しつつある世界なんだなぁ」ということを凄く感じられたわけです。

僕自身も、昔は結構なヘビーゲーマーで、元々「自分でゲームが作りたい」という一念だけで独学でプログラミングを覚えた人間なので、「仮想的な箱庭世界の中に、もう一つの宇宙を構築する」みたいな概念には、ゾクゾクするほど興奮するタイプですので、社長さんのセカンドライフ、あるいはその手のヴァーチャル世界なものに対する熱い思いにはとても共感できました。

なんというか、「セカンドライフ」というコンテンツ(というかインフラなのか?)自体は、非常に魅力的な存在だと気づかされたんですよね。それが一般的な日本人に受け入れられるかどうかは別にして。

魅力的なものなのに、「なんだか巨大な力が働いて無理やりブームになってることにされてる」という恐怖心というか嫌悪感というか、そういうものがあって、それは「セカンドライフ・ブーム」に対する感情なんだけど、「セカンド・ライフ」そのものに対するネガティブな感情だと錯覚してしまっていたわけです。

多分、僕と同じような錯覚に陥ってる人は結構いるんじゃないかな?

条件反射的に拒絶するんじゃなく、一度「アンチ・セカンドライフ」と「アンチ・セカンドライフ・ブーム」を分けて考えてみると、今まで見えて来なかった物が見えてくる気がします。

本来は、その「見えて来る物」が何なのかを考えて、このエントリーで書きたかったんですが、それがなかなかまとまらなかったので、とりあえずこんな感じで僕のつまらない思考をアウトプットしてみました。まる。


それにしても、現状のセカンドライフユーザー層ってどういう人達なんでしょうね。
MMOプレイヤーとか多いんだろうか。
でも、MMOとしてとらえた場合はセカンドライフは多分糞ゲーだよなぁ、何となく。

関連するブログ記事
カテゴリー
セカンドライフ
タグ
セカンドライフ | ブーム

コメント(6)

 

このブログについて

阿部辰也

Webコンサルタントやシステムエンジニア、執筆業などをやっている、グッドホープ代表・阿部辰也のブログです。
Web技術系のTipsから仕事の話、趣味の話まで色々と。
人生は所詮生まれてから死ぬまでの壮大な暇つぶし。
だったら有意義に暇をつぶして生きましょー。

阿部辰也へのお仕事のご依頼・問合せはこちらからどうぞ。

Twitter: @t_abe
読書メーター: ID:Tatsuya

このブログのサイトマップ
このブログのはてなブックマーク数

Feed/RSS購読

タグクラウド

最近のトラックバック

阿部辰也の著書

77のキーワードで知る インターネットで稼ぐ 図解 ブログ・メルマガ・Webサイト構築の基本

77のキーワードで知る インターネットで稼ぐ 図解 ブログ・メルマガ・Webサイト構築の基本

頑張って書いたのに、出版後すぐに出版社が倒産して印税も貰えずじまいで俺涙目(笑)。

Powered by Movable Type 5.02

スポンサード リンク

はてなブックマーク



あわせて読みたい

t-abeの今読んでる本

t-abeの最近読んだ本

t-abeの今やってるゲーム

t-abeの最近やったゲーム