PHPExcel を使って PHP で Excelファイル(xls/xlsxファイル)を読み込む方法

2012年4月17日 10:34 PHPExcel を使って PHP で Excelファイル(xls/xlsxファイル)を読み込む方法

かーなり前にperl や PHP で Excelファイル(xlsファイル)を簡単に出力する方法ということで、ちょっと裏技的なExcelファイルの出力方法をご紹介しました。

今回は、逆にPHPでExcelファイルを読む方法の紹介です。

PHPExcel をダウンロードする

ExcelファイルをPHPで読み込むには、PHPExcelというライブラリを利用するのが楽です。

というわけで、以下のサイトから PHPExcel をダウンロードしましょう。

PHPExcel

解凍すると色々ファイルが出てきますが、「Classes」ディレクトリ内のファイルがライブラリ本体です。
Classesディレクトリを、どこかに置きましょう。

PHPExcel をインクルードする

設置したClassesディレクトリ内のライブラリをインクルードします。

include_once './Classes/PHPExcel.php';
include_once './Classes/PHPExcel/IOFactory.php';

Excelファイルを開く

以下のようにしてExcelファイルを開きます。

#-- Excelファイル名
$xlsFile = 'yutyrannus.xls';

#-- Excel2007のファイルの場合
$xlsReader = PHPExcel_IOFactory::createReader('Excel2007');
#-- Excel95のファイルの場合
$xlsReader = PHPExcel_IOFactory::createReader('Excel5');

#-- Excelファイルを読み込む
$xlsObject = $xlsReader->load($xlsFile);

Excelファイルを読んでいく

Excelファイルをシートごと、行ごと、セルごとに読んでいくには、以下のようにします。

#-- シートごとに読んでいく
for ($i = 0; $i < $xlsObject->getSheetCount(); $i++) {
	$xlsObject->setActiveSheetIndex($i);
	$xlsSheet = $xlsObject->getActiveSheet();
	#-- シート名
	$sheetTitle = $xlsSheet->getTitle();
	$j = 0;
	#-- シートの行ごとに読んでいく
	foreach ($xlsSheet->getRowIterator() as $row) {
		$xlsCell = $row->getCellIterator();
		$xlsCell->setIterateOnlyExistingCells(true);
		$k = 0;
		#-- 行のセルごとに読んでいく
		foreach ($xlsCell as $cell) {
			#-- 「シート名・行番号・セル番号」の連想配列にセル内のデータを格納
			$data[$sheetTitle][$j][$k] = $cell->getCalculatedValue();
			$k++;
		}
		$j++;
	}
}

上記のコードで、$data という連想配列に、シート、行、セルごとのデータが格納されます。

関連するブログ記事
カテゴリー
PHP
タグ
Excel | PHP | PHPExcel

コメント(13)

 

『WebデザイナーのためのPHP入門講座リターンズ』の講師をします【2/29(水) 神戸・カフーツ】

非プログラマなWeb屋のみなさん!

プログラマじゃなくてもちょこっとPHP知ってると色々と便利だし、プログラマな人に仕事を頼む時も話がしやすくなりますよ!!

というわけで、先月も開催しましたが、今月もいつも大変お世話になっている神戸のコワーキング・スペース カフーツさんの主催で『WebデザイナーのためのPHP入門講座』の講師をさせて頂くことになりました。

本格的にプログラミングを学ぶというよりも、普段HTMLのコーディングやWebデザインを生業にしている方にとって、ちょっと知っておくと得するようなPHPの使い方をお伝えする内容になっております。

ぜひぜひお気軽にご参加くださいねー!

『WebデザイナーのためのPHP入門講座リターンズ』の詳細・お申込みはこちら

関連するブログ記事
カテゴリー
PHP | セミナー/講習会
タグ
PHP | セミナー

コメント(2)

 

『WebデザイナーのためのPHP入門講座』の講師をします【1/28(土) 神戸・カフーツ】

非プログラマなWeb屋のみなさん!

プログラマじゃなくてもちょこっとPHP知ってると色々と便利だし、プログラマな人に仕事を頼む時も話がしやすくなりますよ!!

というわけで、いつも大変お世話になっている神戸のコワーキング・スペース カフーツさんの主催で『WebデザイナーのためのPHP入門講座』の講師をさせて頂くことになりました。

本格的にプログラミングを学ぶというよりも、普段HTMLのコーディングやWebデザインを生業にしている方にとって、ちょっと知っておくと得するようなPHPの使い方をお伝えする内容になっております。

ぜひぜひお気軽にご参加くださいねー!

『WebデザイナーのためのPHP入門講座』の詳細・お申込みはこちら

関連するブログ記事
カテゴリー
PHP | セミナー/講習会
タグ
PHP | セミナー

コメント(18)

 

Web上で SQLite を GUI 操作できる SQLiteManager のインストール方法

MySQL用の phpMyAdmin とか、PostgreSQL用の phpPgAdminのように、PHPで動く Webベースで SQLite クライアント SQLiteManager の紹介です。

1. ダウンロード

SQLiteManager のダウンロードはこちらから行なえます。

2. 日本語(UTF-8)対応パッチ

日本語(UTF-8)のデータベースを扱う場合は、UTF-8でSQLiteManagerを使う - よくきたblogを参考に、日本語化パッチをあてます。

euc-jp の場合は必要ない、かも?

3. ひたすらアップロード

上記日本語(UTF-8)対応パッチを含む、全ファイルを頑張ってアップロードします。

アップロードしたディレクトリの index.php にアクセスすれば、SQLiteManager が使えるようになっています。

4. Basic認証の設定

自分以外の人間にphpPgAdminでDBをいじられるととっても困るので、SQLiteManager をインストールしたディレクトリにBasic認証をかけておきます。

Basic認証のかけ方は.htaccess によるBasic認証のかけ方等を参照。

5. データベースを指定

既にサーバー上に存在する SQLiteデータベースを操作したい場合は、ここで操作するデータベースを指定します。

「名前」は適当につけて、「パス」の部分に操作したいSQLiteデータベースのパスを入力。
「保存」をクリックすると、指定した SQLiteデータベースが、左のメニューに追加されるはずです。

左のメニューの該当データベース名をクリックすれば、そのデータベースを GUI で操作できます。

関連するブログ記事
カテゴリー
PHP | SQLite
タグ
.htaccess | Basic認証 | CMS | PHP | RDBMS | SQLite | SQLiteManager

コメント(9)

 

perl / PHP / JavaScript 各言語での URL(URI)エンコード・デコード方法まとめ

日本語等の2バイト文字を URL として使用するための、URLエンコード・デコード方法を、perl / PHP /JavaScript の各言語別にまとめてみました。

と言っても、PHP と JavaScript はそれ専用の関数が用意されてるから簡単なんですけどね。

perl で URLエンコード・デコード

perl で URLエンコードするには、以下のようにします。

$word =  "はぴはぴはっぴー♪";
$word =~ s/([^0-9A-Za-z_ ])/'%'.unpack('H2',$1)/ge;
$word =~ s/\s/+/g;

これで「はぴはぴはっぴー♪」という文字列が「%82%cd%82%d2%82%cd%82%d2%82%cd%82%c1%82%d2%81%5b%81%f4」という文字列にエンコードされます。

続いて、perl での URLデコード方法。

$word =  "%82%cd%82%d2%82%cd%82%d2%82%cd%82%c1%82%d2%81%5b%81%f4";
$word =~ s/+/\s/g;
$word =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ge;

これで「%82%cd%82%d2%82%cd%82%d2%82%cd%82%c1%82%d2%81%5b%81%f4」という文字列が「はぴはぴはっぴー♪」という文字列にデコードされます。

PHP で URLエンコード・デコード

前述の通り、PHP にはURLエンコード・デコード用の関数が用意されているので、非常に簡単です。

