Memo/PHP

https://dexlab.net:443/pukiwiki/index.php?Memo/PHP
 

Memo/PHP


サポート期間


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警告を非表示にする

  • 古いPEARライブラリなど大量に出る場合があるが、それを非表示にする場合
    vim /etc/php.ini
    ----
    error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
    ----
    service httpd restart

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

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:終了処理
  • 日付形式の変換
    php -r 'echo Date("Y-m-d H:i:s", strtotime($argv[1]));' "2012-07-24T22:13:08.000-05:00"
    2012-07-25 12:13:08
  • lsで取得したファイル名を全大文字化
    ls /tmp | php -R 'echo strtoupper($argn),"\n";'
  • シェルスクリプト化
    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()をすると読み込めないエラー多発

外字の取り扱い

  • mb_substitute_character を使うとmb_convert_encodingで変換不可能な文字の取り扱いを指定できる
  • また、外字を含むエンコード形式もある(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
  • /etc/php.ini
    date.timezone = "Asia/Tokyo"

プロファイリング

キャッシュ

小ネタ

負荷計測

MessagePack? serialize

デバッグツール

画像をHTML内に埋め込んで高速化

小さい画像をたくさん使用しているなど、別コネクションへの速度が遅い場合に有効

ファイルマネージャ

ファイルマネージャelfinderをCentOS5.4+PHP5.1.6にインストール

  • json_encode()を使用しているので、PHP5.2.0以降または、「pecl json」が必要
  • 本体のダウンロード
    wget -O elfinder-1.1.zip "http://downloads.sourceforge.net/project/elfinder/elfinder-1.1.zip?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Felfinder%2Ffiles%2F&ts=1283849097&use_mirror=jaist"
    unzip elfinder-1.1.zip
    mv elfinder-1.1 elfinder
    cd elfinder/
  • jsonをpeclでインストールする場合
    sudo pecl install json
    sudo sh -c "cat >> /etc/php.d/json.ini << 'EOS'
    extension=json.so
    EOS"
    sudo /sbin/service httpd graceful
    php -m | grep json
  • Jsphonを利用する場合
    wget http://svn.coderepos.org/share/lang/php/Jsphon/release/Jsphon-1.0.1.tgz
    tar xvfz Jsphon-1.0.1.tgz
    mv Jsphon-1.0.1/Jsphon .
    
    vi connectors/php/elFinder.class.php
    ----
    // <?の次行あたりに追加
    if( !function_exists('json_encode')
    ){
            require_once(dirname(dirname(dirname(__FILE__))) . '/' . 'Jsphon/Encoder.php');
            function json_encode($str){
                    $jsphon = new Jsphon_Encoder();
                    return $jsphon->encode($str);
            }
    }
    ----
  • 環境に合わせる
    • 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
      );
    • fileelfinder.html

apacheログに任意値を出力


ImageMagick?


pecl imagickでインストールエラー

pecl install imagick
  • /usr/bin/php-config
    vernum="50106"
    ...
    --vernum)
            echo $vernum;;
  • 64bit osの場合
    mv /usr/lib/php/modules/imagick.so /usr/lib64/php/modules/

php5.1.6 -> php5.2.xへアップデート


Excel


PDF


Services_TwitterでenableJsonConvert?()を使う

プログラミングができなくても作れるTwitter botの作り方で phaさんが配布している改造版 Services_Twitter でenableJsonConvert?()を有効にするパッチ。
同梱されているJsphon.phpを直接使うように変更しています。

  • easybotter1.42.zip向け
  • サンプル
    <?php
    require_once("Services/Twitter.php");
    
    $user = 'Your_Username';
    $pass = 'Your_Password';
    
    $st =& new Services_Twitter($user, $pass);
    $st->enableJsonConvert();
    
    $result = $st->setUpdate("つぶやき");
    var_export($result);

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
  • pear::HTTP_Request2
    <?php
    $request = new HTTP_Request2();
    
    // SSL証明書の検証(default:true)
    $request->setConfig('ssl_verify_peer', false);
    
    // SSL自己証明書の許可(default:true)
    HTTP_Request2::setConfig('ssl_verify_host', false);

半角英数、全角文字を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を使った整形

  • filephpStylist.sh
    chmod 700 phpStylist.sh
    ./phpStylist.sh INPUT-DIR OUTPUT-DIR

デザインパターン

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でpost

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で日本語が使えない

  • PHP5のバグ PHP :: Bug #37738 :: basename does not work with Japanese
    // PHP5のbasename(), pathinfo()で日本語ファイル名が扱えないため
    function mybasename($file, $suffix = '', $ds = '/')
    {
    	// PHP :: Bug #37738 :: basename does not work with Japanese
    	// http://bugs.php.net/bug.php?id=37738
    	$str = substr(strrchr($ds."$file",$ds),1);
    	if($suffix != '') $str = substr($str, 0, strrpos($str, $suffix));
    	return $str;
    }

グラフ

