カテゴリー別アーカイブ: PHP

ブログ等にソースコードを入力するためにHTML特殊文字を変換してみる – PHP 開発 サンプル

 ブログ等にソースコードやHTMLタグを表示させようとして入れても、HTML特殊文字が評価されてしまって表示が崩れてしまったりする時、対応するために特殊文字をエンコードする必要が出る。
 VPSを持っているなら、簡単なPHPスクリプトを作れば実現できる
実行してみる on さくらのVPS

$code = htmlspecialchars(htmlspecialchars($sourcecode));
echo("<textarea cols=’80’ rows=’40’>{$code}</textarea>");

PHPが提供するhtmlspecialcharsをかけるだけでOK。
1回かけると画面に通常表示なので、2回かけて特殊文字変換された状態の物を表示させる。

(253)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP], PHP | コメントをどうぞ

MySQL接続にSSLを使用する – PHP MySQL SSL WordPress MYSQL_CLIENT_SSL 暗号化

 MySQLの接続にSSLを使う話。

 このブログはWordpressとMySQLが別のサーバで動いている(WindowsServer2003R2化したさくらのVPS上にMySQLサーバを設置して、Apache+PHPを設置したLinux状態のさくらVPSからmysqlコネクタを経由して接続している)
mysql接続は通常は平文なので、ネットワーク上で色々な情報がだらだら流れてしまうのは嫌なので、このコネクションをSSLで暗号化する。

 まず、WindowsServer2003R2上に設置したMySQLサーバにSSL設定を行う。
 MySQL5.5サーバのWindowsバイナリにはSSL機能が含まれているから、特別なプログラムを追加する必要はないけど、Windows上のSSL管理は複雑だ。
 MySQLサーバでは秘密鍵は暗号化されていないファイルでなければならないのだけど、Windowsではそもそも証明書ストアの内部に格納されているので、これを取り出さなければならないんだけど、その操作が証明書の取得と前後する(普通は秘密鍵をベースとして証明書の管理をするんだけど、Windowsでは証明書を取得しないと秘密鍵か取り出せない)
 まず、WindowsのIISマネージャを起動して、ナビゲーションからサーバ>Webサイト>既定のWebサイトを選択して、プロパティを開いて、「ディレクトリセキュリティ」タブにある「セキュリティで保護された通信」の「サーバー証明書」を叩いて「IIS証明書ウィザード」から、「証明書の要求を作成して後で送信する」処理でCSRを作成する(WindowsServer2003R2では古い1024ビットがデフォルトになっているけど、現在は2048ビットが一般的なので、それを選択してCSRを作成する)
 CSRを生成したら、普通にSSL証明書を取得してきて(今回はSSLボックス
からRapidSSLを取得)、適当なcer(※α)としてファイルに保存して、再度「IIS証明書ウィザード」から証明書を登録する(証明書を取得したときに、認証局の証明書も来ると思うので、これも適当なcer(※β)としてファイルに保存しておく)
 証明書の登録処理が完了したら、「セキュリティで保護された通信」の「証明書の表示」を開いて、「詳細」タブの「ファイルにコピー」を実行して、「秘密キーのエクスポート」で「はい」を選んで進むと、PKCS#12形式に固定されているので、チェックボックスを全て解除して、適当なパスワードを設定してpfxファイルにエクスポートする。
 OpenSSLが導入された環境で・・・

openssl pkcs12 -in 出力したpfxファイル -out 中間.cer

で、PFXをデコードする。 この時、聞かれるパスワードは、エクスポート時に設定したパスワードで、パスフレーズはCERに設定するパスフレーズである。
 で、CERにすると、秘密鍵はRSA暗号化された状態なので、再度opensslで

openssl rsa -in 中間.cer -out 平文.pem

とすると、パスフレーズを聞かれるから、先ほど設定したパスフレーズを入れて平文の秘密鍵(※γ)を得る。

 この手順で、α:サーバ証明書、β:認証局証明書、γ:秘密鍵が揃うので、MySQLサーバのあるホストの適当な場所に配置する。
 後は、MySQL設定ファイル(Unixではmy.cnfだが、WindowsではMySQLインストールディレクトリのmy.ini)の[mysqld]セクションに設定を追記する。

ssl-cert=”αのフルパス”
ssl-ca=”βのフルパス”
ssl-key=”γのフルパス”

の、3設定を入れてMySQLサービスを起動する。
 MySQLクライアントで「SHOW VARIABLES LIKE ‘%ssl%’;」とか打つと、

have_openssl : YES
have_ssl : YES

になっていれば、サーバはSSL動作可能な状態になっている。

 PHPのMySQLクライアントでSSL接続する場合には、mysql_connectの第五引数にMYSQL_CLIENT_SSL定数を設定すればOK。
 Wordpressでは、/wp-include/wp-db.php で、@mysql_connect(…)としている部分で、第四引数までセットされているから、「, MYSQL_CLIENT_SSL」と第五引数を追記してやれば、WordpressのDB接続時にはSSL接続を使うようになる。
 正常にSSLに接続されているか確認するために、mysql_connectの下あたりに