#-- URLエンコード
$word = "はぴはぴはっぴー♪";
$encoded = urlencode($word);

#-- URLデコード
$encoded = "%82%cd%82%d2%82%cd%82%d2%82%cd%82%c1%82%d2%81%5b%81%f4";
$word = urldecode($encoded);

JavaScript で URLエンコード・デコード

PHP と同じく、JavaScript にも URLエンコード・デコード用の関数が用意されているので、同じく簡単です。

// URLエンコード
var word = "はぴはぴはっぴー♪";
var encoded = encodeURI(word);

// URLデコード
var encoded = "%82%cd%82%d2%82%cd%82%d2%82%cd%82%c1%82%d2%81%5b%81%f4";
var word = decodeURI(encoded);
関連するブログ記事
カテゴリー
JavaScript | PHP | perl/CGI
タグ
decodeURI | encodeURI | JavaScript | perl | PHP | urldecode | urlencode | 正規表現

コメント(1)

 

perl や PHP で Cookie(クッキー)を読み書きする方法

Cookie の出力

Cookie は HTTPヘッダに出力することで、アクセスしたユーザーのブラウザ毎に書き込むことができます。

Cookie を書き込む際の書式は、

name=value; expires=Sun, 15-Nov-2009 23:59:59 GMT; domain=www.abe-tatsuya.com; path=/cgi-bin/; secure

という感じです。

name
必須。任意の「name」に対する値「value」を指定します。
例) loginid=abetatsuya
expires
Cookie の有効期限を指定します。省略するとブラウザを閉じるまでの間が有効期限になります。
また、過去の時刻を指定すると、該当 Cookie を削除します。
domain
Cookie を有効にするドメイン名を指定します。省略可。
path
Cookie を有効にするパスを指定します。省略すると、Cookie を書き込んだファイルのあるパスとなります。
secure
指定すると、SSL での通信時のみ Cookie をやり取りします。

この情報を、Set-Cookieヘッダとして出力すれば良いので、 perl の CGI の場合には、

print qq|Set-Cookie: loginid=abetatsuya; |;
print qq|expires=Sun, 15-Nov-2009 23:59:59 GMT; |;
print qq|domain=www.abe-tatsuya.com; path=/cgi-bin/; secure\n|;
print qq|Content-type: text/html; chearset=UTF-8\n|;
print qq|\n|;
#-- 以下、ページを出力

という感じにすれば良いわけです。

PHP の場合は、その名の通り setcookie っていう関数が用意されてるので、非常に楽チンですね。

setcookie("loginid","abetatsuya",time,"/cgi-bin",
 "www.abe-tatsuya.com",true);

こんな感じで書けばOKです。
詳細はPHP: setcookie - Manual等を参照。

複数の Cookie を書き込みたい場合は、複数回 Set-Cookie ヘッダを出力すれば大丈夫です。

Cookie の読み込み

書き込んだ Cookie を読み込みたい場合は、環境変数 HTTP_COOKIE を参照します。

perl であれば $ENV{'HTTP_COOKIE'} 内に「name=value」という形式で入っています。
複数の値が指定されている場合は「; 」区切りで「name1=value1; name2=value2」のように入ります。

「; 」で split した後にさらに「=」で split して、$COOKIE{'name'} = value のような連想配列に入れると使い易いかと思います。

PHP の場合は、$_COOKIE['name'] という変数内に、そのまま指定した値が入ってきます。

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
CGI | Cookie | HTTPヘッダ | perl | PHP | Set-Cookie | setcookie | 環境変数

コメント(21)

 

さくらのレンタルサーバーで PHP を .html 等の拡張子で実行させる方法

先日.htaccess で .html 等の拡張子で PHP を実行させる方法という記事を書きましたが、さくらのレンタルサーバーでは、PHP が CGI として動いているため、上記記事の設定では、.html 等の拡張子で PHP を実行することができません。

なので、今回はさくらのレンタルサーバーに絞った、設定方法の解説です。

php-cgi をドキュメントルートにコピーする

SSH でサーバーにログインし、php-cgi というバイナリファイルを、自分のドキュメントルートにコピーします。

cp /usr/local/php/default/bin/php-cgi ~/www/php.cgi

コピーする際に、ファイル名を php.cgi のように拡張子を .cgi にしておくのがポイント。

ついでに、コピーした php.cgi のパーミッションも変えておきましょう。

chmod 0705 php.cgi

.htaccess の編集

さて、続いて .htaccess を編集します。

以下の二行を追加。

Action myphp-script	/php.cgi
AddHandler myphp-script	.php .html

これで .html でも PHP が動くようになります。

ただし、この方法だと、PHP の CGI版バイナリファイルを直接ドキュメントルートに持ってきて、それを実行するようになってますので、レンタルサーバー側の PHP がバージョンアップされても、コピーした PHP は古いままです。
なので、バージョンアップ情報等は自分でチェックして、そのたびにコピーし直す必要があるでしょう。

あるいは、コピーせずにシンボリックリンクを作ってもいけるのかな?
これは試していないので、ちょっと不明です。

関連するブログ記事
カテゴリー
.htaccess | PHP | レンタルサーバー
タグ
.htaccess | CGI | PHP | UNIX | さくらのレンタルサーバー | コマンドライン | シェル | 拡張子

コメント(20)

 

.htaccess で .html 等の拡張子で PHP を実行させる方法

.htaccess を使用して、ディレクトリ単位で PHP を「.php」以外の拡張子で動作させるための設定方法です。

基本的には、.htaccess に、以下を記述するだけで OK です。

AddType	application/x-httpd-php .html

.html じゃなくて、例えば .htm を PHP として動かしたければ、

AddType	application/x-httpd-php .htm

とすれば OK。

ただし、上記の例で言うところの .html や .htm という拡張子に、既に何らかの設定がなされている場合、PHP が正常に動かない場合があります。
その場合は、 AddType を設定する行の前に、

RemoveHandler	.html

という行を追加して、設定をクリアしておくと良いかもしれません。

まとめると、.html という拡張子で PHP を動かしたいときは、

RemoveHandler	.html
AddType	application/x-httpd-php .html

という二行を .htaccess に書いておく。ということになりますね。

関連するブログ記事
カテゴリー
.htaccess | PHP
タグ
.htaccess | AddType | PHP | RemoveHandler

コメント(24)

 

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

以前、メール受信時に perl スクリプトを起動して自動処理させる方法という記事を書きましたが、それのPHP版です。

上記のエントリでも書いていますが、メール受信時に何らかの処理を行なうプログラムを作る場合、

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

という2つのステップが必要ですが、そのうち1番目のステップに関しては、perl だろうが PHP だろうが、全く関係ありません。
なので、1ステップ目のメールサーバー側の設定に関しては、メール受信時に perl スクリプトを起動して自動処理させる方法を参照してください。

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

PHP というと、Webアプリケーションに特化した言語、というイメージがありますが、もちろん perl と同じように、シェル的な使い方もできます。

メールを受け取った PHP スクリプトで、標準入力の内容を読めば、メール受信時の処理を行なえます。

ちなみに PHP の場合、PEAR の Mail_Mime というパッケージを使うと、メール受信時の処理が非常に簡単になります。

PEAR については、さくらのレンタルサーバーに PEAR をインストールするも参考にどうぞ。

#-- PEAR の Mail/mimeDecode.php を読み込む
require_once 'Mail/mimeDecode.php';

#-- メールデータ取得
$params['include_bodies'] = true; 
$params['decode_bodies']  = true; 
$params['decode_headers'] = true; 
$params['input'] = file_get_contents("php://stdin"); // 標準入力
$params['crlf'] = "\r\n"; 
$mail_data = Mail_mimeDecode::decode($params); 

#-- From フィールドの取得
$FromAddress = $mail_data->headers['from']; 

#-- To フィールドの取得
$ToAddress = $mail_data->headers['to']; 

