カテゴリの投稿: » PHP

PHPのvar_dump()の出力内容が省略されたら。。。

Written in 2018年04月27日 by | コメントする( 0件 )

PHPのvar_dump()で出力内容が省略されることがある。長ーいデータだったり、階層が深い配列だったり、要素数の多い配列だったり。省略されたくない場合は以下のように設定する。

ini_set('xdebug.var_display_max_children', -1);
ini_set('xdebug.var_display_max_data', -1);
ini_set('xdebug.var_display_max_depth', -1);

日本語ファイル名でファイルをダウンロードさせるには

Written in 2016年08月23日 by | コメントする( 0件 )

PHPで日本語ファイル名でファイルダウンロードさせようとすると、マルチバイトファイル名をそのまま渡すとIEでファイル名が文字化けしてしまう。

header("Content-disposition: attachment; filename=".$name);

一方、URLエンコードするとIEでは大丈夫となるが、FireFoxなどでURLエンコードされたままのファイル名でダウンロードとなる。

header("Content-disposition: attachment; filename=".rawurlencode($name));

以下のようにするのが正解。

header("Content-disposition: attachment; filename*=UTF-8’ja’".rawurlencode($name));

WINのIE、FF、Chrome、Opera
MACのSafari、Chrome、FF

でファイル名が文字化けせずにダウンロードできた。

  • カテゴリー:
  • PHP

phpMyAdmin4.0.xでカラムの多いテーブルのテーブル構造を開いた際に操作メニューサイズをリサイズするJavascriptのために、表示に時間がかかり操作ができない件の解消

Written in 2013年10月16日 by | コメントする( 0件 )

phpMyAdmin4.0.x (他のバージョンもそうかもしれないが)で、テーブル構造ページを開くと、各カラム情報行の右側にある各種操作メニューを、ブラウザの画面サイズに合わせてリサイズするJavascriptが動くが、これが結構遅くて、カラム数の多いテーブルの場合、画面を開いてから、操作できるようになるまでにかなりの時間がかかり、作業に支障をきたす。これを改善したい。

方法

js/tbl_structure.js

を開き、以下のコードを全箇所でコメントアウトする。(私の使っているバージョンでは3か所あった。)

