サポート期間 †
PhpStorm? 有償IDE †
php-fpm †
- CentOS7.x / Apache 2.4.6 / php-fpm-5.6.30
- 「Require all granted」が必要。「AH01630: client denied by server configuration」エラー対策
<Directory /usr/share/self-service-password>
Require all granted
DirectoryIndex index.php
AddDefaultCharset UTF-8
</Directory>
- 「ProxyPassMatch 」の代わりに「SetHandler」を使う。「AH01071: Got error 'Primary script unknown\n'」エラー対策
<FilesMatch \.php$>
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
- 設定
- /etc/php-fpm.conf
- /etc/php-fpm.d/
- ログ
- /var/log/php-fpm/error.log : php-fpm自体のログ
- /var/log/php-fpm/www-error.log : アプリケーションログ
phpコマンドラインオプション †
- --ini : php.iniのパスを表示
- -i : phpinfo() を表示
- -l : 構文チェックのみ
PHP5.xでDeprecated警告を非表示にする †
curlでSSL通信エラー †
OAuth †
allow_url_fopen=0の時、curlで代用する †
- レンタルサーバ等でallow_url_fopen=0の場合に、fopen(), file_get_contents()で外部URLを開こうとすると以下のエラーが発生し、読み込めない
- Unexpected PHP error [...]: http:// wrapper is disabled in the server configuration by allow_url_fopen=0
- PHP: fopen - Manual curlで検索するとサンプルがあるのでそれを使うと良い
<?php
function get_content($url)
{
$urldata = false;
$user_agent='Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)';
if ( ini_get("allow_url_fopen") ) {
// enable allow_url_fopen
if( version_compare(PHP_VERSION, '5.0', '>=') ){
$option = array(
'http' => array(
'timeout' => 5,
'method' => 'GET',
'header' => 'Referer: ' . $url . "\r\n"
. 'User-Agent: ' . $user_agent . "\r\n"
. 'Connection: close' . "\r\n"
)
);
$context = stream_context_create($option);
$urldata = @file_get_contents($url, 0, $context);
}else{
$urldata = @file_get_contents($url);
}
}else{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
ob_start();
curl_exec ($ch);
curl_close ($ch);
$urldata = ob_get_contents();
ob_end_clean();
}
return $urldata;
}
$content = get_content("http://www.php.net");
var_export($content);
OS判別 †
CLIでも使えるPHP_OS, php_uname が便利
<?php
echo PHP_OS . "\n"; // AIX, Darwin, MacOS, Linux, SunOS, WIN32, WINNT
echo php_uname() . "\n"; // Linux hostname 2.6.18-308.1.1.el5 #1 SMP Wed Mar 7 04:16:51 EST 2012 x86_64
phpでワンライナー †
- $argv[1]:コマンドラインオプションの取得
- -R:標準入力を1行ごとに順に処理する
- -F:処理内容をファイルで渡す
- -B:初期化処理
- -E:終了処理
- シェルスクリプト化
cat >> utf8tosjis.sh <<'EOD'
#!/usr/bin/php -F
<?php echo mb_convert_encoding($argn, "UTF-8", "SJIS-win"), "\n";
EOD
chmod 755 utf8tosjis.sh
./utf8tosjis.sh < utf8.txt > sjis.txt
- ファイルサイズ合計
ls -l /tmp | php -B '$sum=0;' -R '$vals=preg_split("/\s+/",$argn);$sum+=$vals[4];' -E 'echo "Total size of files: ", $sum, "\n";'
PHP5.4の変更点 †
天気の取得 †
配列の文字コードを変換 †
日本語URLのエンコード †
wikipediaやamazon.co.jpのページURLに日本語が含まれており、うまくリンクできない場合もある。
urlencodeすれば動作する場合もある。
<?php
mb_internal_encoding('utf-8');
mb_http_input('pass');
mb_http_output('pass');
echo url_normalize("http://ja.wikipedia.org/wiki/Wikipedia:コミュニティ・ポータル#hoge") . "\n";
//result: http://ja.wikipedia.org/wiki/Wikipedia%3A%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3%E3%83%BB%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%AB#hoge
echo url_normalize("http://www.amazon.co.jp/三洋電機-KBC-L54D-SANYO-USB出力付きリチウムイオンバッテリー-高容量リチウムイオン3-7V5400mAh電池使用/dp/B005DUMNSE/ref=sr_1_1?ie=UTF8&qid=1323766118&sr=8-1");
//result: http://www.amazon.co.jp/%E4%B8%89%E6%B4%8B%E9%9B%BB%E6%A9%9F-KBC-L54D-SANYO-USB%E5%87%BA%E5%8A%9B%E4%BB%98%E3%81%8D%E3%83%AA%E3%83%81%E3%82%A6%E3%83%A0%E3%82%A4%E3%82%AA%E3%83%B3%E3%83%90%E3%83%83%E3%83%86%E3%83%AA%E3%83%BC-%E9%AB%98%E5%AE%B9%E9%87%8F%E3%83%AA%E3%83%81%E3%82%A6%E3%83%A0%E3%82%A4%E3%82%AA%E3%83%B33-7V5400mAh%E9%9B%BB%E6%B1%A0%E4%BD%BF%E7%94%A8/dp/B005DUMNSE/ref=sr_1_1?ie=UTF8&qid=1323766118&sr=8-1
/**
* URL正規化。日本語が含まれたURLをurlencodeして返す
*
* @param string $url URL
* @return string 正規化したURL
*/
function url_normalize($url, $options=array()) {
$tmp = parse_url($url);
$paths = explode("/",$tmp["path"]);
$pattern = "/^[-_.!~*'()a-zA-Z0-9;\/\?:@&=+$,%#]+$/";
foreach($paths as $key => $val){
if( !preg_match($pattern, $val, $matches) ){
$paths[$key] = urlencode($val);
}
}
return sprintf("%s://%s%s%s%s%s",
$tmp['scheme']
, isset($tmp['user']) ? $tmp['user'] . ':' . $tmp['pass'] . '@' : ''
, $tmp['host']
, implode("/", $paths)
, isset($tmp['query']) ? '?' . $tmp['query'] : ''
, isset($tmp['fragment']) ? '#' . $tmp['fragment'] : ''
);
}
コンパイル †
ファイルアップロード †
RESTインタフェース †
携帯判別 †
5.2と5.3で日本語ファイル名の扱いが異なる †
- Windows版php5.3.8で日本語ファイル名に対してfilesize()をすると読み込めないエラー多発
外字の取り扱い †
- また、外字を含むエンコード形式もある(PHP v5.2.1以降) mb_list_encodings() で確認できる
- SJIS-win
- eucJP-win
- ISO-2022-JP-MS
プロキシ経由でも実際のクライアントIPを取得 †
Facebook, twitter, OpenID認証 †
高速化/最適化 †
- opecache / apcu は必須。5倍以上の速度差が出る
- CentOS 7 remi repoを使う場合: デフォルトははphp5.4
sudo yum install php-pecl-zendopcache php-pecl-apcu
sudo service httpd restart
# モジュールとして読み込まれているか確認
php -m
# 他に php55-, php56-, php70-, php71- 等にバージョン毎に別パッケージがある
- php 5.5以上はopcacheが組み込まれた。php-pecl-zendopcacheの代わりに phpXX-php-opcache を入れる
date.timezoneを設定しないとエラー †
php5.3.6でdate.timezoneが設定されていないとエラーが出る
- Strict Standards: date() [function.date]: It is not safe to rely on the systems timezone settings, please use the date.timezone setting, the TZ environment variable or the date_default_timezone_set() function. We now use 'Asia/Tokyo' for 'JST' in
プロファイリング †
キャッシュ †
小ネタ †
負荷計測 †
MessagePack serialize †
デバッグツール †
画像をHTML内に埋め込んで高速化 †
小さい画像をたくさん使用しているなど、別コネクションへの速度が遅い場合に有効
ファイルマネージャ †
ファイルマネージャelfinderをCentOS5.4+PHP5.1.6にインストール †
- json_encode()を使用しているので、PHP5.2.0以降または、「pecl json」が必要
- 環境に合わせる
- connectors/php/connector.php
<?php
if (function_exists('date_default_timezone_set')) {
date_default_timezone_set('Asia/Tokyo');
}
...
$opts = array(
'root' => '../../../', // path to root directory
'URL' => 'http://localhost/path/to/', // root directory URL
'rootAlias' => 'Home', // display this instead of root directory name
);
elfinder.html
apacheログに任意値を出力 †
ImageMagick †
pecl imagickでインストールエラー †
- 「php-config --vernum」を実行しようとして失敗している
pecl install imagick
php5.1.6 -> php5.2.xへアップデート †
Excel †
PDF †
Services_TwitterでenableJsonConvert()を使う †
プログラミングができなくても作れるTwitter botの作り方で phaさんが配布している改造版 Services_Twitter でenableJsonConvert()を有効にするパッチ。
同梱されているJsphon.phpを直接使うように変更しています。
SSL証明書エラーの無視 †
- linux上でチェック
# "https"が含まれていない場合は、PHP本体のコンパイル時にSSLを有効にしていない場合もある
php -i | grep "Registered PHP Streams"
Registered PHP Streams => https, ftps, compress.zlib, compress.bzip2, php, file, glob, data, http, ftp, phar, zip
# mod_ssl, opensslが必要
rpm -qa | grep ssl
mod_ssl-2.2.3-65.el5.centos
openssl-0.9.8e-22.el5_8.4
半角英数、全角文字を1文字としてカウントする †
<?php
// 半角英数、全角文字を1文字としてカウントする
$str = 'カウント対象文字列';
if( preg_match_all('/./u', $str, $matches) ){
printf("count:%d\n", count($matches[0]));
}
PhotoMogaic †
複数の画像で、大きな1毎画像を構成するように見せる事。
SQLのようにHTMLを操作できる htmlSQL †
jQueryのセレクタのようにHTMLを操作できる PHP Simple HTML DOM Parser †
htmlの特定のタグを除去 †
memcachedの情報を表示 †
memcached利用の際にphp.iniの設定を参照する †
phpStylistを使った整形 †
デザインパターン †
file_get_contents()だとLocationヘッダ + body部がある場合にリダイレクトされて、body部が取得できない †
- file_get_contents()だとLocationヘッダ + body部がある場合にリダイレクトされて、body部が取得できない
- 下記の例では、post1.phpのjson文字列が取得できず、「post2.php」という文字列の取得になる
- 取得元ソース
#!php
<?php
echo file_get_contents("http://example.com/path/to/post1.php");
- post1.php
#!php
<?php
header('HTTP/1.0 201 Created');
header('Content-Type: application/json; charset=utf-8');
header('Location: http://example.com/path/to/post2.php');
echo <<<EOD
{
"startIndex" : 1
}
EOD;
- post2.php
#!php
<?php
echo 'post2.php';
- file_get_contents()にLocationヘッダを無視するオプションは見当たらない
file_get_contentsでpost †
- とても簡単にPHPからPOSTリクエストを送信する方法【PHP】 - Programming Magic
<?php
$url = 'http://www.php.net/search.php';
$data = array(
'pattern' => 'htmlspe',
'show' => 'quickref',
);
$headers = array(
'User-Agent: My User Agent 1.0', //ユーザエージェントの指定
'Authorization: Basic '.base64_encode('user:pass'),//ベーシック認証
);
$options = array('http' => array(
'method' => 'POST',
'content' => http_build_query($data),
'header' => implode("\r\n", $headers),
));
$contents = file_get_contents($url, false, stream_context_create($options));
file_get_contentsでhttpヘッダを取得 †
<?php
file_get_contents("http://example.com");
var_export($http_response_header);
直近のエラーメッセージを取得 †
ini_set('track_errors', 1); //直近のエラーメッセージを $php_errormsg に代入
basename,pathinfoで日本語が使えない †
グラフ †
特定の単語を含むhtmlタグ抽出 †
$quote_text = preg_quote("ほげ");
if(!preg_match_all("/<.*?({$quote_text})[^\?>]*?>/i", $data, $matches, PREG_SET_ORDER)){
var_export($matches);
}
月末 †
mktimeは存在しない日付の時に、正しい値に正規化してくれる。
- 月末 (2月の月末)
date('Y-m-d', mktime(0,0,0, 2+1, 0, 2008));
phpDocumentor †
PHPバージョンの取得 †
- phpversion();
- PHP_VERSION
- 比較
- version_compare();
defined('AK_PHP5') ? null : define('AK_PHP5', version_compare(PHP_VERSION, '5', '>=') == 1 ? true : false);
標準エラー †
- httpd経由の場合は、既にSTDERRオープン状態のようで、そのまま使える
- コンソールで実行(php -q hoge.php)の場合は、STDERRは定義されてないので、自分で開いてやる。STDOUT, STDINも同様
if (!defined('STDERR'))
{
define('STDERR', fopen('php://stderr', 'w'));
}
fwrite(STDERR, "Can't open file. [$xml_file]\n");
$_SERVER['PHP_SELF']とXSS脆弱性 †
「このインターネットのサイトを開くことができませんでした。」 †
- IE6で、SSLのサイトからダウンロードしようとすると起こる。不具合っぽい
- phpの場合、session_start()すると、session_cache_limiterの値によって、no-cacheやno-storeが自動送信される。
指定した幅で文字列を丸める †
- strlenだと、2byte文字コードでの境界で、文字化けが発生する。
- mb_strimwidth なら、文字コードが指定でき、置換文字も指定可能
string mb_strimwidth ( string str, int start, int width [, string trimmarker [, string encoding]] )
各種文字エンコード †
- URLやファイル名に日本語が入って場合にエンコードすると良い場合も。
長いURLを短くする †
- ショートURLとか、圧縮URL、短縮URLとか言うのか
テンポラリファイル名 †
- tempnam(string dir, string prefix)がある
各種日付 †
- PHP 5.1.1 以降だと色々な日付が定義されているらしい
- http://blog.koshigoe.jp/archives/2007/09/php_6.html
<?php
$date_const_list = array(
'DATE_ATOM',
'DATE_COOKIE',
'DATE_ISO8601',
'DATE_RFC822',
'DATE_RFC850',
'DATE_RFC1036',
'DATE_RFC1123',
'DATE_RFC2822',
'DATE_RFC3339',
'DATE_RSS',
'DATE_W3C',
);
foreach ($date_const_list as $date_const) {
echo sprintf("%16s: %-16s\t%s\n",
$date_const,
constant($date_const),
date(constant($date_const)));
}
/** 結果
* DATE_ATOM: Y-m-d\TH:i:sP 2007-09-03T17:02:31+09:00
* DATE_COOKIE: l, d-M-y H:i:s T Monday, 03-Sep-07 17:02:31 JST
* DATE_ISO8601: Y-m-d\TH:i:sO 2007-09-03T17:02:31+0900
* DATE_RFC822: D, d M y H:i:s O Mon, 03 Sep 07 17:02:31 +0900
* DATE_RFC850: l, d-M-y H:i:s T Monday, 03-Sep-07 17:02:31 JST
* DATE_RFC1036: D, d M y H:i:s O Mon, 03 Sep 07 17:02:31 +0900
* DATE_RFC1123: D, d M Y H:i:s O Mon, 03 Sep 2007 17:02:31 +0900
* DATE_RFC2822: D, d M Y H:i:s O Mon, 03 Sep 2007 17:02:31 +0900
* DATE_RFC3339: Y-m-d\TH:i:sP 2007-09-03T17:02:31+09:00
* DATE_RSS: D, d M Y H:i:s O Mon, 03 Sep 2007 17:02:31 +0900
* DATE_W3C: Y-m-d\TH:i:sP 2007-09-03T17:02:31+09:00
*/
?>
デザインQR †
QRコードに文字や絵を埋め込んだもの。
QRコードのエラー訂正率の高さを利用していると想像される。
正規表現 †
phpで分かち書き †
カレンダーライブラリ †
Basic認証済みユーザ名/パスワード †
$_SERVER['PHP_AUTH_USER']
$_SERVER['PHP_AUTH_PW']
Basic認証されたページを取得する †
- PEAR::HTTP_Client HTTP_ClientはHTTP_Requestのラッパー
[luna @ xxxxx public_html]$ php --version
PHP 5.1.6 (cli) (built: Nov 17 2006 08:52:42)
[luna @ xxxxx public_html]$ pear list
HTTP_Client 1.1.0 stable
HTTP_Request 1.4.0 stable
Net_Socket 1.0.6 stable
Net_URL 1.0.14 stable
[luna @ xxxxx public_html]$ cat httpclient.php
<?php
require_once 'HTTP/Client.php';
$url = "https://xxxxx.xxx.xxxx/~xxxxx/xxxxx/";
$param = array( 'user' => 'xxxxx', 'pass' => 'xxxxxxxx' );
$req = new HTTP_Client($param);
$req->get($url);
$response = $req->currentResponse();
var_dump($response);
- PEAR::HTTP_Request
- httpsの場合、php -i or phpinfo()で、「Registered PHP Streams」に「https」が含まれている必要はある。
- http_get()
- PECL pecl_http:0.1.0-1.4.1
- Curl
<?
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt(CURLOPT_USERPWD, '[username]:[password]')
$data = curl_exec();
curl_close($ch);
?>
フィルタリングの順序 †
n進数変換 †
- DBのシーケンス値を文字列に変換。URLの表示等に。
- urlの短縮に。
- YoutubeのコンテンツIDは62進数っぽい
Tag Cloud †
- はてなブクマやblog等で最近よく見かける「タグ」システムについて。
- 勝手に添削「タグを実現するテーブル設計を妄想する」
- PHP用タグクラウド生成ライブラリ(HTML_TagCloud)利用サンプル
ini中のサイズ文字列を数値に変換 †
- PHP: ファイルアップロードの処理 - Manual
<?php
function ini_get_size($sName)
{
$sSize = ini_get($sName);
$sUnit = substr($sSize, -1);
$iSize = (int) substr($sSize, 0, -1);
switch (strtoupper($sUnit))
{
case 'Y' : $iSize *= 1024; // Yotta
case 'Z' : $iSize *= 1024; // Zetta
case 'E' : $iSize *= 1024; // Exa
case 'P' : $iSize *= 1024; // Peta
case 'T' : $iSize *= 1024; // Tera
case 'G' : $iSize *= 1024; // Giga
case 'M' : $iSize *= 1024; // Mega
case 'K' : $iSize *= 1024; // kilo
};
return $iSize;
}
// example
echo ini_get_size('post_max_size'); // e.g. 8388608 instead of 8M
?>
マルチバイト文字対応trim †
/**
* 全角文字対応trim
*
* @param string $str 入力文字列
* @param string $charlist 削除する文字を指定(省略可。入力する場合は'EUC-JP'の文字のみ)
* @param string $encoding 文字コード(省略可。utf-8の場合必須)
*
* @note
* - 文字列の先頭および末尾にあるホワイトスペースを取り除く
* - " ", 通常の半角空白。
* - " ", 全角空白。
* - "\t", タブ。
* - "\n", リターン。
* - \r", 改行。
* - "\0", NULバイト
* - "\x0B", 垂直タブ
*/
function mb_trim($str, $charlist = '', $encoding = '')
{
$pattern = "/^[ {$charlist}]*(.*?)[ {$charlist}]*$/";
if( strcasecmp($encoding, 'UTF-8') == 0 ){
$pattern .= 'u'; // UTF-8処理オプション付加
$pattern = mb_convert_encoding($pattern, 'UTF-8', 'EUC-JP');
}
$str = preg_replace($pattern, '$1', $str);
$str = trim($str);
return $str;
}
PostgreSQLと文字コード †
PHPソースの文字コードがUTF-8で、データベースの文字コードがEUC-JPだった場合、
いちいちmb_convert_encodingで変換しなくとも、pg_set_client_encodingで自動変換してくれます。
pg_set_client_encoding(mb_internal_encoding());
foreach, array_map, array_walk 速度比較 †
- 結果
- foreachが一番早く、array_walkが一番遅かった。関数の複雑さ通りの結果か。
- foreach : 1.05 s
- array_map : 4.74 s
- array_walk : 5.21 s
xmlからJSON形式へ変換 †
require_once("XML/Unserializer.php");
require_once("Jsphon/Jsphon.php");
function xmlToJson($url, $callback = "") {
$req =& new HTTP_Request($url);
if (PEAR::isError($req->sendRequest())) {
die($req->getMessage());
}
$xml = $req->getResponseBody();
$xml = mb_convert_encoding($xml, "UTF-8", "auto");
$unserializer =& new XML_Unserializer();
$unserializer->setOption('parseAttributes', TRUE);
$status = $unserializer->unserialize($xml);
if (PEAR::isError($status)) {
die($status->getMessage());
}
$json = Jsphon::encode($unserializer->getUnserializedData(), false);
if ($callback != "") {
$json = $callback . '(' . $json . ')';
}
header("Content-Type: text/javascript; charset=utf-8");
echo $json;
}
16桁のID作成 †
- uniqidは標準で13桁なので、+3文字プラスする。
uniqid(rand(100,999))
phpのシリアライズ変数を別言語で扱う †
phpコードをexeに変換 †
JavaScriptのescape()をデコードする †
Ajaxでは、フォームの自動encode/decodeはしてくれないので、自分で行う必要がある。
機種依存文字の変換 †
PHP4とPHP5の共存 †
continueのレベル †
以下の例では期待通りの動作をしない。phpの場合、continueにループのレベル階層数を指定する事で、switch文の中でも、指定のループの先頭へ戻る事ができる
- 「continue 2」にした場合
0,2,3,4,
phpで圧縮・解凍 †
microtimeの取得 †
<?php
function getmicrotime(){
list($usec, $sec) = explode(" ",microtime());
return ((float)$sec + (float)$usec);
}
$st = getmicrotime();
// 長い処理
sleep(1);
$ed = getmicrotime();
printf("time : %0.4fs\n", $ed - $st);
Cookieが使えない場合のセッション指定方法 †
- SID
- "name=ID"形式でセッション名とセッションIDを格納している定数。 セッションIDがセッションクッキーに適切にセットされている場合には空文字列が入る。
- 1.phpへセッションを渡す
<?
ini_set("session.use_cookies", 0);
session_start();
$_SESSION["date"] = date("Ymd");
?>
<a href="1.php?<? echo SID; ?>">1.php</a>
- 結果
<a href="1.php?PHPSESSID=4dd9dab841e4433471120f80508af2a3">1.php</a>
外部変数名のドット †
Warning: Call-time pass-by-reference has been deprecated ... †
Warning: Call-time pass-by-reference has been deprecated
php.iniの「allow_call_time_pass_reference = Off」の時、引数にリファレンスを用いると発生する。
- 対策
- 「allow_call_time_pass_reference = On」にするか、ソースを書き換える。
- allow_call_time_pass_reference = Off
PHP Notice: Only variables should be assigned by reference in ... †
カレントの行番号、ファイル名等を得る †
- __FILE__, __LINE__
- debug_backtrace()を使用
生のHTTP POSTを取得する †
バイナリデータをPOSTで受信したい場合等に使用。
セッションの分散化 †
CAPTCHA - SPAM対策 †
イメージに書かれたグニャ〜と歪んだ文字をテキストボックスに入力してください
というのがあります。
:CAPTCHA(キャプチャ)((completely autattachref(array_speed.php);
- 結果
- foreachが一番早く、array_walkが一番遅かった。関数の複雑さ通りの結果か。
- foreach : 1.05 s
- array_map : 4.74 s
- array_walk : 5.21 s
xmlからJSON形式へ変換 †
require_once(omated public Turing test to tell computers and humans apart))|コンピュータと人間を区別する完全に自動化された公開チューリングテスト
クラスのメンバ関数をコールバック関数として使う †
array_map()に指定するコールバック関数で、クラスのメンバ関数を指定する方法です。
- PHP4
array_map(array(&$this, 'コールバック関数'), 配列)とします。
- PHP5
array_map(array($this, 'コールバック関数'), 配列)とします。
ダメな例:
array_map('Sample::array_convert_encoding'), $ary); // エラー
array_map('$this->array_convert_encoding'), $ary); // エラー
成功例:
<?
$oSample = new Sample;
$oSample->main();
exit;
class Sample
{
function main()
{
$ary = array("hoge", "hogehoge");
var_export( array_map(array(&$this, 'array_convert_encoding'), $ary) );// PHP4のみ。PHP5の場合は参照('&')は必要ない。
}
function array_convert_encoding($str)
{
return mb_convert_encoding($str, "SJIS", mb_internal_encoding());
}
}
SQLのようにHTMLを操作できる htmlSQL †
簡易コールバック関数を使う †
array_map()等コールバック関数を必要とする場合で、簡単な処理ならばcreate_function()を使う事で1行記述もできるようです。
わかりにくくなるので、注意が必要です。
素直な例:
<?
$a = range( 1, 9 );
$a = array_map( 'hoge', $a );
print_r($a);
function hoge( $n ){
return sprintf( "%02d", $n );
}
?>
小細工で短く:
<?
$a = range( 1, 9 );
$a = array_map( create_function( '$n', 'return sprintf( "%02d", $n );' ), $a );
print_r($a);
?>
UDPパケットクラス †
- 簡単な使い方
例:ブロードキャストのポート10000にパケットを投げる。
include_once("udp.inc.php"); ///< UDP
$data = pack("C*", 0x00, 0x01, 0x02); ///< データ
$oUDP = new UDP;
if(!$oUDP->open("", 10000)){
return false;
}
$oUDP->send($data);
udp.inc.php
PHPソースのコーディングスタイルを統一する †
phpCodeBeautifier(Windowsのみ)がある。
phpファイルを読み込んで、整形してくれる。
デフォルトのままでは、マルチバイト文字が文字化けするが、保存は正常にできる模様。
NULLバイトアタックの対処 †
include(), include_once(), require(), require_once()等、動的includeする場合は、NULLバイトアタックに注意する。
// NULLバイト等不適切な部分を削除する関数
function sanitize( $arr )
{
if ( is_array( $arr ) ) {
return array_map( 'sanitize', $arr );
}
return str_replace( "\0", "", $arr );
}
$_GET = sanitize( $_GET );
$_POST = sanitize( $_POST );
$_COOKIE = sanitize( $_COOKIE );
標準出力に違う文字コードで出力したい †
通常、echoやprint等で出力すると、自動的にphp.iniで指定された、mbstring.http_outputの文字コードに変換されます。
しかし、UTF-8のXMLを出力させる時は、文字化けしてしまいます。
これを抑制して素のデータを出力するには、以下のようにします。
// 無変換で出力させる
mb_http_output("pass");
// ヘッダ
header("Content-type: text/xml; charset=UTF-8");
// 出力
echo mb_convert_encoding("ほげ", "UTF-8");
デフォルトの文字エンコードを変更して文字化けの解消 †
apacheのhttpd.conf や .htaccessに記述する事により、ディレクトリ毎に文字コードを指定できる。
- 文字化けする場合
- 文字列が短すぎると、自動認識(mbstring.detect_order=auto)に失敗する場合がある
- mbstring.detect_order を変更して、検出させたい文字コードを先に指定すると良い
- /etc/php.ini の例
output_handler = mb_output_handler
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.encoding_translation = Off
mbstring.detect_order = UTF-8,SJIS-win,eucJP-win,JIS,ASCII
mbstring.substitute_character = none
mbstring.func_overload = 0
- .htaccess の例
Options -Indexes
php_value output_handler "mb_output_handler"
php_value mbstring.language "Japanese"
php_value mbstring.internal_encoding "utf-8"
php_value mbstring.http_input "pass"
php_value mbstring.http_output "pass"
php_flag mbstring.encoding_translation "Off"
php_value mbstring.detect_order "UTF-8,SJIS-win,eucJP-win,JIS,ASCII"
php_value mbstring.substitute_character "none"
php_value mbstring.func_overload "0"
例:/var/www/html/phpPgAdmin以下の内部エンコードをUTF-8にする。
/etc/httpd/conf/httpd.conf
<Directory "/var/www/html/phpPgAdmin">
php_value mbstring.internal_encoding UTF-8
</Directory>
サービスの再起動
# service httpd restart
httpヘッダに「X-Powerd-By ...」を出力しないようにする †
デフォルトでは、httpヘッダにPHPの作成元やバージョンが出力されます。
セキュリティ上脆弱性のあるバージョンを知られてしまう上、余計な情報なので、
出力しない場合は、php.iniを変更します。
/etc/php.ini
expose_php = Off
その後、httpdの再起動
# service httpd restart
16進数文字列を数値に変換する †
HexDec("ff"); // -> 255
preg_replaceで'¥'を置換する †
例えば、'¥'を'/'に置換する場合、’¥’が3つ必要。
× preg_replace('/\\/', '/', $str);
○ preg_replace('/\\\/', '/', $str);
"select multiple"タグで選択された全ての結果を取得する †
以下のようにタグの名前に"[]"を付けてやることで、phpに配列だと知らせる事ができる。
<select name="var[]" multiple>
JavaScriptでは上記"[]"でエラーが出る事があるので、以下のようにelements経由でアクセスする。
var variable = documents.フォーム名.elements['var[]'];
var count=0;
for(var i=0; i < variable.options.length; i++){
if(variable.options[i].selected) count++;
}
alert("selected:" + count);
PHPマニュアル>"select multiple"タグで選択された全ての結果を取得するにはどうす ればよいですか?
ob_end_flush()でエラーとなる †
ob_end_flush()でエラーとなる場合がある。
以下のように"ob_gzhandler"を使うとエラーとなるようである。
対応モジュールが入っていない場合は、コメントアウトすると良いだろう。
ob_start("ob_gzhandler");
巨大なファイルをダウンロードさせる †
通常では30秒でセッション切れを起こし、PHPは致命的エラーを返します。
そこで、set_time_limit()でセッションの時間を延長します。
出力バッファを無効にすると、すぐにダウンロードダイアログが出るようになります。
// HTTPヘッダ出力前
set_time_limit(0); // 制限時間なし
// ob_start("ob_gzhandler"); // 出力バッファをgzip圧縮する(モジュールがある場合)
// HTTPヘッダ出力後
while (@ob_end_flush()); // バッファを無効に
// 以後、巨大なファイル出力
数値を3桁づつカンマ区切りにする †
number_format()関数がある。
デフォルトでカンマで区切ってくれる。
$a = number_format(1234);
// 1,234
文字列を1文字に分割する †
<?
$a = preg_split('//', "abcde", -1, PREG_SPLIT_NO_EMPTY);
var_export($a);
?>
https経由でのファイルダウンロードで壊れる †
クライアントが Win 版 MSIE 5.5 のときに、
- HTTPS 経由で
- 同時に Set-Cookie ヘッダがあると
ファイルダウンロードに失敗するようです。
解決策は、セッション開始前に、キャッシュ設定をしてやるといいようです。
session_cache_limiter('public');
session_start();
ファイルアップロードでファイルが壊れる場合 †
PHPでファイルアップロード後に、ファイルが壊れる(ファイルサイズが増える)場合があります。
これは、Apacheの設定が原因のようです。
具体的には以下の行を、コメントアウトすると壊れなくなりました。
/etc/httpd/conf/httpd.conf
#AddType application/x-httpd-php .php
#AddType application/x-httpd-php-source .phps
AddTypeの設定は、PHPが、DSOモジュールでインストールされている場合は必要ないようです。
「/etc/httpd/conf.d/php.conf」がヘッダの設定をしているようです。
複雑な構造の変数の内容を表示するには †
var_export()やvar_dump()を使います。
var_export()は値だけ、var_dump()は型も表示します。
オブジェクトもその中身を表示してくれるので便利です。
クラスの参照を返すには †
PHPの参照宣言は、C++言語の参照とは違い、
関数宣言時と変数への代入時両方に&を付けないと予想通りには動かない。
付け忘れて、値が変更されない場合があるので、参照を使う際には注意が必要。
参考URL:http://php.s3.to/man/language.references.return.html
<?php
class base{
var $x = "none";
}
class ext extends base{
function printVar(){
echo "printVar() : " . $this->x . "<br>\n";
}
function &getThis(){
return $this;
}
}
$obj = new ext();
$r = $obj->getThis(); // &なし
$r2 = &$obj->getThis(); // &あり
$r->x = "hoge"; // 値は変更されない
$r2->x = "moke"; // 値は変更される
echo '$r->x : ' . $r->x . "<br>\n";
echo '$r2->x : ' . $r2->x . "<br>\n";
$obj->printVar();
?>
実行結果
$r->x : hoge
$r2->x : moke
printVar() : moke