#-- Subject フィールドの取得
$Subject = $mail_data->headers['subject'];
$Subject = mb_convert_encoding($Subject,"UTF-8","JIS");

#-- 本文の取得
$MailBody = $mail_data->body;
$MailBody = mb_convert_encoding($MailBody,"UTF-8","JIS");

後は、取得したデータを元に、色々処理すれば良いです。

なお、添付ファイルつきのメールの場合、本文を上記の方法で取得できないと思います。あくまでテキストメールの場合の例ですので悪しからず。

関連するブログ記事
カテゴリー
PHP
タグ
Mail_Mime | PEAR | PHP | sendmail | SMTP | UNIX | ケータイメール | コマンドライン | メール | モバイル | レンタルサーバー

コメント(7)

 

さくらのレンタルサーバーに PEAR をインストールする

PEAR とはPHP Extension and Application Repository の略で、PHP のライブラリが色々入っているパッケージ群です。

さくらのレンタルサーバーには、一応 PEAR は入ってるみたいですが、用意されているパッケージが少ないので、もともと用意されているライブラリ以外のものを使いたい場合は、自分のサーバー領域にローカルコピーをインストールする必要があります。

というわけで、さくらのレンタルサーバーに PEAR をインストールする手順のメモです。

1. SSH でサーバーにログインする

SSH でサーバーにログインします。

2. 設定ファイルの作成

以下のコマンドで、PEAR のローカル設定ファイルを作成。

pear config-create /home/user/pear .pearrc

user」の部分はもちろん自分のユーザー名にすること。

3. .cshrc にパスを追加する

vi か何かで .cshrc を開き、「set path」の行に、以下を追加する。

~/pear/bin

4. PEAR のインストール

以下のコマンドで、ホームディレクトリに「pear」というディレクトリが作られ、パッケージが保存できるようになります。

pear install -o PEAR

5. 追加したいパッケージのインストール

続いて、自分が使いたいパッケージをインストールします。

例えば、Mail_Mime が使いたければ、

pear install Mail_Mime

とやればOK。

6. パッケージのリストを確認

以下のコマンドで、インストールされている PEAR パッケージのリストが確認できます。

pear list

これで、先ほどインストールしたパッケージ(前述の例では Mail_Mime)が一覧に表示されていれば、完了です。

7. 実際に PHP スクリプト内で PEAR を使うとき

普通なら、

require_once ("Mail/mimeDecode.php");

みたいな感じで、使用するパッケージを指定しますが、そのままだとパスが通っていないので、 include_path に「/home/user/pear/php」を追加するか(未確認)、以下のようにフルパスでパッケージを指定すればOKです。

require_once ("/home/user/pear/php/Mail/mimeDecode.php");

参考: Manual :: 共有ホストでの PEAR のローカルコピーのインストール

関連するブログ記事
カテゴリー
PHP | レンタルサーバー
タグ
PEAR | PHP | UNIX | さくらのレンタルサーバー | コマンドライン | シェル | レンタルサーバー

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

 

perl の CGI や PHP でフォーム入力チェックによく使う正規表現のまとめ

perl や PHP で Webアプリケーションを作る際、ユーザーがフォームに入力した値を受け取って、何らかの処理を行なう、というのは基本中の基本です。

ユーザーが入力した値をチェックして、こちらが想定したフォーマットで送られているかどうか確認し、想定外の値ならばエラーを返す、というのも基本中の基本ですね。

というわけで、そんなフォームからのユーザー入力の値のエラーチェックによく使いそうな正規表現をまとめてみました。

以下、perl の方は「$FORM{'data'}」という変数の中に、 PHP の方は「$_REQUEST['data']」という変数の中に、ユーザー入力の値が入っているとします。

半角数字のみを受け付ける場合

フォームに入力された値の中に、「半角数字以外が含まれている場合」にエラーを返すには、以下のようにします。

#-- perl の場合
if($FORM{'data'} =~ /\D/){
	print qq|Error: 半角数字で入力して下さい\n|;
}

#-- PHP の場合
if(preg_match("/\D/",$_REQUEST['data'])){
	print ("Error: 半角数字で入力して下さい\n");
}

ただし、上記の場合はフォーム入力が空の場合はチェックを通ってしまいますので、別途チェックが必要です。

なので以下のように、「1桁以上の半角数字のみ受け付ける」ようなチェック方法の方が良いかと思います。

#-- perl の場合
if($FORM{'data'} !~ /^\d+$/){
	print qq|Error: 半角数字で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^\d+$/",$_REQUEST['data'])){
	print ("Error: 半角数字で入力して下さい\n");
}

「5桁の数字のみ受け付ける」という場合は、以下のようにします。

#-- perl の場合
if($FORM{'data'} !~ /^\d{5}$/){
	print qq|Error: 5桁の半角数字を入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^\d{5}$/",$_REQUEST['data'])){
	print ("Error: 5桁の半角数字を入力して下さい\n");
}

桁数を変えたければ、「\d{5}」の部分を「\d{10}」とか「\d{6}」とかにすればOK。

「5桁ぴったりではなく、5桁以内(1~5桁)の半角数字のみ受け付ける」という場合は、以下のようにします。

#-- perl の場合
if($FORM{'data'} !~ /^\d{1,5}$/){
	print qq|Error: 1~5桁の半角数字を入力して下さい。\n|;
}

#-- PHP の場合
if(!preg_match("/^\d{1,5}$/",$_REQUEST['data'])){
	print ("Error: 1~5桁の半角数字を入力して下さい。\n");
}

1~5桁ではなく、2~4桁にしたければ「\d{1,5}」の部分を「\d{2,4}」にすれば良いですし、0~10桁にしたければ「\d{0,10}」にすればOK。

半角数字と半角ドット「.」のみ受け付ける場合

要するに、数字だけを入力して欲しいけれど、小数もOKにしたいので、小数点「.」も許可したい、という場合ですね。

半角数字と半角ドット以外が含まれている場合にエラーを返すには、以下のようにします。

#-- perl の場合
if($FORM{'data'} =~ /[^\d\.]/){
	print qq|Error: 半角数字と半角ドット「.」で入力して下さい。\n|;
}

#-- PHP の場合
if(preg_match("/[^\d\.]/",$_REQUEST['data'])){
	print ("Error: 半角数字と半角ドット「.」で入力して下さい。\n");
}

しかし、これも入力が空だと通ってしまいますし、半角ドットが二つ以上あっても通ってしまいますので「小数は許可したい」というニーズを超えてしまっています。

なので「一桁以上の数値からはじまっていて、0~1個の半角ドットと半角数字だけが含まれ、最後は半角数字で終わるもののみ受け付ける」という考え方で正規表現を書くのが良いかと思います。

#-- perl の場合
if($FORM{'data'} !~ /^\d$|^\d+\.?\d+$/){
	print qq|Error: 半角数字と半角ドット「.」で入力して下さい。\n|;
}

#-- PHP の場合
if(!preg_match("/^\d$|^\d+\.?\d+$/",$_REQUEST['data'])){
	print ("Error: 半角数字と半角ドット「.」で入力して下さい。\n");
}

上記は、「一桁の数字か、一桁以上の数字から始まって0~1個のドットを含み一桁以上の数字で終わる」もののみマッチします。

半角英数字のみ受け付ける場合

正規表現で「半角英数字」は「\w」で表すことができます。
また、「半角英数字以外」は「\W」で表すことができます。

2010/07/16追記
flagged utf8 では、「\w」に日本語が含まれるという指摘を頂きました。
参考リンク1 参考リンク2

なので、前述の「半角数字のみを受け付ける場合」の「\d」「\D」を「\w」「\W」に置き換えるだけで基本的には問題ないかと思います。

