カテゴリー: PHP

PDOでmysqlに接続する時の文字コード

久しぶりにメモ。

開発環境でPDOからmysqlにつないでデータを入れたりしてたのに
本番サーバに設置した途端にプログラムから入れたデータが文字化けした。

mysql> show variables like 'character_set%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       | 
| character_set_connection | utf8                       | 
| character_set_database   | utf8                       | 
| character_set_filesystem | binary                     | 
| character_set_results    | utf8                       | 
| character_set_server     | utf8                       | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+
8 rows in set (0.01 sec)

dbにつないで文字コードの設定をみてみたけど問題なかったので変だなーと。

で、以下のプログラムで確認。

$PDO=NULL;
try {
    $PDO=new PDO(
        sprintf('mysql:host=%s;dbname=%s','localhost','dbname'),'user','password',
        array(
            PDO::MYSQL_ATTR_READ_DEFAULT_FILE=>'/etc/my.cnf',
            PDO::MYSQL_ATTR_READ_DEFAULT_GROUP=>'client',
            PDO::ATTR_EMULATE_PREPARES=>'FALSE'));
    $PDO->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
} catch(PDOException $e) {
    var_dump($e->getMessage());
}

//$PDO->query("SET NAMES utf8");


$sth=$PDO->prepare("SHOW VARIABLES LIKE 'char%'");
$sth->execute();
while($ins=$sth->fetchObject()){
    echo $ins->Variable_name . " | " . $ins->Value . "\n";
}

開発環境での結果…

$ php connect_test.php
character_set_client | utf8
character_set_connection | utf8
character_set_database | utf8
character_set_filesystem | binary
character_set_results | utf8
character_set_server | utf8
character_set_system | utf8
character_sets_dir | /usr/share/mysql/charsets/

本番環境の結果…

$ php connect_test.php
character_set_client | latin1
character_set_connection | latin1
character_set_database | utf8
character_set_filesystem | binary
character_set_results | latin1
character_set_server | utf8
character_set_system | utf8

コレですね…

どうも開発環境では/etc/my.cnfに[client]に文字コードの
指定があったから上手くいってたけど、本番環境では
/etc/my.cnfに文字コードの設定がちゃんとされていないのが問題
だったみたい。

今回の本番環境は/etc/my.cnfを勝手に触れないので

$PDO->query("SET NAMES utf8");

で対応する。。

いろんな環境で動かすならSET NAMESはちゃんと書いておいたほうが良さそうですね。

PHP Google Analyticsのデータを扱う GAPI Version 1.3

Google Analyticsのデータを取得してウニャウニャする必要が
あったのでデータの取得方法から調べてみた。
(昔APIができたとかいう時にちょっと触ったけど完全に覚えていないのでやり直し。。)

とりあえず今回取得したいデータはgoogle analyticsを仕込んであるサイトの指定期間内の
コンテンツ単位のページビューランキング※ただし特定の形式のURLのみのランキング
まずはgoogle analyticsのサイトで調べる。
使うのはこれ。

Data Export API

Google Analytics Data Export API を使用すると、クライアント
アプリケーションを作成して、許可したユーザーの既存のアナリティクス
プロファイルからのデータをリクエストしたり、クエリ
パラメータを使用してリクエストの結果を絞り込むことができます。
現在、Data Export API は Google アナリティクス データへの読み取り専用
アクセスをサポートしています。

とりあえずスタートガイドを読んでおく。

もっと読む PHP Google Analyticsのデータを扱う GAPI Version 1.3

PHP (int)の挙動

今日(int)でキャストしてる時に挙動が気持ち悪かったのでメモ。

echo (int)"3abc";    //3 と出力される
echo (int)"test";    //0 と出力される
echo (int)"01abc";   //1 と出力される
echo (int)"   01gd"; //1 と出力される

PHPの文字列比較で気をつけるべきこと暗黙の型
こちらのサイトに同じ挙動が書かれてました。(上のサンプルは引用)

で、

C言語のstrtodという関数の挙動だそうです

ここが多少きになりました。

[ソフトウェア]PHP の言語仕様は、ランタイムのコンパイル環境に依存します。
こっちに関連する事が書かれてます。

 

PHP smartyで変数の修飾子を使う

仕様変更でやむなくsmarty内でpreg_replace的なことをしないと
いけなくなったけどやり方を知らなかったのでググッた結果。

Smarty内でPHP関数を使う

Chapter 5. 変数の修飾子

上記を参考にして書いたのがこちら↓

{if strpos($item, '-new') !== false }
    {assign var="new_flag" value="1"}
    {assign var="item" value=$item|regex_replace:"/-new/":""}
{else}
    {assign var="new_flag" value="0"}
{/if}

strpos — 文字列が最初に現れる場所を見つける

上記を利用して$itemに’-new’という文字列が含まれていなかったらifへ、あったらelseへ。
‘-new’が含まれている場合は以下で’-new’を取り除き再び$itemに値を入れ直す。

{assign var="item" value=$item|regex_replace:"/-new/":""}

regex_replaceこちらを参照。

今日はこの位で。

PHP:array_intersect 配列の共通項を計算する

毎回思い出せなくなる関数。

array_intersect