$('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);

PMA_tbl_structure_menu_resizer_callback で検索すると全部見つかるでしょう。

これで画面を開いた際にメニューのリサイズ処理が走らなくなる。ただし、画面が狭いとメニューが折り返されて、幾分見づらい。。。

courier-imapの送信済みフォルダ名

Written in 2012年12月07日 by | コメントする( 0件 )

courier-imapでIMAPを通信をする際に、メーラ側から送信済みフォルダや、ごみ箱フォルダを作成・指定できますが、その際、フォルダ名に日本語を使うと、サーバ側のMaildir以下に作成されるフォルダ名は、文字化けしたような文字列になっている。これはフォルダ名が「UTF7-IMAP」にエンコードされているのだ。

「送信済み」というフォルダは、「&kAFP4W4IMH8-」みたいになっているでしょう。

それでこの文字化けしたような文字列をマルチバイトに戻したい時は、PHPでは以下のようにする。

$folder_name = mb_convert_encoding( $folder_name, 'UTF-8', 'UTF7-IMAP' );

ここではUTF-8に変換している。

WEBメールなどを作成される方はこのエンコード変換が必要でしょう。参考になれば幸いです。

10進数と62進数を相互変換するPHP関数

Written in 2012年06月18日 by | コメントする( 0件 )

62進数なんてどこかの古代文明かって感じですが、たとえばたくさんの数値をGETパラメータで渡したいが、クエリーの長さに制限のあるような環境の場合、数値を62進数にすれば桁数が減りますよね。そんなニーズで作ったものです。参考までにコード公開。

16進数は、0,1,2,3,・・・,8,9,A,B,C,D,E,Fで桁があがりますが、62進数は、0,1,2,3,・・・,8,9,a,b,c,・・・,x,y,z,A,B,C,・・・,X,Y,Zまできて桁があがります。数値、小文字、大文字という順ですね。数字が10文字、小文字が26文字、大文字が26文字なので合計で62あるのだ。

<?php

// 62進数を10進数に変換
function dec62to10( $dec62 )
{
  $dec62 = trim( $dec62 );
  if ( !preg_match( '/^[0-9a-zA-Z]*$/', $dec62 ) ) {
    trigger_error( "62進数を指定してください。", E_USER_ERROR );
  }
  if ( !$dec62 ) {
    return 0;
  }
  $digits = strlen( $dec62 );
  $lower_a = unpack( 'C', 'a' );
  $upper_a = unpack( 'C', 'A' );
  $dec10 = 0;
  $code = unpack( 'C', $dec62 );
  for ( $i=1; $i<=$digits; $i++ ) {
    $char = substr( $dec62, $i-1, 1 );
    if ( preg_match( '/[a-z]/', $char ) ) {
      $num = 10 + $code[ $i ] - $lower_a[1];
    } elseif ( preg_match( '/[A-Z]/', $char ) ) {
      $num = 36 + $code[ $i ] - $upper_a[1];
    } else {
      $num = $char;
    }
    $dec10 += pow( 62, $digits - $i ) * $num;
  }
  return $dec10;
}

// 10進数を62進数に変換
function dec10to62( $dec10 )
{
  $dec10 = trim( $dec10 );
  if ( !preg_match( '/^\d*$/', $dec10 ) ) {
    trigger_error( "10進数を指定してください。", E_USER_ERROR );
  }
  if ( !$dec10 ) {
    return 0;
  }
  $lower_a = unpack( 'C', 'a' );
  $upper_a = unpack( 'C', 'A' );
  $digits = 0;
  do {
    $digits++;
  } while ( $dec10 / pow( 62, $digits - 1 ) >= 1 );
  $digits--;
  $dec10_tmp = $dec10;
  $dec62 = '';
  for ( $i=1; $i<=$digits; $i++ ) {
    $digit_num = floor( $dec10_tmp / pow( 62, $digits - $i ) );
    if ( $digit_num < 10 ) {
      $dec62 .= $digit_num;
    } elseif ( $digit_num < 36 ) {
      $dec62 .= pack( 'C', $digit_num - 10 + $lower_a[1] );
    } else {
      $dec62 .= pack( 'C', $digit_num - 36 + $upper_a[1] );
    }
    $dec10_tmp -= $digit_num * pow( 62, $digits - $i );
  }
  return $dec62;
}

?>

mPDF5.xでTTFフォント使用時に一部の文字が四角で出力

Written in 2012年04月23日 by | コメントする( 2件 )

mPDF5.4を使って、PDFのレポートを出力していたが、TTFフォントで日本語を出す際に一部の文字が四角の形で出力されてしまう原因不明の不具合がでた。フォントのサブセットを埋め込む際の問題らしいが、散々検証してようやく解決できた。。。結構みんな困ってるんじゃなかろうか。。。

その四角をコピーして、秀丸とかに貼ると、復元される。間違いなく、文字コードの埋め込みではなく、フォント自体の埋め込みの問題です。

これはTTFフォントのサブセットをPDFに埋め込む際に、
Supplemental Ideographic Plane (SIP i.e. U+20000 to U+2FFFF)を扱うメソッドの方が動作してしまうかららしい。

http://mpdf.bpm1.com/forum/comments.php?DiscussionID=470&page=1#Item_11

が参考となりました。

mPDFがフォントのサブセットを埋め込む際に、そのフォントファイルを調べ、そのフォントにSIP(またはSMP U+10000+1FFFF)が含まれている場合、問題の原因となっているその第二のメソッドが使われるのである。それはドキュメント内でそれらの文字が使われているか否かに関わりません。(mPDFが水面下で融通をきかせてしまうのです。) しかしながら、該当フォントをconfig_fonts.phpの$this->BMPonly配列にくわえることによって、この挙動を上書きできます。こうすることでmPDFに第一のメソッドを使うように強制することができます。ただし、SIPの文字は表示されなくなります。

この設定をするとUnicode Basic Multilingual Plane (BMP i.e. U+0000 to U+FFFF)内の文字だけが利用可能な状態となります。

/mpdf54/config_fonts.phpの307行の
$this->BMPonly に、使用したいフォント名を追加してやる。(”mspgothic”など。)

例)

$this->BMPonly = array(
    "mspgothic",
    "msgothic",
    "mspmincho",
    "msmincho",
    "ipagothicp",
    "ipagothic",
    "ipaminchop",
    "ipamincho",
    "dejavusanscondensed",
    "dejavusans",
    "dejavuserifcondensed",
    "dejavuserif",
    "dejavusansmono",
);

64bitのLinuxサーバにPHPを./configureする際にlibjpeg, libpng, ldapなどがない!と怒られる