ただし「\w」には半角アンダーバー「_」も含まれます(逆に「\W」は正確には「半角英数字とアンダーバー以外」ですね)。
なので、半角アンダーバー「_」を除外したい場合は「\w」の代わりに「[A-Za-z0-9]」を使うのが良いかと。
また、「\W」の代わりは「[^A-Za-z0-9]」になります。

たまにあるケースで、ユーザーIDが「数桁の英字+数桁の数字」(ABC0123みたいな)で固定されているケースでは、それに応じた正規表現を書くのが良いでしょう。

例えば「3桁の英字+4桁の数字」の場合は以下のようになります。

#-- perl の場合
if($FORM{'data'} !~ /^[A-Za-z]{3}\d{4}$/){
	print qq|Error: 3桁の英字+4桁の数字を入力して下さい。\n|;
}

#-- PHP の場合
if(!preg_match("/^[A-Za-z]{3}\d{4}$/",$_REQUEST['data'])){
	print ("Error: 3桁の英字+4桁の数字を入力して下さい。\n");
}

英字が大文字のみで統一されている場合は「[A-Za-z]」の部分を「[A-Z]」に、小文字で統一なら「[a-z]」にしても良いですが、大文字と小文字でIDに差異がないのなら、どちらでも受け付けられる方がユーザビリティが良いでしょう。

郵便番号入力欄のエラーチェック

郵便番号は、ユーザーに入力の際にハイフンを省力してもらって、数字7桁のみ受け付けるようにするのが手っ取り早くて楽ですね。

#-- perl の場合
if($FORM{'data'} !~ /^\d{7}$/){
	print qq|Error: 郵便番号を半角数字(ハイフンなし)で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^\d{7}$/",$_REQUEST['data'])){
	print ("Error: 郵便番号を半角数字(ハイフンなし)で入力して下さい\n");
}

ハイフンありじゃないと困る、という場合は以下のような感じになります。

#-- perl の場合
if($FORM{'data'} !~ /^\d{3}-\d{4}$/){
	print qq|Error: 郵便番号を半角数字(ハイフンつき)で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^\d{3}-\d{4}$/",$_REQUEST['data'])){
	print ("Error: 郵便番号を半角数字(ハイフンつき)で入力して下さい\n");
}

ハイフンがあってもなくても受け付けるようにしたい、という場合は以下のような感じに。

#-- perl の場合
if($FORM{'data'} !~ /^\d{3}-?\d{4}$/){
	print qq|Error: 郵便番号を半角数字で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^\d{3}-?\d{4}$/",$_REQUEST['data'])){
	print ("Error: 郵便番号を半角数字で入力して下さい\n");
}

ハイフンがあってもなくても受け付けるようにしておいて、後でスクリプト内でハイフンを取り除いて統一させておくのが一番良いかもですね。

電話番号入力欄のエラーチェック

電話番号も、郵便番号と同じく、ユーザーに入力の際にハイフンを省略してもらうのが楽ですよね。

国内の電話番号は、多分「0から始まる10~11桁の数字」で大丈夫だと思うので、以下のような感じ。

#-- perl の場合
if($FORM{'data'} !~ /^0\d{9,10}$/){
	print qq|Error: 電話番号を半角数字(ハイフンなし)で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^0\d{9,10}$/",$_REQUEST['data'])){
	print ("Error: 電話番号を半角数字(ハイフンなし)で入力して下さい\n");
}

携帯電話に限定するなら「1文字目と3文字目が0で、全部で11桁の数字」で良いと思うので、以下のような感じでしょうか。

#-- perl の場合
if($FORM{'data'} !~ /^0\d0\d{8}$/){
	print qq|Error: 電話番号を半角数字(ハイフンなし)で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^0\d0\d{8}$/",$_REQUEST['data'])){
	print ("Error: 電話番号を半角数字(ハイフンなし)で入力して下さい\n");
}

ハイフンありの場合は「市外局番2~6桁-市内局番0~4桁-4桁の数字」(これで合ってるかどうか正直自信ないです)にマッチしているかどうかチェックすれば良いと思うので、以下のような感じ。

#-- perl の場合
if($FORM{'data'} !~ /^0\d{1,5}-\d{0,4}-?\d{4}$/
 || $FORM{'data'} !~ /^.{11,13}$/){
	print qq|Error: 電話番号を半角数字で入力して下さい\n|;
}

#-- PHP の場合
if(!preg_match("/^0\d{1,5}-\d{0,4}-?\d{4}$/",$_REQUEST['data'])
 || !preg_match("/^.{11,13}$/",$_REQUEST['data'])){
	print ("Error: 電話番号を半角数字で入力して下さい\n");
}