2つの配列の共通項を取り出すことができる。

別の言い方をすると2つの配列の重複箇所を取り出すことができる関数。

intersectはこいう意味

intersect
【名】
交差、横断
【自他動】
交差する、交わる、横切る、横断する

マニュアルに記載されている例はこれ

<?php
$array1 = array("a" => "green", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_intersect($array1, $array2);
print_r($result);
?>

実行結果

Array
(
    [a] => green
    [0] => red
)

注意: 二つの要素は、 (string) $elem1 === (string) $elem2 の場合のみ等しいとみなされます。言い換えると、文字列表現が同じ場合となります。

上記のような簡単な例だけでなく、入れ子になった配列でも使う事ができる。
※注意にもあるように文字列表現が同じ事が前提。

大文字・小文字は区別されます。

その他intersect関係

array_intersect_assoc
追加された添字の確認も含めて配列の共通項を確認する

array_intersect_key
キーを基準にして配列の共通項を計算する

array_intersect_uassoc
追加された添字の確認も含め、コールバック関数を用いて 配列の共通項を確認する

array_intersect_ukey
キーを基準にし、コールバック関数を用いて 配列の共通項を計算する

PHP5 fgetcsv 日本語文字が消える場合

2019/1/16 追記 現在は以下の記事を参照してください。

PHP「fgetcsvはsetlocaleしないと日本語が読めない」は迷信なのか?


PHP5 で fgetcsvを使ってマルチバイト文字列を読込む際に
日本語が消える、もしくは一部消える現象が起きるのでその対策。

fgetcsvの使い方はここに書いてあります。

fgetcsv — ファイルポインタから行を取得し、CSVフィールドを処理する

注意点

この関数はロケール設定を考慮します。もし LANG が例えば en_US.UTF-8 の場合、 ファイル中
の 1 バイトエンコーディングは間違って読み込まれます。

wonder on server sideにも書いてます。
csvファイルを読み込む

もっと読む PHP5 fgetcsv 日本語文字が消える場合

GDとImageMagickでリサイズ時の画質の比較

CodeIgniter1.7.3の画像操作クラス「image_lib」でgd2を使って画像をリサイズしてましたが、
なんか元画像と較べると色が少し変と言われてので調査。

qualityを100にしても少し色が違うと・・・。

少し調べると以下のようなサイトが・・・。

GDとImageMagickの画質比較(Asial blog)
GDとImageMagick比較(プログラミングを始める10の理由)

ImageMagickのほうが画質はいいんですね。

で、image_libではGD/GD2、NetPBM、および ImageMagickに対応しているようなので
ImageMagickに変更してみた。

※以下メモ。処理は少し省いています。ファイルアップロード部分とか。

$data = $this->CI->upload->data();

$this->CI->load->library('image_lib');
$config = array();
$config['image_library'] = 'imagemagick';
$config['library_path'] = '/usr/local/bin/convert';
$config['source_image'] = $data['full_path'];
$config['maintain_ratio'] = TRUE;
$config['quality'] = 100;
$config['master_dim'] = 'auto';
$config['new_image'] = $data['file_path'] . $data['raw_name'] . "-" . $size . $data['file_ext'];

$setting = $this->CI->config->item('resize');

if($data['image_width'] >= $data['image_height']) {
    $config['width'] = 400;
    $config['height'] = 240;
} else {
    $config['width'] = 240;
    $config['height'] = 400;
}

$this->CI->image_lib->initialize($config);
$this->CI->image_lib->resize();
$this->CI->image_lib->clear();

だいたい上記の用な感じでリサイズしたら元画像と比較しても遜色の無い
綺麗な画像ができました。

※ちなみに上がgd2下がimagemagickです。

わかりずらいけどimagemagickのほうが背景色がより白く元画像に近い。。

ブログだとおなじみ見えるかも。。

CodeIgniter xss_cleanの謎

ぺらたんからのタレコミ。

CodeIgniterの1.7.3や2系でxss_cleanの挙動が不思議らしい。

例えば「EPA&DHA」の文字列をxss_cleanにかけると「EPA&DHA;」となるらしい。

xss_cleanの該当箇所を抜き出して試してみた。

<?php
$str = 'EPA&DHA';

$hash = '901119URL5918AMP18930PROTECT8198';

$str = preg_replace('|\&([a-z\_0-9]+)\=([a-z\_0-9]+)|i', $hash."\\1=\\2", $str);
echo $str . "\n";

$str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str);
echo $str . "\n";

$str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$str);
echo $str . "\n";

$str = str_replace($hash, '&', $str);
echo $str . "\n";

$str = rawurldecode($str);
echo $str . "\n";

実行結果

$ php ci_xss_test.php
EPA&DHA
EPA&DHA;
EPA&DHA;
EPA&DHA;
EPA&DHA;
$str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str);

ここが原因みたい。
&のあと2文字以上なら「;」挿し込む?
ちょっと意味が分かっていない・・・。

そもそもxss対策を全部自前でやってるのはどうなのかな?

ちょっとぐぐってみたら

CodeIgniterのGlobal XSS Filteringには要注意?

CodeIgniter XSS対策

とか出てきた。

あんまり使わないほうがいいのかなー。