Monthly Archives: 2月 2019

EC-CUBE 2系でポート番号付で管理画面を動かす

Apacheの処理分散させるために、ロードバランサーを介してラウンドロビンを掛けた複数台で同じEC-CUBEを動かす必要が出てきました。
Apacheを動作させるフロントエンドをコピーした複数台でPHP処理を分担、MySQLはローカル接続されているバックエンドの専用サーバーで運用という形です。

EC-CUBEはそもそもPHPセッションをDB保存しているので、DBをバックエンドのサーバーで共通化しておけば複数台でのPHPセッションの共有化を配慮する必要はなく、複数台運用への切り替えは簡単です。

ただし、管理画面からアップロードした画像等はApacheを動かしているサーバーに物理的に保存されるため、ラウンドロビンが掛かった状態ではどのサーバーにファイル保存されるか分からなくバラバラになってしまうため、どれか1台固定のサーバーを正としてそこへ保存し、rsync等で各サーバーへコピーしなくてはなりません。

サブドメインではっきり分けれれば良いのですが、ドメイン追加をできない場合は1443などの独自のポート番号でポートフォワードで振り分けて管理画面を動かすサーバーを固定したいところ。

ただし、普通にポート番号付きでアクセスしてしまうと、管理画面でログインした直後にリダイレクトエラーが出ます。
これは/data/config/config.php で設定している HTTP_URL や HTTPS_URL と異なるURLへジャンプすることを防ぐセキュリティ対策の影響です。
では、そもそもHTTP_URL に:1443付きで定義したらどうかとなりますが、そうすると今後はポート番号無しでアクセスしているカート画面などでリダイレクトエラーが出ます。訪問者画面も管理画面も同じEC-CUBEだと設定も共通なので。

そこで、ポート番号付きでアクセスしたときだけこのURLを書き換えてしまうと良いです。
具体的には /data/config/config.php をこんな風に書きます。常時SSLのご時勢ですからHTTP_URLは振り分けなくても良いかな?

define('HTTP_URL', 'http://www.exsample.co.jp/');
if ($_SERVER['SERVER_PORT'] == '1443') {
  define('HTTPS_URL', 'https://www.exsample.co.jp:1443/');
} else {
  define('HTTPS_URL', 'https://www.exsample.co.jp/');
}

PHP5.6でEUC-JPやShift_JISのサイトを動かす

今さら何でPHP5.6なのかと悲しくなりますが、サーバー変更するときにPEARを使っていたりmysql_connect等のPHP7で廃止された関数を大量に使用しているサイトだったので、修正予算が無い関係でどうしてもPHP5系を選ばないといけませんでした。

しかもMySQLデータもPHPソースもHTMLも、全てEUC-JPで書かれているというサイトです。

せめてものあがきで最新である5.6を選択するわけですが、PHP5.6はデフォルトの言語がUTF-8になっているため、UTF-8で構築する分には何も考えなくて良いのですが、EUC-JPやShift_JISで書かれたサイトを設置すると文字化けにハマります。
今回、試行錯誤で時間が掛かったので、その解決策をメモしておきます。

通常はPHPソースもHTMLもUTF-8で掛かれている前提でphp.iniは、こう設定されていると思います。

; mbstring.language = Japanese
; mbstring.detect_order = 
; mbstring.encoding_translation = Off
; mbstring.func_overload = 0
; mbstring.http_input = 
; mbstring.http_output = 
; mbstring.internal_encoding = 
; mbstring.strict_detection = Off
; mbstring.substitute_character = 
default_language = UTF-8

今回、他のバーチャルドメインも乗せているレンタルサーバーでphp.iniは変更できない状況だったので、php.iniはUTF-8の設定のままでプログラム側で対処します。

共通設定処理など、サイト全体の最初に処理されるPHPソースに以下の文を書き足します。

ini_set('input_encording', 'EUC-JP');
ini_set('internal_encoding', 'EUC-JP');
header('Content-Type: text/html; charset=EUC-JP');

mb_~関数では無いのが重要。
mb_http_inputやmb_internal_encodingでEUC-JPを指定した場合、表示はうまく出来てもフォームのPOST値がコード変換がされず文字化けしたり$_POSTで受け取れなかったり、htmlspecialchars が文字コードを誤認したりしました。
PHP5.6ではmb_internal_encoding等が非推奨になっているのはこの辺りの問題もあるからなのかも?

そこでPHP5.6で新設された input_encoding や internal_encoding で指定します。
→ mbstring.http_input mbstring.http_output mbstring.internal_encoding も一緒に設定した方が良さそう。

また default_language = UTF-8 がデフォルトになっていて Content-type: text/html; charset=UTF-8 というヘッダーが吐かれてしまうので、header関数でEUC-JPに上書きします。

Smarty3をもし使っているなら、define(“SMARTY_RESOURCE_CHAR_SET”, “EUC-JP”); も定義しましょう。この定数が定義されていないとSmartyが勝手に mb_internal_encoding を UTF-8 か ASCII に上書き設定してしまいます。

MySQLデータベースは5系以降は内部コードがUTF-8で処理されますので、EUC-JPでdumpしてきたデータはエディタ等でUTF-8にコード変換して、UTF-8でデータベースに流し込み通信段階でクライアント側の文字コードに変換させるのが吉。

PHPプログラムからは、connectしたあとにeucでデータを読み書きできるように文字コード設定しておけばOK

$con = mysql_connect($host, $user, $pass); 
mysql_set_charset('eucjpms', $con);

PotgreSQLデータベースだった場合も内部コードがUTF-8で処理されますので、EUC-JPでdumpしてきたデータもそのまま createdb したデータベースに psql で流し込めばUTF-8で格納されるので、あとは通信段階でクライアント側の文字コードに変換させるのが吉。/var/lib/pgsql/data/postgresql.conf に client_encoding = “EUC-JP” を書いちゃうのが楽

もう試行錯誤しないで済みますように。