「市外局番2~6桁-市内局番0~4桁-4桁の数字」のチェックだけでなく、総文字数が11~13文字であるかどうかもチェックしています。
※単純な文字数チェックは length関数とか strlen関数とか使った方が良いと思いますが、今回は正規表現の記事なので、無理矢理正規表現でやってみました(^^;


他にもまだ色々ありますが、この記事書くのに意外と時間がかかったので、続きはまた次の機会に。

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
CGI | perl | PHP | preg_match | 正規表現

コメント(327)

 

perl や PHP で Excelファイル(xlsファイル)を簡単に出力する方法

perl や PHP で、Excelファイル(拡張子が「.xls」のファイルとか)を出力するために、色々とライブラリみたいなものがあるみたいなんですが、裏技的でちょっと邪道な、もっと簡単な解決方法があります。

Excel で作った文書を保存する際に、「Webページとして保存」というメニューがあることからも想像できますが、Excelで html文書を開いたら、普通に Excel 文書として読めるんですよね。

なので、 perl の CGI や PHP で、Excel 形式で出力しようと思ったら、perl の CGI や PHP でよく出力する Content-type ヘッダ一覧 (MIME-type)を参考に、以下のようなヘッダを出力。

#-- perl の場合
print qq|Content-type: application/vnd.ms-excel\n\n|;

#-- PHP の場合
header('Content-Type: application/vnd.ms-excel');

そしてその後は、普通に html を出力すれば、勝手に Excel が開いて、Excel 文書として出力されます。

Excel を開くのではなく、ダウンロードさせたい場合は、perlやPHPでファイルのダウンロード確認ダイアログを表示させる方法を参考にすれば良いと思います。

#-- perl の場合
print qq|Content-type: application/vnd.ms-excel\n|;
print qq|Content-Disposition: attachment; filename="sample.xls"\n\n|;

#-- PHP の場合
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="sample.xls"');

なお、Excel ファイルを前述のように「Webページとして保存」すると、作成したファイルが html 文書として保存されるので、それを元に編集して perl の CGI や PHP の出力結果を用意すると良いかと思います。
Excel が吐き出す html ソースは凄まじく汚くて読み辛いですが......。

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
CGI | Content-Disposition | Content-type | Excel | HTTPヘッダ | Internet Explorer | MIME | perl | PHP | Windows | xhtml | ダウンロード | 拡張子

コメント(541) | トラックバック(4)

 

PHP の便利なマルチバイト文字列操作(mb_***)系関数まとめ

プログラミングをする上で、マルチバイト文字(全角文字etc)の扱いというのはなかなか面倒な問題ですよね。
言語側で用意されている文字列操作系関数が、1バイト文字にしか対応していなくて困ったりとか。

PHP のマルチバイト文字操作系関数(mb_ が頭につく関数群)は、そういう意味で非常に便利な存在だといえます。

というわけで、個人的によくお世話になっている(or 今後なる予定の)関数群を、備忘録的にまとめておきます。

mb_check_encoding

文字列が、指定した文字コードかどうか判別する関数。

文字列 $string が utf-8 かどうか判別する場合、

if(mb_check_encoding($string,'UTF-8')){
	print ("\$string は UTF-8 です。\n");
}else{
	print ("\$string は UTF-8 ではないです。\n");
}

みたいな感じで使う。

mb_detect_encoding

文字列の文字コードを取得する。

$encode = mb_detect_encoding($string);

mb_convert_encoding

文字列を、指定した文字コードに変換する。

euc の文字列を utf-8 に変換する場合、

$utf8_string = mb_convert_encoding($euc_string,'UTF-8','EUC-JP');

みたいな感じで使う。

最後の「'EUC-JP'」の部分は、配列や、カンマ区切りの文字列で指定可能。
また「auto」を指定すると、自動判別してくれる(あまりあてにならない)。

mb_convert_kana

全角文字と半角文字の相互変換。

$string = mb_convert_kana($string,option,'UTF-8');

「option」の部分で、変換前・変換後の文字種を指定する。

a
全角英数字を半角英数字に変換。
A
半角英数字を全角英数字に変換。
s
全角スペースを半角スペースに変換。
S
半角スペースを全角スペースに変換。
k
全角カナを半角カナに変換。
K
半角カナを全角カナに変換。
h
全角かなを半角カナに変換。
H
半角カナを全角かなに変換。
c
全角カナを全角かなに変換。
C
全角かなを全角カナに変換。
V
濁点つき半角カナを一文字の全角文字に変換。K や H と併用。

mb_strlen

文字列の長さを、マルチバイト文字も各一文字扱いで取得する。

$length = mb_strlen($string,'UTF-8');

mb_substr

文字列を、マルチバイト文字も各一文字扱いで、指定した長さにして返す。

文字列の頭から20文字目までを取得したい場合、

$substring = mb_substr($string,0,20,'UTF-8');

みたいな感じにする。

mb_send_mail

自動で文字コードを変換した上で、メール送信する。

mb_send_mail($to_address,$subject,$mailbody);

ただし、自動文字コード変換はあまりあてにならないので、件名や本文の文字コードをあらかじめ変換しておくか、PHP 内部のデフォルト文字コードを設定しておく方が良いかも。
詳しくは、PHPのmb_send_mail()関数で送信したメールが文字化けする際の対処法を参照のこと。

関連するブログ記事
カテゴリー
PHP
タグ
mb_check_encoding | mb_convert_encoding | mb_convert_kana | mb_detect_encoding | mb_send_mail | mb_strlen | mb_substr | PHP | 文字コード | 文字化け

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

 

PHP と perl の配列の添え字に関するメモ

PHP の配列自動指定について

PHPでは、配列に空の添え字を指定することで、自動で添え字を +1 できるんですね。
恥ずかしながら知りませんでした。

例えば、

$list = array();
for($a=0;$a<10;$a++){
	$list[] = $a;
}

と書けば、 $list[0]~$list[9] にそれぞれ 0~9が入る、と。

他にも、

$list = array();
$list[0] = 'Red';
$list[1] = 'Blue';
$list[5] = 'Purple';
$list[] = 'Pink';

とやると、最後の行は $list[6] = 'Pink'; となるそうな。

perl では似たような方法あるのかな......?

PHP と perl の配列の添え字最大値取得方法

上記のような手段を取ると、やっぱり配列の添え字の現在の最大値を見るような処理が必要になってくるケースなんかもある気がします。

そういう場合、perl だと、

@list = ('Red', 'Blue', 'Purple', 'Pink');
$max = $#list;

という感じで、$#配列名 で配列の添え字の最大値が取得できます。

PHPの方にはざっと調べたところ、こういう簡単な手段はないようで、

$list = array('Red', 'Blue', 'Purple', 'Pink');
$max = max(array_keys($list));

とかやるみたいです。

参考: 最大添字を取得するには - Yahoo!知恵袋

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
perl | PHP | 配列

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

 

XAMPP で Windows 上に Webサーバー(Apache) と PHP と MySQL と FTPサーバー(Filezilla) と メールサーバー(Mercury) を一括でインストール

Windows上にPHPの開発環境を用意する上で、非常に便利な XAMPP の紹介です。

XAMPP を使えば、一括で以下の環境を Windows 上に用意することができます。

  • Webサーバー(Apache)
  • PHP
  • MySQL
  • phpMyAdmin
  • FTPサーバー(FileZilla)
  • メールサーバー(Mercury)

それぞれを別個のサイトからダウンロードしてインストールしなくても、XAMPPだけで、これらの開発環境が揃うわけです。
便利な世の中になったもんですよねー。

というわけで、以下導入手順です。

1. XAMPP をダウンロードする

XAMPP 導入手順(1)

apache friends - xampp for windowsへアクセスし、XAMPP をダウンロードします。

 
XAMPP 導入手順(2)

画面を下の方にスクロールしていくと、ダウンロードサイトへのリンク一覧が出てきます。

特にこだわりや理由がなければ、インストーラをダウンロードするのが手っ取り早いと思います。

「XAMPP Windows版 〔ベーシックパッケージ〕」の「インストーラ」のリンクからダウンロードします。

 

2. XAMPP をインストールする

XAMPP 導入手順(3)

ダウンロードした XAMPP インストーラを起動すると、言語選択のダイアログが表示されます。

「Japanese」を選択して「OK」をクリック。

 
XAMPP 導入手順(4)

「セットアップウィザードへようこそ」という画面が表示されるので、「次へ」をクリック。

 
XAMPP 導入手順(5)

インストール先のフォルダを指定します。
左記画面の例では、「C:\xampp」を指定しています。

ここで指定したフォルダに、 XAMPP のコントロールパネルとか、Apache とか MySQL とか PHP とか、その他もろもろが全部インストールされます。

指定したら「次へ」をクリック。

 
XAMPP 導入手順(6)

オプション設定画面。

「Apache をサービスとしてインストール」「MySQL をサービスとしてインストール」「FileZilla をサービスとしてインストール」にチェックを入れておくと、これらを Windows サービスとして利用できるので、便利です。

ただし、既にWindows 上でWebサーバーとして IIS を利用している場合等は、一旦 IIS を停止しておかないと、サービスとして Apache がインストールできなかったり、色々と不具合があるかもしれません。

チェックを入れたら「インストール」をクリック。

 
XAMPP 導入手順(7)

インストールが始まります。

そこそこ時間がかかるので、しばらく待ちましょう。

 
XAMPP 導入手順(8)

インストール完了画面。
これでXAMPP のインストールは完了です。

「完了」をクリック。

 

3. コントロールパネルを触ってみる&セキュリティ関連の設定

XAMPP 導入手順(9)

インストールが完了すると、「XAMPP コントロールパネルを今すぐ起動しますか?」というダイアログが表示されます。

「はい」をクリック。

 
XAMPP 導入手順(10)

XAMPP のコントロールパネルが起動します。

この手順通りにインストールしていれば、「Apache」「MySQL」「FileZilla」が「起動」の状態になっているかと思います。

各モジュールの右側にある「停止」または「停止中」ボタンをクリックすれば、それぞれのサーバーを停止できます。

 
XAMPP 導入手順(11)

さて、実際にApache が Webサーバーとして動いているのか、確認してみましょう。

ブラウザを立ち上げて、http://localhost/ あるいは、http://127.0.0.1/ へアクセスしてみます。

左記のような画面が表示されれば、Apache は正常に動作しています。

XAMPP の Web管理画面に入るため、右下の「日本語」をクリックします。

 
XAMPP 導入手順(12)

XAMPP の Web管理画面です。

とりあえず、最低限のセキュリティ設定を行なうため、左のメニューから「セキュリティ」をクリックします。

 
XAMPP 導入手順(13)

現在のセキュリティ関連の状態がどうなっているか、一覧で簡単に教えてくれます。
ほとんどの項目が「要注意」になっているかと思います。

そのテーブルの下に http://localhost/security/xamppsecurity.php へのリンクがあるので、それをクリック。

 
XAMPP 導入手順(14)

MySQL の root のパスワードを設定するフォームと、XAMPP の Web管理画面に .htaccess で Basic認証を設定するフォームの二つが表示されます。

とりあえず、まずは MySQL の root のパスワードを設定しましょう。

任意のパスワードを入力し、phpMyAdmin の認証方法(初期設定では Cookie)を選択。

フォーム下部のチェックボックスにチェックを入れると、設定したパスワードを、自動でテキストファイルに保存しておいてくれます。
まあ、その行為自体がセキュリティ的にどうなんだ、的な感じではありますので、その辺はお好みで。

そして「パスワードを変更しました」というボタンをクリック。

 
XAMPP 導入手順(15)

MySQL の root のパスワードを正常に設定できれば、「root のパスワードを変更しました。設定を有効にするために、MySQL を再起動してください。」と表示されます。

 
XAMPP 導入手順(16)

XAMPP のコントロールパネルを再度開きます。

MySQL が「起動」状態になっているはずなので、一旦「停止」ボタンをクリックします。

 
XAMPP 導入手順(17)

MySQL の「起動」状態が消えます。

再び「開始」ボタンをクリックして「起動」状態に戻します。

これで MySQL の再起動は完了。

 
XAMPP 導入手順(18)

再び、XAMPP の Web管理画面のセキュリティ設定フォームの方に戻ります。

次は、Web管理画面に .htaccess で Basic認証をかけるための設定を行ないます。

Basic認証については、「.htaccessによるBasic認証のかけ方」「.htaccess で特定のファイルのみにBasic認証を設定する方法」等も参考になれば。

フォームに、Basic認証に利用するユーザー名とパスワードを入力します。

MySQL の root のパスワードを設定した際と同様に、チェックボックスにチェックを入れると、ユーザー名とパスワードをテキストファイルに保存してくれますが、こちらもお好みで。

入力したら「安全な XAMPP ディレクトリを作成してください」というボタンをクリック。

 
XAMPP 導入手順(19)

「成功: XAMPP ディレクトリ制御が成功しました! 全ユーザのデータは、以下のファイルに格納されました:」と表示されたら、設定完了です。

 
XAMPP 導入手順(20)

以後、XAMPP の Web管理画面にアクセスすると、左記画像のように、Basic認証のダイアログが出るようになります。

とりあえず、これで最低限の設定は完了です。

 

なお、 XAMPP をインストールしたフォルダ内に「htdocs」というフォルダが作られています。
このフォルダ内にファイルを放り込めば、「http://localhost/***.html」等の URI でアクセスできます。

関連するブログ記事
カテゴリー
MySQL | PHP | Web制作技術
タグ
.htaccess | Apache | Basic認証 | FileZilla | FTP | Mercury | MySQL | PHP | phpMyAdmin | SMTP | Windows | XAMPP | アクセス制限 | オープンソース

コメント(5)

 

fgetcsv()関数について

2007年12月 5日 11:37 fgetcsv()関数について

本日も旧ブログからの転載です。

PHP の fgetcsv 関数に関するエントリーですが、2年半ほど前に書いたものなので、現状の PHP のバージョンではまた色々と違ってくるかもしれません。

もう fgetcsv 関数は全然使わなくなったので、現状でどういう挙動なのかはさっぱり知りませんが、まあ何かの参考になれば。


データ群を、特定の文字を区切りとしてcsv形式で保存し、phpから取り出すことはよくあると思うのですが、そういう時に便利なのが fgetcsv()関数。
が、この関数はphpのバージョンによって微妙に挙動が違ったりするようなので、適当に使ってると別のサーバーで同じスクリプトを使うと痛い目に遭ったりします。

array fgetcsv ( resource handle, int length [, string delimiter [, string enclosure]])

fgets()に動作は似ていますが、 fgetcsv()は行をCSVフォーマッ トのフィールドとして読込み処理を行い、読み込んだフィールドを含む 配列を返すという違いがあります。フィールドのデリミタは、オプショ ンの3番目のパラメータで別のデリミタを指定した場合を除きカンマです。 また、オプションの enclosure (フィールド囲い子) パラメータは、別の文字を4番目のパラメータで 指定しない限り、デフォルトではダブルクォーテーショーンマークとなります。 enclosuredelimiter はそれぞれ1文字に限られており、もし1文字を超える文字列が指定された場合は、 最初の文字だけが使われます。

日本PHPユーザ会マニュアル内「fgetcsv」の頁より。

つまり、ファイルを一行ずつ読み込んで、特定の区切り文字でsplitして、という作業をこの関数が一発で済ましてくれるわけです。

ここでまず重要なのは最後の「enclosuredelimiter はそれぞれ1文字に限られており、もし1文字を超える文字列が指定された場合は、 最初の文字だけが使われます。」という一文。
フィールドの区切りは1文字に限定されますので、perlのcgiなんかでよく使われていた(orる)「<>」を区切りに使う手法は使えません。
カンマ「,」区切りとか、タブ「\t」区切りとかを使いましょう。
「もし1文字を超える文字列が指定された場合は、 最初の文字だけが使われます。」とありますが、「\t」を「\」と「t」の二文字として判断したりはしません。

次に、「enclosure (フィールド囲い子) パラメータは、別の文字を4番目のパラメータで 指定しない限り、デフォルトではダブルクォーテーショーンマークとなります。」という一文。
私はマニュアルを良く読まずに「enclosureを指定しなければ、フィールドの囲い子は「ない」として扱われると思いこんでいたため(そしてうちのサーバーではそれで問題なく動いてしまっていた)、そのスクリプトを他所様のサーバーで動かすと大量に文字化けが発生してしまいました。

この件の場合、fgetcsv()を使っている箇所は何も弄らずに、データ自体の各フィールドをダブルクォーテーションで括るようにしたところ、無事に意図通りの挙動をするようになりました。

とは言え、enclosureを指定せず、データの囲い子がない状態でもうちのサーバーだとちゃんと区切ってくれたと言うことは、逆にenclosureをちゃんと指定しておかないとどういう挙動をするかわからない、という可能性もあるわけで。
というわけで、このfgetcsv()関数を使う際、enclosuredelimiterは省略可能なオプションとして設定されていますが、必ず指定した方が良さそうです。
また、色々ぐぐってみたところ「fgetcsv()関数はあてにならない」というような意見も結構見受けられましたので、使いどころには気をつけた方が良さそうです。

関連するブログ記事
カテゴリー
PHP
タグ
fgetcsv | PHP

コメント(2)

 

phpPgAdmin導入メモ

2007年12月 3日 02:02 phpPgAdmin導入メモ

今回も旧ブログから記事を引っ張ってきました。

2年半以上前の記事ですが、まあ何かの参考にはなるかな、と。

というわけで、以下は過去に使っていたレンタルサーバーでの phpPgAdmin のインストール手順のメモです。


1. はじめに

phpPgAdminは、PostgreSQLデータベースをGUIで操作するためのWebアプリケーションです。名前の通り、プログラム本体はPHPで記述されていますので、PHPの動作する環境でないと使えません。

このphpPgAdminのことは以前から知っていたのですが、今までSSHでサーバーにログインしてコマンドラインからpsqlを起動しての管理に特に不便を感じていなかったことと、インストールがめんどくさそう、という理由から導入は見送っていました。

が、つい先日別のWebサーバーでphpPgAdminを使う機会があって、その想像以上の操作の便利さに導入を決めました。
以下はこのサイトで使っているレンタルサーバーでのphpPgAdmin 3.5.3の導入手順です。

※ちなみに、同じようにPHPで記述されたMySQL管理用のWebアプリケーション「phpMyAdmin」というのもあります(というかこっちの方が有名かも)。

2. phpPgAdminのダウンロード

phpPgAdmin公式サイトより、ソースコード本体をダウンロードします。


3. config.inc.php の編集

ダウンロードしたファイルを解凍し、 conf/ ディレクトリを開きます。
config.inc.php-dist というファイルがあるので、同一ディレクトリ内に config.inc.php という名前でこれのコピーを作ります。
※config.inc.php-dist は設定ファイルのデフォルトの状態が記述されたファイルなので、万が一のために残しておく方が良いかと思われます。

コピーした config.inc.php をテキストエディタで開き、下記のように編集しました。

// データベース名を自分の使用しているものに変更
$conf['servers'][0]['defaultdb'] = 'template1';
  ↓
$conf['servers'][0]['defaultdb'] = 'amethyst';

// 画面に表示される言語を英語から日本語に変更
$conf['default_lang'] = 'english';
  ↓
$conf['default_lang'] = 'japanese';

// レンタルサーバーを利用しているため、他のユーザーアカウントのDBが見えてしまうと
// 邪魔&色々困るのでownerが私になってるものだけ表示するように設定
$conf['owned_only'] = false;
  ↓
$conf['owned_only'] = true;

4. ひたすらアップロード

編集した config.inc.php を含む全ファイルをアップロードします。


5. Basic認証の設定

自分以外の人間にphpPgAdminでDBをいじられるととっても困るので、phpPgAdminをインストールしたディレクトリにBasic認証をかけておきます。
Basic認証のかけ方は.htaccessによるBasic認証のかけ方等を参照。


6. 動作確認

phpPgAdminをインストールしたディレクトリの index.php にアクセスします。
ログインフォームが表示されるので、PostgreSQLのユーザー名とパスワードを入力し、ログインできればインストールは正常に完了しているかと思われます。

後はお好きなように。

関連するブログ記事
カテゴリー
PHP | PostgreSQL
タグ
.htaccess | Basic認証 | CMS | PHP | phpPgAdmin | PostgreSQL | RDBMS

コメント(2)

 

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)

 

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 の CGI や PHP でよく出力する Content-type ヘッダ一覧 (MIME-type)