$res = mysql_query(“SHOW STATUS LIKE ‘Ssl_cipher'”);
var_dump(mysql_fetch_assoc($res));

とか書いてWordpressサイトに接続してみると、DHE-RSA-AES256-SHAとかの値がべたっと入っていれば、接続はSSLで保護されている(空文字が戻っていたらSSL保護されていない)

 これで、ネット経由のmysql接続が保護されるので、安心して使うことが出来る。

(1254)

カテゴリー: MySQL, PHP, Windows VPS, サーバ設定 | コメントをどうぞ

PHPでデフォルトのSessionを使うとブラウザキャッシュが無効になる

普通にheader関数でCache-Control:max-age=360とかやったけど、ブラウザで見るとno-cacheとか色々設定されていて、Pragma:no-cacheとかも設定されている。
これは、session.cache_limiter設定値がデフォルトでnoneになっているために、Cache-Control, Expires, Pragmaをキャッシュ無効な設定をはき出す様になっている。
部分的にキャッシュを有効化したい場合、PHPマニュアルの関数を使って、設定値をprivateとかにして、適当なsession.cache_expire設定値を入れてやれば良い。
キャッシュさせるパーツにセッションを使わずget渡しにして、session_startしないのもあり。

(353)

カテゴリー: PHP | コメントをどうぞ

PHPの謎バグ

PHPでオブジェクトを配列にキャストする場合、Object $objを$array = (array)$objみたいにキャストすると、$obj->propが$array[‘prop’]になるわけだけど、JSONで渡ってきた値をphpのjson_decodeでデコードしたオブジェクトをこのキャストした場合・・・

配列をvar_dumpしたときに

‘1’=>’北海道’
‘2’=>’青森’

みたいになるんで、$array[‘1’]にアクセスすると当然’北海道’が戻ってくるべきなんだけど、$array[‘1’]でも$array[1]でもnullが戻ってきてアクセス不能になるという謎現象に陥った。

$temporary = array();
foreach($array as $key=>$val){
$temporary[$key] = $val;
}

みたいな無駄な処理を通すと、$temporary[1]にアクセスすると’北海道’ が得られるようになった。

どうも、PHPの内部処理で型キャストで配列を作る場合に内部構造がおかしくなって、連想配列と数値インデックスの単純配列の動きがおかしくなってしまうようだ。

(242)

カテゴリー: PHP | コメントをどうぞ

PHP – staticで機能をまとめる

 ある程度の規模のシステムでファンクション名を決めていると、ファンクション名が被ることがある。
 そう言うとき、機能クラスを作って、そのstaticメソッドとして定義することで、クラス名::メソッド名でコールすることが出来るのでちょっと便利。

 staticは、クラスをインスタンス化していなくても呼び出せる物で、変数とメソッドについて定義できる。

class ORDER{
public static $PAYMENT_METHODS = array(‘CARD’, ‘PAYPAL’, ‘CHECK’);
public static makeList($list){

}
}

class INVOICE{
public static makeList($list){

}
}

みたいな定義をしておくと、同じmakeList命令をORDERのmakeListとINVOICEのmakeListに明示して使い分けることが出来る。
非staticだと、

$order = new ORDER();
$order->makeList($order->PAYMENT_METHODS);
$invoice = new INVOICE();
$invoice->makeList($list);

のように、newを使ってインスタンスを作らなければならないけど、static宣言している場合は

ORDER::makeList(ORDER::$PAYMENT_METHODS);
INVOICE::makeList($list);

みたいに呼び出せるので、コードが楽になる。

(80)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP], PHP | コメントをどうぞ

PHP de ウェブサービス – WebService SOAP

 ウェブサービスを構築するときの便利プロトコル、SOAP。
 XML通信をベースとしたシステムで、下位の転送プロトコルに一般的なHTTPの他、SMTPなどを用いることも出来る便利プロトコル。
 PHPでもPHP-SOAPモジュールを使うことで扱うことが出来る。
 WSDL(Web Services Description Language:ウェブサービス記述言語)によって、サーバとクライアントでウェブサービスの機能や通信形式を記述することが出来て、これを記述すればリモートのサービスをあまり意識することなく処理することが出来る。

<?xml version=”1.0″ encoding=”UTF-8″?>
<wsdl:definitions
name=”MyService”
targetNamespace =”http://xn--ockc3f5a.com/”
xmlns =”http://schemas.xmlsoap.org/wsdl/”
xmlns:apachesoap =”http://xml.apache.org/xml-soap”
xmlns:wsdlsoap =”http://schemas.xmlsoap.org/wsdl/soap/”
xmlns:soapenc =”http://schemas.xmlsoap.org/soap/encoding/”
xmlns:soapenv =”http://schemas.xmlsoap.org/soap/envelope/”
xmlns:xsd =”http://www.w3.org/2001/XMLSchema”
xmlns:xsi =”http://www.w3.org/2001/XMLSchema-instance”
xmlns:wsdl =”http://schemas.xmlsoap.org/wsdl/”>

