Kinopyo Blog

プログラマとしてRuby, Rails, iPhone, iPad,Macなどなどと向き合う日々のログポース

Archive for the ‘PHP5’ Category

PHP プロセス数を指定して実行するマルチスレッド処理(curl_multi)

2011年08月09日

curl_multi系を使って、プロセス数を指定して実行するマルチスレッド処理です。

urlは配列で受け取って、もし指定したプロセス数より多い場合は分割して実行するようになってます。

このサンプルコードではこのブログの幾つかのurlに対してtitleを取得しました。

<?php
/**
* 指定したプロセス数で並列処理を実行する
*
* @param array $url_list URLの配列
* @param boolean $url_as_key 結果配列を返すときに、urlをキーにする
* @param int $timeout タイムアウト秒数 0だと無制限
* @return array 結果配列
*/
function execute($url_list, $url_as_key = false, $timeout=0) {
    // set your process number
    $process = 5;

    $is_over_process = false;
    if ($process < count($url_list)) {
        // chunk url list / process number*
        $url_chunk = array_chunk($url_list, $process);
        $is_over_process = true;
    }

    $ret = array();
        
    if ($is_over_process && !empty($url_chunk)) {

        foreach ($url_chunk as $key => $url_list) {
            echo "chunk start:{$key}\n";
            
            $res = fetch_multi_url($url_list, $url_as_key, $timeout);
            if (!empty($res)) {
                $ret = array_merge($ret, $res);
            } else {
                continue;
            }

        }
    } else if (!$is_over_process && !empty($url_list)){
        $ret = fetch_multi_url($url_list, $url_as_key, $timeout);
    } else {
        echo "url invalid::";
    }
    
    return $ret;
    
}