ここ数日、perlやPHPでファイルのダウンロード確認ダイアログを表示させる方法へのアクセスが、すば抜けて多いです。

こういうスクリプトを書こうとしている人って多いんでしょうか。

なので、件のエントリーの補完ということで、今回は perl の CGI や PHP で個人的によく出力する or 今後出力する機会がありそうな Content-type ヘッダをまとめておきます。
まとめとけば自分が後で一番楽だし。

テキスト・文書・MSオフィス関連

ファイルの種類 拡張子 MIME-Type
テキスト文書 .txt text/plain
CSVファイル .csv text/csv
TSVファイル .tsv text/tab-separated-values
ワード文書 .doc application/msword
エクセルシート .xls application/vnd.ms-excel
パワーポイント .ppt application/vnd.ms-powerpoint
PDF文書 .pdf application/pdf
Docuworks .xdw application/vnd.fujixerox.docuworks
HTML文書 .html .htm text/html
スタイルシート .css text/css
JavaScriptファイル .js text/javascript
HDML文書 .hdml text/x-hdml

画像関連

ファイルの種類 拡張子 MIME-Type
JPEG .jpg .jpeg image/jpeg
PNG .png image/png
GIF .gif image/gif
ビットマップ .bmp image/bmp
イラストレーター .ai application/postscript

