カテゴリー
Database PHP

CPI レンタルサーバーでPHP/MySql UTF-8 文字化け

先日から使用しているCPIレンタルサーバーへシステムを構築しているのですが、PHP でデータベースへ文字を登録すると文字化けしてしまうようです。

CPIレンタルサーバーのコントロールパネルからデータベースを新規作成する際に文字コードをUTF-8を指定したし、CREATE TABLE も UTF-8 を指定してあり、また PHP も mb_internal_encoding もファイルのエンコーディングも UTF-8 を指定していて、ローカルサーバーではきちんと動作しているシステムなので問題ないはずなのですが。

コントロールパネルのMySQL5.5管理画面より変数をしらべると character set 関連が ujis となっていました。

character set server: ujis
character set system: utf8
character set database: ujis
character set client: ujis

ではこれを編集して utf8 にすれば良いのだろうと思い、編集し保存すると権限がないてめ拒否されてしまった。

そこで、PHP/PDO からデータベースへ接続するときに charset=utf8 をつけてみると読み出し、登録も文字化けすることなく解決にいたりました。

https://php.net/manual/ja/ref.pdo-mysql.connection.php
https://php.net/manual/ja/mysqlinfo.concepts.charset.php

カテゴリー
Database PHP Web

CPI レンタルサーバーでPHP/PDO MySql接続エラー

CPIレンタルサーバーにWebシステムを構築していてはまってしまった件なのですが、PHP で PDO を使って MySql へ接続すると以下のエラーが。。。

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

ローカルのサーバーでは出ていなかったので、Unixソケットも調べたが /tmp/mysql.sock で問題なし。

原因は、host=localhost で接続していたためでした。’localhost’ を ‘127.0.0.1’ に変更したら接続ができました。

カテゴリー
PHP

PHP fputcsvで出力するとダブルクォーテーションで括られる

PHP のfputcsvは配列データをCSVファイルへ出力する際に自動でエスケープ処理もしてくれるので便利ですが、エンコーディングを UTF-8 から Shift-JIS へ変換して出力すると、文字列が予期せずダブルクォーテーションで括られる場合があります。

<?php
function convertEnc($arg) {
    if (is_array($arg)) {
        return array_map('convertEnc', $arg);
    } else {
        return mb_convert_encoding($arg, "SJIS-win", "UTF-8");
    }
}

$array = array(
              "あ"
             ," "
             ,"\r\n"
             ,"ソ"
             ,"十"
);
$fp = fopen("php://stdout", "w");

// UTF-8 のまま出力
fputcsv($fp, $array);

// Shift-JIS に変換して出力
//fputcsv($fp, convertEnc($array));

fclose($fp);
?>

// UTF-8 出力結果
UTF-8 のままで出力すると改行コードだけがダブルクォーテーションで囲まれます。

あ," ","
",ソ,十

// Shift-JIS 出力結果
Shift-JIS へ出力すると「ソ」、「十」もダブルクォーテーションで囲まれてしまいます。

あ," ","
","ソ","十"

「ソ」、「十」は Shift-JIS では、れぞれ「0x8F5C」、「0x835C」で 0x5C はバックスラッシュ、バックスラッシュはエスケープ文字扱いなのでダブルクォーテーションで囲まれるようです。

参考:
https://github.com/php/php-src/blob/master/ext/standard/file.c

		/* enclose a field that contains a delimiter, an enclosure character, or a newline */
		if (FPUTCSV_FLD_CHK(delimiter) ||
			FPUTCSV_FLD_CHK(enclosure) ||
			FPUTCSV_FLD_CHK(escape_char) ||
			FPUTCSV_FLD_CHK('\n') ||
			FPUTCSV_FLD_CHK('\r') ||
			FPUTCSV_FLD_CHK('\t') ||
			FPUTCSV_FLD_CHK(' ')
		) {
カテゴリー
PHP

PHP fputcsvの改行コードをCRLFで出力

PHP のfputcsv関数で出力した CSV ファイルの各行の改行コードは LF なんですね。
記憶の片隅に残しておかないと、改行コードに CRLF を期待しているシステムで読み込めませんなんてことになってしまいます。 😉

改行に CRLF を出力する方法は、いろいろあると思いますが、php_user_filter を使った方法がスマートに思えます。
フィルタをつくって、stream_filter_register で登録、開いたストリームに stream_filter_append で追加すると、読み込みまたは書き込み時にフィルタが適用されます。

// filter class that applies CRLF line endings
class crlf_filter extends php_user_filter
{
    function filter($in, $out, &$consumed, $closing)
    {
        while ($bucket = stream_bucket_make_writeable($in)) {
            // make sure the line endings aren't already CRLF
            $bucket->data = preg_replace("/(?data);
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}

// フィルタの登録
stream_filter_register('crlf', 'crlf_filter');

// 出力ファイルのオープン
$fp = fopen($foldername."/".$filename, 'w');

// 出力ファイルへフィルタをアタァッチ
stream_filter_append($fp, 'crlf');

while(繰り返す) {
    $output = array();
... 省略 ...
    // 出力
    fputcsv($fp, $output);
}

// 出力ファイルのクローズ
fclose($fp);

参考:
stream_filter_register
https://stackoverflow.com/questions/12722894/how-can-i-change-the-line-endings-used-by-fputcsv

カテゴリー
PHP

PHP スクリプト実行PCのIPアドレス取得

PHP スクリプト実行PCのIPアドレス取得方法、再考しました。

<?php
echo GetIpAddr();

/*
  GetIpAddr
*/
function GetIpAddr()
{
    preg_match_all('/inet addr: ?([^ ]+)/', `ifconfig`, $ipaddr);
//  var_dump($ipaddr);
    return $ipaddr[1][0];
}
?>

出力結果:

192.168.1.3

CentOS 6.6 と Ubuntu14.04LTS で動作確認済み。
CentOS 7 は期待通り動作しません。