Written in 2011年05月20日 by | コメントする( 0件 )

64ビットのLinuxサーバにPHPをソースインストールで./configureする際に、予期せず以下のようなエラーに遭遇したことはないだろうか。

configure: error: libjpeg.(a|so) not found. php 5.2.17

configure: error: libpng.(a|so) not found. php 5.2.17

単にlibjpeg-devel, libpng-develがインストールされていないなら、

yum install libjpeg-devel

yum install libpng-devel

でインストールすればいい。しかし、これはもうやったのに、上記エラーが出る場合、32bit(i386)のライブラリがインストールされていない可能性がある。

# ls -la /usr/lib | grep libjpeg
lrwxrwxrwx   1 root root      17  5月 20 15:58 libjpeg.so -> libjpeg.so.62.0.0
lrwxrwxrwx   1 root root      17  5月 20 15:58 libjpeg.so.62 -> libjpeg.so.62.0.0
-rwxr-xr-x   1 root root  134268  1月  6  2007 libjpeg.so.62.0.0

のように、/usr/lib の中に、ライブラリが入っているか確認するといい。もしかしてなかったりしませんか? 次に64ビット用ライブラリも確認してみよう。

# ls -la /usr/lib64 | grep libjpeg
lrwxrwxrwx  1 root root      17  5月 20 15:17 libjpeg.so -> libjpeg.so.62.0.0
lrwxrwxrwx  1 root root      17  7月  2  2010 libjpeg.so.62 -> libjpeg.so.62.0.0
-rwxr-xr-x  1 root root  138936  1月  6  2007 libjpeg.so.62.0.0

こちらは有ったりしませんか?
なんだ、64bitのしかないなら、

./configure –with-libdir=lib64

のように指定すればいいではないか。でもやってみると、今度は、mysql_clientがないとか言われたりする。今度は32ビット版のライブラリしかないものが見つからなくなってしまう。。。困ったもんだ。

もし、yumでインストールしたlibjpegやlibpngのライブラリが64ビット版はあり、32ビット版がないという状況の場合、yumでi386のパッケージを除外する設定がされている可能性があります。普通、libjpeg, libpngは、yumインストールすると32ビット版、64ビット版の両方がインストールされるはずだからです。以下のように確認してみよう。

# cat /etc/yum.conf

設定の中に、

exclude=*.i386

のような記述があればコメントアウトする必要がある。これでyum install libjpeg-develで、32ビット版のライブラリもインストールされるはずだ。

/etc/yum.repos.d/

の中にあるファイルに関しても確認してみル必要があるかもしれない。

 

Apache2.2+PHP5.3+MySQL5.5環境でApacheが立ち上がらない

Written in 2011年03月23日 by | コメントする( 0件 )

最近、Apache2.2+PHP5.3+MySQL5.5の構築をしました。何度もしていたので甘く見てたら、Apache起動でOKと表示されるものの実際には立ち上がっておらず、ログにもエラーが出ていなかったので、とても困りました。

おそらくopensslの複数バージョンの混在が原因ではないかと思います。RPM版のopenssl0.9.8eが入っており、別途ソースインストールで、/usr/local/openssl にopenssl1.0.0cを入れていました。

MySQL5.5では、コンパイル時にCmakeを使うようになり、設定方法が以前と変わっており、opensslのインストールPREFIXを指定できずに(方法があるのかもしれませんが、、、)、デフォルトのディレクトリ/usr からライブラリを組み込むようで、RPM版のopenssl0.9.8eが組み込まれました。

一方、PHPではopensslのインストールディレクトリを指定できるので、/usr/local/openssl のopenssl1.0.0cを組み込もうとしたところ、MySQL5.5からクライアントライブラリを組み込む指定もしていたので、MySQL5.5のopenssl0.9.8eとPHP5.3のopenssl1.0.0cがコンフリクトして「セグメンテーション違反」となって、コンパイルできなかった。

なので、opensslは複数バージョンのDSOモジュールがあると競合するようだ。仕方なく、PHPには、/usrのパスを指定してopenssl0.9.8eを組み込んだ。

さて、Apache2.2には、opensslのパス指定ができるので、/usr/local/openssl のopenssl1.0.0cを組み込んでいました。このアパッチにlibphp5.soを読み込ませるわけだが、そうするとApache2.2のopenssl1.0.0cと、PHP5.3およびMySQL5.5に組み込まれたopenssl0.9.8eがコンフリクトするのではなかろうか。PHPコンパイル時のPHP x MySQLのコンフリクトのようにエラーが出ればいいが、Apache起動時にエラーも吐かずに立ち上がらないという状況はいかにも困った。