音声関連

ファイルの種類 拡張子 MIME-Type
MP3 .mp3 audio/mpeg
MP4 .m4a audio/mp4
WAV .wav audio/x-wav
MIDI .mid .midi audio/midi
SMAF .mmf application/x-smaf

動画関連

ファイルの種類 拡張子 MIME-Type
MPEG .mpg .mpeg video/mpeg
WMV .wmv video/x-ms-wmv
Flash (Shockwave) .swf application/x-shockwave-flash
3GPP2 .3g2 video/3gpp2

圧縮ファイル関連

ファイルの種類 拡張子 MIME-Type
ZIP形式 .zip application/zip
LZH形式 .lha .lzh application/x-lzh
tar / tar+gzip形式 .tar .tgz application/x-tar

その他

ファイルの種類 拡張子 MIME-Type
実行ファイル .exe application/octet-stream

perl なら出力の一番最初に、

print qq|Content-type: MIME-Type\n|;

PHPなら出力の一番最初に、

header("Content-type: MIME-Type");

とやれば良いわけです。

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
CGI | Content-type | HTTPヘッダ | MIME | perl | PHP | RFC | ダウンロード

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

 

Yahoo!モバイルのjigブラウザ機能の問題点と、perlとPHPでのjigブラウザのUser-Agent振り分け方法

「ケータイでPCのサイトが閲覧できる!」という謳い文句の割に、所謂「フルブラウザ」と比較しても機能的に中途半端で(特にJavaScript非対応はイタい)、個人的にはあんまり使い物にならないと思っている jigブラウザ。

同一URLで、User-Agentを元にして、ケータイとPCを自動で振り分ける際に、jigブラウザをPCサイト側に振り分けると、サイトの構成によっては、あまりいただけないことになってしまいます。

特に問題なのが、ケータイ版のYahoo!検索「Yahoo!モバイル」で検索した際に「PCサイトとの一致」でヒットしたサイトは、自動的にjigブラウザで表示されてしまうこと。

Yahoo!モバイルのインデックスが微妙なせいで、ケータイサイトとPCサイトを同一URLで公開していると、「携帯サイトとの一致」ではヒットしないけど「PCサイトとの一致」ではヒットする、みたいなことも起こりうるんですよね。

「PCサイトとの一致」でヒットしたサイトを、自動でjigブラウザで表示するのは基本的には便利な機能なんですが……。
こっちはちゃんとケータイに合わせた仕様でのサイトを提供しているんだから、わざわざ中途半端な機能しかないjigブラウザでPCサイト見るくらいなら、普通にケータイ用のブラウザでケータイ向けサイトを見てもらった方が、まともにサイト内のコンテンツを利用することができるわけです。

そういうわけで、jigブラウザからのアクセスの場合は、それを判別して、サイト内に注意書きを自動で入れるとか、そもそもjigブラウザでもケータイ向けサイトを表示するようにするとか、そんな対処が必要になります。

「Yahoo!モバイル」等で提供されている「jigブラウザ WEB」のデフォルトのUser-Agentは、