<wsdl:message name=”getSumRequest”>
<wsdl:part name=”A” type=”xsd:decimal”/>
<wsdl:part name=”B” type=”xsd:decimal”/>
</wsdl:message>

<wsdl:message name=”getSumResponse”>
<wsdl:part name=”Answer” type=”xsd:decimal”/>
</wsdl:message>

<wsdl:portType name=”Sum”>
<wsdl:operation name=”getSum”>
<wsdl:input name=”getSumRequest” message=”getSumRequest”/>
<wsdl:output name=”getSumResponse” message=”getSumResponse”/>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name=”SumSoapBinding” type=”Estates”>
<wsdlsoap:binding style=”rpc” transport=”http://schemas.xmlsoap.org/soap/http”/>
<wsdl:operation name=”getSum”>
<wsdlsoap:operation soapAction=””/>
<wsdl:input name=”getSumRequest”>
<wsdlsoap:body use=”encoded” encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” namespace=”http://xn--ockc3f5a.com/”/>
</wsdl:input>
<wsdl:output name=”getSumResponse”>
<wsdlsoap:body encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” namespace=”http://xn--ockc3f5a.com/”/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name=”MyService”>
<wsdl:port name=”Estate” binding=”SumSoapBinding”>
<wsdlsoap:address location=”http://xn--ockc3f5a.com/service”/>
</wsdl:port>
</wsdl:service>

</wsdl:definitions>

こんなXML文書がWDSL定義。
で、serviceに

function getSum($A, $B) {
return $A+$B;
}

$server = new SoapServer(“service?wsdl”);
$server->addFunction(‘getSum’);
$server->handle();

みたいな実装をすると、SOAPクライアントからgetSum(A, B)を呼び出すとA+Bの結果が返ってくる。

クライアントは

$options = array(
‘soap_version’=>SOAP_1_2,
‘exceptions’=>true,
‘trace’=>1,
‘cache_wsdl’=>WSDL_CACHE_NONE
);

$client = new SoapClient(‘http://xn--ockc3f5a.com/service?wsdl’, $options);
echo(“$_GET[‘A’] + $_GET[‘B’] = “.$client->getSum($_GET[‘A’], $_GET[‘B’]));

これで、client.php?A=1&B=2とかフォームで投げれば
1 + 2 = 3
みたいな動作をしてくれる。
細かい通信動作とかを自分で作らないでも、勝手に処理してくれる便利ものだ。 通信の実装を一切書かず、ローカル命令を使うのと大差ない記述でリモート命令を使えるので、ビジネスロジックとプレゼンテーションを分離したシステムを構築したりするのにとても便利だ。
SOAPはJavaや.NETにも実装されているから、サーバやクライアントを別言語で実装することも出来て自由度も高い(クライアントに至ってはMicrosoftのInfoPathと言うOfficeスイートのアプリを使うと、GUI操作だけで簡単にフォーム型クライアントを構築できてしまう)
今回は基本機能だけ使ったが、サーバで発生した例外をクライアントでキャッチしたり、addFunctionで関数を割り当てるのに変えてクラスを割り当てたり、独自の型をTypesで定義して使うことが出来るので、色々と追加していくと、超便利である。

(766)

カテゴリー: PHP | コメントをどうぞ

PHP チューニングの基本

MySQLの時にも書いたけど、チューニング情報収集が大事(どこでどれだけ時間がかかっているか知る)
Webシステムでは、どのページがどれくらい時間がかかっているかというのを知った上で、そのページの中のどこが時間がかかっているかを調べる。

で、各ページの処理時間を簡単に表示するのに、
php.ini

auto_prepend_file
auto_apend_file

この設定を使うと便利。

これは、PHPのページアクセス時に、スクリプトに先立って自動実行されるファイルと、終了時に自動実行されるファイルを指定するものだ(exit命令で終了すると自動実行されない)
この設定は.htaccessでも設定できるので、開発ディレクトリに
.htaccess

php_value auto_prepend_file autoprepend.php
php_value auto_append_file autoappend.php

のように設定して、
autoprepend.php

<?php $time_start = microtime(true); ?>

autoappend.php

<?php echo(‘runtime:’.(microtime(true)-$time_start).’sec’); ?>

みたいなファイルを用意しておくと、ページの最後にruntime:4.6920776367188372secとか表示されるので、これが大きいページから処理していくと効率が良い。

なお、この自動実行ファイルはrequiredなので、ファイルがないとFatalErrorで落ちるので、include_pathに置いておくのが良い。

(202)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP], PHP | コメントをどうぞ