これらのopensslコンフリクトの仮説をもとに、Apache2.2もopenssl0.9.8eを組み込んでコンパイルし直し、PHP5.3も同様にコンパイルしなおしたところ、動きました。。。。

OpenPNEのインストールにはpdo_mysqlが必要

Written in 2010年05月14日 by | コメントする( 0件 )

OpenPNEのインストールで、

./symfony openpne:install

を実行した際に、

Couldn’t locate driver named mysql

と怒られたなら、それはPHPにpdo_mysqlエクステンションが入っていないから。ソースディレクトリからエクステンションをコンパイルする。

cd /usr/local/src/php/php-5.2.5/ext/pdo_mysql/
phpize
./configure –with-php-config=/usr/local/php5/bin/php-config \
–with-pdo-mysql=/usr/local/mysql5.0
make
make install

でインストールし、php.iniに、

extension=pdo_mysql.so

を加えてApacheリスタート。
起動OKと出て、安心できない。ブラウザでPHPのページをみると閲覧できない。Apacheが起動していない。。。

php -i

で、確認しようとすると、

php: symbol lookup error: /usr/local/php5/lib/php/20060613/pdo_mysql.so:
undefined symbol: php_pdo_declare_long_constant

とでる。これは、/usr/local/php5/include/php/ext/pdo/php_pdo_driver.hのバージョンがよろしくないようだ。PHPをソースインストールした際のソースディレクトリからコピーしてやる。

cp /usr/local/src/php/php-5.2.5/ext/pdo/php_pdo_driver.h \
/usr/local/php5/include/php/ext/pdo/php_pdo_driver.h

いったんpdo_mysqlをアンインストールする。

rm -f /usr/local/php5/lib/php/20060613/pdo_mysql.so

上記、ソースから再度インストール。make cleanしてからね。これでApache再起動でいけました。OpnePNEもインストール完了。

  • カテゴリー:
  • PHP

preg_matchのサブキャッチパターンの文字数が多いと落ちます!!

Written in 2010年05月03日 by | コメントする( 0件 )

PHPのpreg_matchにおいて、カッコを使って、サブキャッチパターンを作ることがあるだろう。ただ、そのサブキャッチパターンにマッチする文字数(バイト数)が10万文字(バイト)を超えると、エラーも発生させず、ただ単に、「マッチせずに」終了となる。(PHP5.2.5にて検証) 以下にサンプルコードを示す。

<?php
for ( $i=1; $i<=1000000000; $i++ ) {
  $src .= '1234567890';
  if ( !preg_match( '/<(.+?)>/', '<'.$src.'>', $matches ) ) {
    echo "not match at ".$i;
    break;
  }
}
?>

上記コードでは、決して「not match at ???」とは表示されることはないように思われるだろう。しかし実際はそうではない。実行してしばらく待つと以下の結果が出る。

not match at 10000

(.+?)というサブキャッチパターンにマッチする文字列が、10000×10文字=10万文字になった時点で、マッチしなくなり、echoして、breakしていることが分かるはずだ。ちなみに、以下のコードでは、どうだろう。

<?php
for ( $i=1; $i<=1000000000; $i++ ) {
  $src .= '1234567890';
  $src2 .= '1234567890';
  if ( !preg_match( '/<(.+?)><(.+?)>/', '<'.$src.'><'.$src2.'>', $matches ) ) {
    echo "not match at ".$i;
    break;
  }
}
?>

上記の場合、以下のような結果となる。

not match at 5000

おわかりだろう。やはり10万文字だ。(5000×10文字)+(5000×10文字)=10万文字なのである。

そんな長い文字をサブキャッチなんかしないといわれるかもしれない。しかし、私がこれに気付いたのは、XML-RPCのリクエストのパースを実装していた時だ。XML-RPCで、データを登録するリクエストにおいて、<base64></base64>タグで、画像データを受け取った際に、preg_matchのサブキャッチパターンで中身を取得したのだ。結果、大きな画像を受け取ったときに、マッチしないという事態に陥ったのだ。

たちが悪いのは、エラーをはいてプログラムが停止するのではなく、単にマッチしなくなって次の処理に進んでしまうことだ。ぜひ、気をつけていただきたい。

  • カテゴリー:
  • PHP