Mozilla/4.0 (jig browser web; version; 機種名

という感じです。
version」はjigブラウザのバージョン。「1.0.4」みたいな数字が入る。
機種名」は利用している携帯の機種名。「F904i」「812SH」みたいなのが入る。

なのでとりあえず、User-Agent内に「jig browser web」が含まれている場合はjigブラウザだと判断して、何らかの処理をするのが手っ取り早いかと思います。

perlなら、

if($ENV{'HTTP_USER_AGENT'} =~ /jig browser web/){
	#-- ここにjigブラウザの場合の処理
}

PHPなら、

if(preg_match("/jig browser web/",$_SERVER['HTTP_USER_AGENT'])){
	// ここにjigブラウザの場合の処理
}

こんな感じで。

ちなみに、GoogleもPCサイトの検索結果に出たサイトを携帯で見る場合、独自のブラウザを介して表示しますが、こっちは未調査です。
そのうち調べます。

関連するブログ記事
カテゴリー
PHP | perl/CGI | モバイル(携帯電話・ケータイ)Web
タグ
jigブラウザ | perl | PHP | User-Agent | Yahoo!モバイル | YST | モバイル | 環境変数

コメント(8)

 

perlやPHPでファイルのダウンロード確認ダイアログを表示させる方法

perlやPHPを使って、ユーザーにWebブラウザから何らかのファイルをダウンロードしてもらうスクリプトというのは、作る機会も結構多いかと思います。

しかし、ダウンロードしてもらうファイルがjpegやpng、gif等の画像ファイルだったり、PDFやワード・エクセル等のファイルだったり、音声や動画ファイルだったり等、ブラウザでそのまま閲覧できるファイルだった場合、ローカルにダウンロードするダイアログが出ずに、そのままブラウザに表示されてしまうことがよくあります。

そういう場合、「『右クリック⇒対象をファイルに保存』でローカルに保存できます」なんて注意書きをつけて、そのCGIやPHPスクリプトにリンクを張ることも多いかもしれませんね。

この現象は、CGIやPHPからブラウザに送信するHTTPヘッダを少し変えることで、避けることが可能です。
(ただし、ブラウザによっては駄目かも……)

具体的には、以下のようなHTTPヘッダを送信します。

Content-Disposition: attachment; filename="sample.jpg"

sample.jpg」の部分には、ファイルのダウンロードダイアログにデフォルトで表示される、保存先ファイル名を指定します。

これを踏まえて、perlである特定のjpeg画像を、ダウンロード確認ダイアログを表示させてダウンロードさせる場合は、以下のようになります。

#-- ダウンロードさせる元ファイル
$source = '/home/tatsuya/data/img/00001.jpg';
#-- 保存時のファイル名(デフォルト)
$filename = 'uetoaya.jpg';

#-- HTTPヘッダ送信
print qq|Content-type: image/jpeg\n|;
print qq|Content-Disposition: attachment; filename="$filename"\n|;
print qq|\n|;
#-- ファイルを読み込んで出力
open(FILE,"$source");
while(<FILE>){print;}
close(FILE);

PHPの場合は、以下のような感じ。

// ダウンロードさせる元ファイル
$source = '/home/tatsuya/data/img/00002.jpg';
// 保存時のファイル名(デフォルト)
$filename = 'aibusaki.jpg';

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

何らかのWebアプリケーションのバックアップデータなんかをダウンロードする場合とかは、保存時のファイル名を「ダウンロード時の日付.txt」みたいな感じにするようにしとくと便利かもですね。

関連するブログ記事
カテゴリー
PHP | perl/CGI
タグ
CGI | Content-Disposition | Content-type | HTTPヘッダ | perl | PHP | ダウンロード

コメント(34)

 

PHPのmb_send_mail()関数で送信したメールが文字化けする際の対処法

PHPというのは非常に便利なスクリプト言語で、perlなんかと比べても非常にコーディングか楽チンです。

例えば、sendmailを利用してサーバーからメールを送信する、なんて処理も、perlだったら大体以下のような処理するコードを順番に書いてやる必要があります。

  1. メールヘッダを文字列として定義する
  2. メール本文を文字列して定義する
  3. メールヘッダとメール本文の文字コードをJISに変換する
  4. sendmailのパイプを開く
  5. sendmailに文字コード変換したメールヘッダとメール本文を渡す

でも、PHPならこれらの処理をmb_send_mailという関数ひとつでやっちゃえるわけです。
(勿論、perlでも何らかのライブラリなりモジュールを使えば関数一つでやっちゃえますが)

具体的には、以下のような感じですね。

// 件名
$subject = '主人じゃ…満足できなくて!!';
// 本文
$mailbody = 'おいしそうな人妻がイッパイで攻略の価値大';
// メール送信
mb_send_mail("test@abe-tatsuya.com",$subject,$mailbody);

test@abe-tatsuya.com」の部分が宛先メールアドレス。
$subject」の部分が件名。
$mailbody」の部分が本文。
ちなみに、件名と本文は、ちょうど今届いたSPAMメールをそのままコピーしました(笑)。

まあとにかく、こんな感じで非常にシンプルで簡単な関数があるわけなんですが、意外とこの関数を使ってメールを送信した際に、文字化けするケースが多いです。

原因は、PHPのスクリプトを書いている文字コードと、そのPHPスクリプトを動作させるサーバーのデフォルトの文字コード設定の相違にあることがほとんどだと思います。

解決方法としては、

  1. 件名や本文等の文字コードを事前に変換しておいてから、mb_send_mail関数を使う
  2. PHPスクリプト内のデフォルトの文字コード設定を変える

というあたりが手っ取り早いでしょうか。
サーバーの設定を変えることが可能で、変えても他のWebアプリケーションなどに影響がないのであれば、そちらを変えちゃう方が手っ取り早いかもしれませんが……。

とりあえず、1番目の「件名や本文等の文字コードを事前に変換しておいてから、mb_send_mail関数を使う」場合は、以下のような感じになります。

// 件名
$subject = '初めて浮気しました・・・';
// 本文
$mailbody = '話題の新サイト、こっそり教えちゃいます!!';

// 件名をJISに変換
$subject = mb_convert_encoding($subject,"JIS");
// 本文をJISに変換
$mailbody = mb_convert_encoding($mailbody,"JIS");

// メール送信
mb_send_mail("test@abe-tatsuya.com",$subject,$mailbody);

ちなみに、件名と本文は今届いたSPAMを(ry

そして二番目、「PHPスクリプト内のデフォルトの文字コード設定を変える」の方。
こっちの方が楽だし、スクリプトも短くて済みます。

// カレントの言語を日本語に設定する
mb_language("ja");
// 内部文字エンコードを設定する
mb_internal_encoding("UTF-8");

// 件名
$subject = '週末とか逢えませんか?';
// 本文
$mailbody = 'これ見て貰えれば1時間だけでも時間作ってもらえますか?';

// メール送信
mb_send_mail("test@abe-tatsuya.com",$subject,$mailbody);

ちなみに、件名と本文は(ry

「mb_internal_encoding("UTF-8");」の部分は、UTF-8で書いたPHPスクリプトの場合です。

eucで書いたPHPスクリプトなら、下記のようになります。

mb_internal_encoding("EUC-JP");

で、SHIFT_JISで書いたPHPスクリプトなら、下記のようになります。

mb_internal_encoding("SJIS");

mb_internal_encoding関数は、場合にもよりますが、mb_send_mail関数を使う直前に毎回入れるよりも、スクリプトの最初の方で事前に使って、あらかじめ設定しておいた方が、後々のメンテとかが楽になりますね。

関連するブログ記事
カテゴリー
PHP
タグ
mb_convert_encoding | mb_internal_encoding | mb_language | mb_send_mail | PHP | sendmail | 文字化け

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

 

php.iniの設定を.htaccessで変更する。

PHPスクリプトの各種挙動に関する設定は、php.iniという設定ファイルによって、Webサーバー単位で管理されています。

複数のユーザーが利用しているレンタルサーバーの場合、各ユーザーが自分の都合によってphp.iniの設定を書き換えるようなことは、基本的にはできません。

そういうケースで、各ユーザーがphp.iniの設定とは異なる設定で、PHPを動かしたい場合、.htaccessを利用することで、それが実現できます。

PHPを置くディレクトリの.htaccessに、

php_flg なんとかかんとか on

とか、

php_value うんともかんとも ほげ

とかやります。

今までに世話になった項目としては、以下のようなものがあります。

php_flag magic_quotes_gpc Off

PHP側で、フォーム等から入力された引用符(ダブルクォーテーション「"」やシングルクォーテーション「'」)に対して、自動でバックスラッシュ「\」を頭につけてエスケープする処理が効いていた時に、その設定をオフにするために使いました。

php_flag output_buffering Off
php_value default_charset EUC-JP
php_value mbstring.language Japanese
php_flag mbstring.encoding_translation On
php_value mbstring.http_input auto
php_value mbstring.http_output EUC-JP
php_value mbstring.internal_encoding EUC-JP
php_value mbstring.substitute_character none

基本的に文字コードeucでPHPを動かすことが多かった頃、そのレンタルサーバーのデフォルトの文字コード設定がeucではなかったために、フォームから受け取った文字が化けまくった際に、この辺を指定したら直ったことがありました。

php_flag display_errors On

PHPのエラー表示機能がオフになっている設定のサーバーで、デバック時だけエラーを出したい、なんて時に頻繁に世話になります。

今回は以上で。
またネタに詰まった時にでも、続きを書きます。

関連するブログ記事
カテゴリー
.htaccess | PHP
タグ
.htaccess | PHP | php.ini | レンタルサーバー

コメント(9)