/**
* curl_multi_execの並列処理
* ほぼboilerplate
*
* @param array $url_list URLの配列
* @param boolean $url_as_key 結果配列を返すときに、urlをキーにする
* @param int $timeout タイムアウト秒数 0だと無制限
* @return array 結果配列
*/
function fetch_multi_url($url_list, $url_as_key, $timeout) {
    $mh = curl_multi_init();
    foreach ($url_list as $i => $url) {
        $ch[$i] = curl_init($url);
        curl_setopt($ch[$i],CURLOPT_RETURNTRANSFER,1);

        //タイムアウト
        if ($timeout){
            curl_setopt($ch[$i],CURLOPT_TIMEOUT,$timeout);
        }

        curl_multi_add_handle($mh,$ch[$i]);
    }

    //URLを取得
    //すべて取得するまでループ
    $active = null;
    do {
        $mrc = curl_multi_exec($mh,$active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);

    while ($active and $mrc == CURLM_OK) {
        if (curl_multi_select($mh) != -1) {
            do {
                $mrc = curl_multi_exec($mh,$active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }

    if ($mrc != CURLM_OK) {
        echo '読み込みエラーが発生しました:'.$mrc;
    }

    //ソースコードを取得
    $res = array();
    foreach ($url_list as $i => $url) {
        if (($err = curl_error($ch[$i])) == '') {
            // url_as_keyがtrueの場合、urlをキーとして格納
            if ($url_as_key) {
                $res[$url] = curl_multi_getcontent($ch[$i]);
            // そうでない場合は、ただ配列に入れる
            } else {
                $res[$i] = curl_multi_getcontent($ch[$i]);
            }
        } else {
            echo '取得に失敗しました:'.$url_list[$i].'<br />';
        }
        curl_multi_remove_handle($mh,$ch[$i]);
        curl_close($ch[$i]);
    }
    curl_multi_close($mh);

    return $res;
}


// 並列実行したいurl list
$url_list = array(
    "http://www.kinopyo.com/blog/ipad-2-not-charging-when-connected-to-pc-usb",
    "http://www.kinopyo.com/blog/the-first-app-i-installed-to-ipad2",
    "http://www.kinopyo.com/blog/chrome-warn-before-quitting-with-command-q-in-mac",
    "http://www.kinopyo.com/blog/reply-to-all-always-in-gmail",
    "http://www.kinopyo.com/blog/lion-fullscreen-shortcut-key-conflict-with-evernote-client",
    "http://www.kinopyo.com/blog/how-to-set-gesture-for-chrome-to-swipe-back-and-forth-in-lion",
    "http://www.kinopyo.com/blog/3-free-ebooks-for-study-coffeescript"
);

// start time
$start_time = microtime(true);

// execute
$res = execute($url_list, true);

// execute time
$time = microtime(true) - $start_time;

// play with the result
// here I just get the page title
$titles = array();
foreach ($res as $url => $html) {
    preg_match('{<title>(.*)</title>}',$html, $match_title);
    $titles[$url] = $match_title[1];
}

echo "Result:\n";
echo "time:{$time} sec\n";
print_r($titles);

参考:PHPでマルチスレッド(バックグラウンド処理)を実現する方法

PHP:必要桁数まで0埋めする

2011年07月22日
// 47 -> 047
sprintf("%03d", 47); 

// or

// parameter: string $input , int $pad_length,
str_pad(47, 3, '0', STR_PAD_LEFT);

str-padについては:http://php.net/manual/en/function.str-pad.php

PEAR HTTP_Requestのサンプルコード

2011年06月08日

仕事で使ったので簡単にサンプルコードをまとめました。

PHP:環境構築時に使う接続テストコードまとめ MySQL/Oracle/Memcache/Memcached

2011年06月03日

環境構築時に接続テスト用のコードをまとめました。

Cakephp XML to Array

2011年05月15日

CakephpでXMLを配列に変換するのはとても簡単です。

下記のファンクションを使えば一発でできます。

uses('Xml');
$xml = new Xml("/path/to/xml");
$xml_array = Set::reverse($xml);

Smartyで文字列を連結

2011年05月11日

こんな感じです。

{"`$foo` plain text `$bar`"}

PHP Fatal error: Call to undefined function mcrypt_decrypt()

2011年04月22日

こちらを参照してください。

PHPを–with-mcrypt[=DIR]再コンパイルする必要があるそうです。またlibmcryptも2.5.6以上のバージョンを求められます。

一般的にもしfunction is undefinedになったら、何かライブラリをコンパイルする必要があるということになります。

sudo apt-get install php5-mcrypt

works on ubuntu.

sudo port install php5-mcrypt

works on mac.

http_build_queryを使うときの注意点:URLパラメータ区切りがエスケープされる(XAMPP要注意)

2011年04月15日

障害

http_build_queryを使ってurlのパラメータを作るときにパラメータがこうなりました。

foo=bar&amp;baz=boo&amp;hoge=hoge

上記のように複数のパラメータがある時に;であるべきのところが&となってしまいました。

これはPHPの設定ファイル、php.iniのarg_separator.outputで制御されてて、XAMPPの場合インストールされたデフォルトでは、「&」となるそうです。

解決方法

なので、php.iniの「arg_separator.output」の値を「&」から「&」に変更する

参考

http_build_queryを使うときの注意点(PHP)

http://www.multiburst.net/sometime-php/2008/12/http_build_query/

PHP: mysqlnd cannot connect to MySQL 4.1+ using old authentication

2011年03月17日

問題

新しい mysqlnd ライブラリは、MySQL 4.1 用の41バイトの新しいパスワードフォーマットを使用します。 古い16バイトのパスワードを使うと、mysql_connect() 系の関数は次のようなエラーメッセージを生成します。”mysqlnd cannot connect to MySQL 4.1+ using old authentication”

http://www.php.net/manual/ja/migration53.incompatible.php

MacPortでインストールしたPHP5.3では、

mysqlnd(php5.3のmysql native client)が適用される。

しかし、CentOSなどのyumでインストールできるMySQLサーバーとの相性がよろしくない。

PHP Warning: mysql_connect(): mysqlnd cannot connect to MySQL 4.1+ using old authentication

というエラーが現れ、接続することができません。

mysqlndを利用しないよう再コンパイルが必要となる。

http://taikimen.blogspot.com/2010/10/snowleopard-php53mysql.html

解決方法

portでインストールしたモジュールを確認、mysqlndがactiveなってるはず。

sudo port installed

php5-mysql @5.3.5_0+mysqlnd (active)

そしてmysql5のvariantsを指定で再インストール。

% sudo port install php5-mysql +mysql5
--->  Computing dependencies for php5-mysql
--->  Fetching php5-mysql
--->  Verifying checksum(s) for php5-mysql
--->  Extracting php5-mysql
--->  Configuring php5-mysql
--->  Building php5-mysql
--->  Staging php5-mysql into destroot
--->  Installing php5-mysql @5.3.5_0+mysql5
--->  Deactivating php5-mysql @5.3.5_0+mysqlnd
--->  Cleaning php5-mysql
--->  Activating php5-mysql @5.3.5_0+mysql5
--->  Cleaning php5-mysql

再度port installedで確認すればmysql5がactiveになるはず。これで解決。

php5-mysql @5.3.5_0+mysqlnd
php5-mysql @5.3.5_0+mysql5 (active)

参考

【php】mysqlndを使うとMySQLに接続できない

http://www.softel.co.jp/blogs/tech/archives/2225

SnowLeopard + PHP5.3でのMySQLリモート接続

http://taikimen.blogspot.com/2010/10/snowleopard-php53mysql.html

PHP: mysqlnd cannot connect to MySQL 4.1+ using old authentication

http://www.bitshop.com/Blogs/tabid/95/EntryId/67/PHP-mysqlnd-cannot-connect-to-MySQL-4-1-using-old-authentication.aspx

おまけ

mysqlが古い16バイトのパスワードを使ってるかを確認する方法です。

mysqlにログインして下記コマンドを実行:

mysql> select password('aa');

+------------------+
| password('aa')         |
+------------------+
| 0123456789abcdef |
+------------------+

16位だっだら古いです。40位なら新しいってことです。

CakePHP, and Strict Standards

MacportでPHPをインストールし、CakePHPを動かしたら「Strict Standards」エラーが出ました。

当時のエラー本文は残ってませんので、Googleで検索したエラー本文を貼り付けます。パス以外は同じのはずです。

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/basics.php on line 279
Strict Standards: Redefining already defined constructor for class Object in /Applications/MAMP/htdocs/xxxx/cake/libs/object.php on line 65
Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/object.php on line 92
Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/inflector.php on line 65
Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/configure.php on line 96
Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/configure.php on line 154
Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/cache.php on line 71
Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/cache.php on line 157
Strict Standards: Non-static method Configure::getInstance() should not be called statically in /Applications/MAMP/htdocs/xxxx/cake/bootstrap.php on li

解決方法

これはCakePHPの問題ではなく、PHPのerror_reportingの設定問題だそうです。

php.iniを開いてerror_reportingで検索します。

値をE_ALLに変更すれば解決です。

ちなみにMacportでPHPをインストールしたときのphp.iniパスは/opt/local/etc/php5/php.iniになります。

参考リンク

http://oldblog.awpny.com/2007/12/mamp-php5-cakephp-and-strict-standards/