エントリー

タグ「PHP」の検索結果は以下のとおりです。

PHP入門

以前に書いたPHP入門、「PHP4 + Shift-JIS + PEAR::DB」で解説していましたが「PHP5 + UTF-8 + PDO」での解説に書き換えました。ついでにXAMPPのインストール方法なども追加しています。

http://www.php-labo.net/tutorial/

「そのうち書き換えたいなぁ…」で放置すること数年、仕事へ流用する必要に迫られたので、やっと作業した…。(´・ω・`)

新着マークが付いていないページでも、ほとんどのページに何らかの加筆修正をしてあります。まだ説明不足だったりスクリーンショットが無駄に大きかったりする箇所がありますが、気長に書き換えていくとします。

PHPで表示言語を自動判別

仕事で「日本語環境からアクセスすると日本語ページ」「英語環境からアクセスすると英語ページ」のような切り替えを自動で行う方法を尋ねられたので、具体的な方法を調べてみた。
なかなか目当ての情報にたどり着けなかったけど、主に以下のページを参考にプログラムを作成してみた。

例えば、日本語・英語・中国語を自動判別するなら以下のようなコードで大丈夫そう。

<?php

$languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$languages = array_reverse($languages);

$result = '';

foreach ($languages as $language) {
  if (preg_match('/^ja/i', $language)) {
    $result = 'Japanese';
  } elseif (preg_match('/^en/i', $language)) {
    $result = 'English';
  } elseif (preg_match('/^zh/i', $language)) {
    $result = 'Chinese';
  }
}

if ($result == '') {
  $result = 'Japanese';
}

echo $result;

?>

環境変数の「HTTP_ACCEPT_LANGUAGE」にブラウザの言語設定が格納されているので、それをもとに自動判別。
言語は複数設定できる上に優先順位も設定できるので、その対策もしておいた。(単純に「HTTP_ACCEPT_LANGUAGEにenが含まれていたら英語環境」のように判別すると、表示言語を複数設定している場合に問題が起きるので、一つ一つ判別。)
稀に大文字で情報が格納されていることもあるそうなので、大文字小文字は区別しないようにもしておいた。
なお、言語が判別できなかった場合は強制的に日本語環境とみなすようにしています。

freo設置のトラブルシューティング

freo設置について色々調べる機会があったのでまとめ。freoというよりPHP5利用のトラブルシューティングと言った方がいいかも。

ファーストサーバー

コンフィグレータにアクセスし、「PHPインストール」で実行バージョンを「PHP5(DSO版)」に変更する。
freoの設置ディレクトリもしくはその上位ディレクトリに .htaccess を作成し、以下の内容を記述する。

php_flag mbstring.encoding_translation Off
php_value default_charset UTF-8
php_flag output_buffering Off
php_value output_handler None

MySQLを使用する場合、データベース作成の際に

  • 接続照合順序は「utf8_unicode_ci」のまま
  • 照合順序は指定せず(そのまま)

で作成する。

freoの設定ファイル(config.php)にある FREO_DATABASE_CHARSET は設定しなくて(そのまま)で大丈夫そう。

CORESERVER

freoの設置ディレクトリもしくはその上位ディレクトリに .htaccess を作成し、以下の内容を記述する。

AddHandler application/x-httpd-phpcgi .php
mod_gzip_on Off

WADAX

mod_rewriteを使用する場合、freoの設置ディレクトリもしくはその上位ディレクトリに .htaccess を作成し、以下の内容を記述する。

Options FollowSymLinks Includes

ロリポップ+PHP5での設定変更

freoの設置難易度を下げるためにあれこれ実験していたところ、ロリポップ+PHP5で、ini_set() が使えるようになっていました。

以前に「.htaccessでの変更も、ini_set()での変更も許可しない」と公式にアナウンスされてショックを受けたのだけど、いつの間にか仕様が変わったのかなぁ…。公式な告知は見当たらないけど。

もし「サーバーの設定ミスで、一時的に使えるだけ」なら悲しいけど、どうなんだろう…。

PHP+ImageMagick その3

さらにImageMagickについて。

ImageMagickの実行には exec() 関数を使っていたけど、shell_exec() の方が個人的には読みやすいので変更。

<?php

echo shell_exec('/usr/bin/convert -version');

?>

ロリポップでImageMagickを使えなかったのは、PHPの設定で safe_modeOn にしていたからでした。すっかり忘れてた…。(正確には、ImageMagickではなく exec()shell_exec() の実行に制限がかかります。)
Off にすれば無事実行できました。一安心。

また、ImageMagickは処理結果は常にファイルに出力されるのかと思っていたけど、標準出力に渡すこともできるのですね。
以下のようにすれば、150px×150pxのサムネイルを直接画面に表示できます。

<?php

echo shell_exec('/usr/bin/convert -geometry 150x150 illust.png -');

?>

さらに、以下のようにすればJpegに変換した上で直接画面に表示できます。

<?php

echo shell_exec('/usr/bin/convert -geometry 150x150 illust.png jpg:-');

?>

freoで使いそうなのはサムネイル作成と画像形式変換くらいなので、これで実装できそうです。

PHP+ImageMagick その2

freoに実装するためにImageMagickの使い方を調べてみたのでメモ。…と思ったけど、メモするほどでもないかも。(^^;
色々な処理がとても簡単にできて素敵です。

バージョン情報を表示

/usr/bin/convert -version

PNGをGifに変換

/usr/bin/convert illust.png illust.gif

PNGをJpegに変換

/usr/bin/convert illust.png illust.jpg

150px×150pxのサムネイルを作成

/usr/bin/convert -geometry 150x150 illust.png thumbnail.png

画質70を指定して150px×150pxのサムネイルを作成

/usr/bin/convert -geometry 150x150 -quality 70 illust.png thumbnail.jpg

PHP+ImageMagick

特に気にしていなかったけど、GDよりもImageMagickの方が綺麗な画像が作れるらしいので、PHPからImageMagickを呼び出す方法を調べてみた。

PHPではPECLのImagickクラスでImageMagickを扱えるみたいだけど、利用できるサーバーは少ないようなので、直接ImageMagickを呼び出す方法にしてみます。

<?php

exec('/usr/bin/convert -version', $output);

print_r($output);

?>

とりあえずバージョン情報を表示するだけのプログラム。ImageMagickが使えるサーバーなら

Array
(
  [0] => Version: ImageMagick 6.0.7 04/20/08 Q16 http://www.imagemagick.org
  [1] => Copyright: Copyright (C) 1999-2004 ImageMagick Studio LLC
  [2] => 
)

とか表示されます。…が、ロリポップサーバーでは何も表示されませんでした…。

マニュアルを読むとImage::Magickは利用可らしいけど、PHPからはダメとかあるのかなぁ…。
色々調べてみると、ロリポップはサーバーによってはImage::Magickがインストールされていなかったりするらしいので、あまり頼りにはできないのかも。

PHPで自分自身のURLを取得

パスはサーバー変数から取得できるけど、URLは取得できるのか調べてみた。
どうやら以下のコードで大丈夫っぽい。

<?php

echo 'http://' . $_SERVER["SERVER_NAME"] . $_SERVER["SCRIPT_NAME"];

?>

PHPで添付ファイル付きメールを送信

PHPには mb_send_mail() という命令があり、これを使うと簡単に日本語メールを送信することができます。ただし添付ファイルには対応していないので、添付ファイルを扱う場合は利用できません。

大抵の解説では「mail() 関数を使ってメールヘッダを自力で書けば添付ファイルも送れますが、面倒なのでPEARなどを使いましょう。」とか書かれています。ですが例によってPEARは使いたくないので、自力でヘッダなどを書いてみた。

<?php

//マイムタイプ定義
$mime_content_types = array(
  'ez'      => 'application/andrew-inset',
  'atom'    => 'application/atom+xml',
  'atomcat' => 'application/atomcat+xml',
  ~略~
  'avi'     => 'video/x-msvideo',
  'movie'   => 'video/x-sgi-movie',
  'ice'     => 'x-conference/x-cooltalk'
);

//送信先メールアドレス
$to = 'example@example.com';

//送信元メールアドレス
$from = 'example@example.com';

//件名
$subject = '添付ファイルのテスト';

//メール本文
$message  = "テストメール。\n";
$message .= "添付ファイル送信のテストです。\n";

//添付ファイル
$files = array('images/test.gif');

//件名・本文をエンコード
$subject = mb_convert_encoding($subject, 'JIS', 'UTF-8');
$message = mb_convert_encoding($message, 'JIS', 'UTF-8');

$subject = '=?iso-2022-jp?B?' . base64_encode($subject) . '?=';

//バウンダリ文字列を定義
if (empty($files)) {
  $boundary = null;
} else {
  $boundary = md5(uniqid(rand(), true));
}

//メールボディを定義
if (empty($files)) {
  $body = $message;
} else {
  $body  = "--$boundary\n";
  $body .= "Content-Type: text/plain; charset=\"iso-2022-jp\"\n";
  $body .= "Content-Transfer-Encoding: 7bit\n";
  $body .= "\n";
  $body .= "$message\n";

  foreach($files as $file) {
    if (!file_exists($file)) {
      continue;
    }

    $info    = pathinfo($file);
    $content = $mime_content_types[$info['extension']];

    $filename = basename($file);

    $body .= "\n";
    $body .= "--$boundary\n";
    $body .= "Content-Type: $content; name=\"$filename\"\n";
    $body .= "Content-Disposition: attachment; filename=\"$filename\"\n";
    $body .= "Content-Transfer-Encoding: base64\n";
    $body .= "\n";
    $body .= chunk_split(base64_encode(file_get_contents($file))) . "\n";
  }

  $body .= '--' . $boundary . '--';
}

//メールヘッダを定義
$header  = "X-Mailer: PHP5\n";
$header .= "From: $from\n";
$header .= "MIME-Version: 1.0\n";
if (empty($files)) {
  $header .= "Content-Type: text/plain; charset=\"iso-2022-jp\"\n";
} else {
  $header .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
}
$header .= "Content-Transfer-Encoding: 7bit";

//メール送信
if (mail($to, $subject, $body, $header)) {
  echo 'メールが送信されました。';
} else {
  echo 'メールの送信に失敗しました。';
}

?>

プログラムはUTF-8で書くことを前提としています。

$mime_content_types の定義内容の全文はPHPでマイムタイプを自動判別に記載しています。添付ファイルのマイムタイプは常に application/octet-stream でも大丈夫っぽいですが、正しく定義した方が好ましいようです。

添付ファイルは $files に配列の形式でいくつでも設定できます。添付ファイルが無い場合、それにあわせてメールヘッダなどの内容も自動で変化します。

特に問題なく送信できましたが、書いたばかりなので近々じっくりテストしてみます。

PHPでマイムタイプを自動判別

PHPでファイルを読み込んで、そのまま出力するプログラムを書こうとしたのですが、マイムタイプの判別で躓いたのでメモ。

マイムタイプとはデータの形式を指定するためのもので、ブラウザにデータを渡す際に指定する必要があります。
具体的には、GIF画像なら

Content-Type: image/gif

Jpeg画像なら

Content-Type: image/jpeg

テキストなら

Content-Type: text/plain

などです。
今回はどんなファイルでも出力できるようにしたいのですが、マイムタイプは非常にたくさんあるので、上の内容を条件分岐させていくのは面倒です。

拡張子から簡単にマイムタイプを判別する方法は無いものか…と探していたら、以下の関数を発見。

mime_content_type

ファイル名を与えると、image/giftext/plain という値を返してくれるそうです。これは便利!と思ったら、この関数の利用は非推奨だそうです。実際、環境によっては利用できません…。

代わりにPECL拡張モジュールを使うといいらしいですが、やっぱり利用できない環境があります。PEARを使って判別することもできるらしいですが、できればPEARは使いたくないです。(freoではPEARを一切使わない方針なので。)

…という訳で、いい方法を見つけられなかったので「拡張子からマイムタイプを自動判別する」処理を自作してみた。結局ものすごく露骨な処理になりましたが、あらかじめ拡張子とマイムタイプを定義しておくだけです。

<?php

//マイムタイプ定義
$mime_content_types = array(
  'ez'      => 'application/andrew-inset',
  'atom'    => 'application/atom+xml',
  'atomcat' => 'application/atomcat+xml',
  ~略~
  'avi'     => 'video/x-msvideo',
  'movie'   => 'video/x-sgi-movie',
  'ice'     => 'x-conference/x-cooltalk'
);

//GIF画像ファイルのマイムタイプを出力
echo $mime_content_types['gif'];

//テキストファイルのマイムタイプを出力
echo $mime_content_types['txt'];

?>

マイムタイプ定義部分が長いので、あとで自分で流用しやすいように全文を置いておきます。関数にして使いまわせるようにするといいかも。突っ込み歓迎。

php_mime.txt

ちなみに、マイムタイプと拡張子は Apache 2.0 の conf/mime.types の内容を参考にしました。連想配列で定義しているだけなので、定義内容の編集は難しくないと思います。

ページ移動

ユーティリティ

カテゴリー

検索

エントリー検索フォーム
キーワード

過去ログ

過去ログ表示フォーム
キーワード

Feed