特定の単語を含む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

  • インストール
    pear install --alldeps phpdocumentor
  • 実行
    phpdoc -t doc/ -d trunk/ -o HTML:Smarty:PHP

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のサイトからダウンロードしようとすると起こる。不具合っぽい
    • [暗号化されたページをディスクに保存しない] が有効の場合
    • Cache-control: no-cache ヘッダーが送信された場合
    • Cache-control: no-store ヘッダーが送信された場合
    • http://support.microsoft.com/kb/812935/ja
  • phpの場合、session_start()すると、session_cache_limiterの値によって、no-cacheやno-storeが自動送信される。
    • session_cache_limiter('public');を実行する事で、上記ヘッダが出力されなくなるので、ダウンロードできるようになる。
    • もしくは、以下のようにheader()で上書しても可能。
      header("Cache-Control: public");
      header("Pragma: public");

指定した幅で文字列を丸める

  • strlenだと、2byte文字コードでの境界で、文字化けが発生する。
  • mb_strimwidth なら、文字コードが指定でき、置換文字も指定可能
    string mb_strimwidth ( string str, int start, int width [, string trimmarker [, string encoding]] )

各種文字エンコード

  • URLやファイル名に日本語が入って場合にエンコードすると良い場合も。
  • プログラム
    <?php
    mb_http_output('pass');
    $str = "abc123-_ほげ";
    echo "str           : " . $str . "\n";
    echo "urlencode     : " . urlencode($str) . "\n";
    echo "base64_encode : " . base64_encode($str) . "\n";
    echo "rawurlencode  : " . rawurlencode($str) . "\n";
  • 結果
    str : abc123-_ほげ
    urlencode : abc123-_%82%D9%82%B0
    base64_encode : YWJjMTIzLV+C2YKw
    rawurlencode : abc123-_%82%D9%82%B0

長い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で分かち書き

  • chasen使用ライブラリ(作成途中)

カレンダーライブラリ

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進数っぽい
  • 2〜36まで
    • base_convert()

Tag Cloud

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文の中でも、指定のループの先頭へ戻る事ができる

  • 例1:通常のcontinue。期待通りの動作をしない。
    for($i=0;$i<5;$i++){
    	switch($i){
    	case 1;
    		continue;
    	}
    	echo "$i,";
    }
  • 結果
    0,1,2,3,4,
  • 「continue 2」にした場合
    0,2,3,4,

phpで圧縮・解凍

  • system関数を使う
    • zip
      • 圧縮
        system('zip -q test.zip 001.jpg file2.jpg');
      • 解凍
        system('unzip -q test.zip -d ./test/');
  • lzh
    • 圧縮
      system('lha aq test.lzh 001.jpg file2.jpg');
    • 解凍
      system('lha eqw=./test/ test.zip');

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を使う
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>

外部変数名のドット

  • GETやPOST等、外部変数名に"."が含まれていると"_"に変換されてしまいます。

  • http://hoge.php?a.b=c...
    -> var_export($_GET)
    array(
      "a_b" => "c..."
    )
  • PHPマニュアルより

    重要なことを記述しておくと、このため、外部変数に含まれるドットを PHP は自動的にアンダースコアに変換します。

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
    • エラー
      <?
      function foo($str) {
          return $str;
      }
      
      $str = "foo";
      echo foo(&$str);
      ?>
    • 修正
      <?
      function foo(&$str) {
          return $str;
      }
      
      $str = "foo";
      echo foo($str);
      ?>

PHP Notice: Only variables should be assigned by reference in ...

  • php4.4.xからリファレンスのエラーチェックが強化された。
    Notice: Only variable references should be returned by reference in ...
    参照返ししてるのに値で代入したり、値返ししてるのに参照代入すると注意されるようになった。
  • 修正方法
    • エラー箇所を修正する
    • もしくは、E_NOTICE を無視する
      //error_reporting(E_ALL);
      error_reporting(E_ALL & ~E_NOTICE);
  • エラーサンプル1
    error_reporting(E_ALL);
    function foo() {
        return "foo";
    }
    $bar =& foo();
  • エラーサンプル2
    error_reporting(E_ALL);
    function &foo() {
        return "foo";
    }
    $bar = foo();
    
  • php4.4.0 Changes
    • リファレンスによるメモリ破壊問題の修正
    • 関数内で参照代入を行うとsegfaultする(ことがある)の修正

カレントの行番号、ファイル名等を得る

生のHTTP POSTを取得する

バイナリデータをPOSTで受信したい場合等に使用。

  • php.iniで「always_populate_raw_post_data=On」の場合
    $HTTP_RAW_POST_DATA
  • それ以外
    $stdin = fopen("php://input", "rb");
    while (!feof($stdin)) {
    	$buf .= fread($stdin, 8192);
    }
    fclose($stdin);
    

セッションの分散化

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); 

fileudp.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

添付ファイル: fileelfinder.html 1396件 [詳細] fileTwitter.php.patch 1554件 [詳細] filememcachefactory.php 1764件 [詳細] filephpStylist.sh 1074件 [詳細] filejavascript_unescape.inc.zip 1624件 [詳細] filembcs.zip 2014件 [詳細] fileregex_test.php 1729件 [詳細] fileudp.inc.php 1870件 [詳細] fileFilteringAndEscapingCheatSheet.pdff 477件 [詳細] filearray_speed.php 2335件 [詳細] filechasen.php 1970件 [詳細] filegetLocationInformation.php 1927件 [詳細] file.htaccess 1473件 [詳細] fileBaseConvert.inc.zip 2085件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-09-15 (土) 07:31:38 (9d)