PHP: バージョンアップできなくて使えない関数がある時の対応
2012年04月20日 16時03分
PHPがバージョンアップされて関数が増えたがサービスを停止するわけにもいかずPHPのバージョンアップができず使用できない。
こんな状況はないだろうか。
俺の場合は具体的にjson_decodeが使いたい。
でないとFacebookのSDKがFacebook needs the JSON PHP extensionってエラーが出て使用できない。
なんとかしたいなぁと思っていたらupgradephpというライブラリを発見した。
upgradephp
http://include-once.org/p/upgradephp/
バージョンアップされて追加された関数が定義されていない場合、追加されるという代物。
これインクルードしてからFacebookのSDKをインクルードしたらjson_decodeが定義されて問題なく処理できた。
こんなんあったんかぁ、素晴らしい。
ついでにFacebookが返すマルチバイト文字形式の\uxxxx形式が文字化けするので以下の関数をjson_decodeする前に通す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
// UTF-8文字列をUnicodeエスケープする。ただし英数字と記号はエスケープしない。 function unicode_encode($str) { return preg_replace_callback("/((?:[^\x09\x0A\x0D\x20-\x7E]{3})+)/", "encode_callback", $str); } function encode_callback($matches) { $char = mb_convert_encoding($matches[1], "UTF-16", "UTF-8"); $escaped = ""; for ($i = 0, $l = strlen($char); $i < $l; $i += 2) { $escaped .= "\u" . sprintf("%02x%02x", ord($char[$i]), ord($char[$i+1])); } return $escaped; } // Unicodeエスケープされた文字列をUTF-8文字列に戻す function unicode_decode($str) { return preg_replace_callback("/\\\\u([0-9a-zA-Z]{4})/", "decode_callback", $str); } function decode_callback($matches) { $char = mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UTF-16"); return $char; } |
facebook:fan pageのウォールに投稿された画像を一覧表示する
2012年04月16日 11時07分
ファンページのウォールに投稿した画像を自分のサイトに表示したいという要望があった。
上記ぐらいだったらSDK使わずに直にGraph APIのURL叩く方式で問題なく実装できたのでそのメモ。
アルバム一覧取得のAPI URL
http://graph.facebook.com/[ファンページID]/albums/
上記のURLを叩くとアルバム一覧がJSON形式で帰ってくるのでその一覧の中でtype属性がwallのデータのアルバムIDを取得する。
|
$album_list_cont = file_get_contents("http://graph.facebook.com/[ファンページID]/albums/"); $js = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); $albums_arr = $js->decode($album_list_cont); if (!empty($albums_arr["data"])) { foreach($albums_arr["data"] as $crt_album) { if ($crt_album["type"] == "wall") { // ウォールに投稿されたデータ // $crt_album["id"]にアルバムIDが入っているので保持しておく } } } |
※PHPのバージョンが古いためjson_decodeが使えないのでPearのライブラリを使用している
次はalbumから画像を取得する手順。
アルバム一覧取得のAPI URL
http://graph.facebook.com/[アルバムID]/photos?limit=25&offset=0&fields=images
上のURLを叩くと画像一覧が取得できる。
offsetやfieldsパラメータは適せん変更するべし。
一回で取得できなかった場合は[paging][next]というパラメータに続きを取得するパラメータが入ってくるので拾うこと。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
$photos_cont = file_get_contents("http://graph.facebook.com/[アルバムID]/photos?limit=25&offset=0&fields=images"); $photos_arr = $js->decode($photos_res); $next_page_url = "first url"; while ($next_page_url != "") { $next_page_url = ""; foreach($photos_arr as $crt_photo_key => $crt_photo_val) { switch ($crt_photo_key) { case "paging": $next_page_url = isset($crt_photo_val["next"]) ? $crt_photo_val["next"] : ""; break; case "data": $crt_image_arr = get_image_infos($crt_photo_val, $thumb_size_set); $image_arr = array_merge($image_arr, $crt_image_arr); break; default: break; } } if ($next_page_url != "") { $photos_res = file_get_contents($next_page_url); $photos_arr = $js->decode($photos_res); } } // とりあえずブラウザ表示 for ($img_idx = 0 ; $img_idx < count($image_arr) ; $img_idx ++) { echo "<img src='{$image_arr[$img_idx]['source']}' />\n"; } |
サンプルURL
http://www.crossl.net/blog/pg_sample/fb_album_image/wall_images.php
※うちの会社のブランドです。
別にアルバムを作ってしまうとtypeがwallではなくnormalになるのでこの方法では取得できない。
あくまでアルバムwallの画像一覧になる。
Webの資料を調べるけど結局は本家が一番わかりやすいという罠。(英語ですが…)
Graph API参考
http://developers.facebook.com/docs/reference/api/album/
PHP:csvファイルの読み込みでfgetcsvを使用すると文字化けする対応
2012年03月23日 12時56分
phpにはcsvを読み込むfgetcsvという標準関数があるがマルチバイト系の処理に難がある。
ちょっとググってみるだけでもかなりの情報が出てくるので日本語を含むcsvを読み取るには使用しない方が無難。
じゃあどうするか、自分で作るかなぁとしぶしぶ手をキーボードにやりかけた所、
やっぱり思うところはみんな一緒らしく先人の方が素晴らしい関数を作成して公開してくださっている。
yossy.blog / PHP5でfgetcsvが正常に動作しない
http://yossy.iimp.jp/wp/?p=56
ここに記載されているfgetcsv_regをfgetcsvの変わりに呼び出せば万事OK。
phpで外部コマンド実行(shell_exec)が上手くいかなかった時のメモ
2012年02月27日 13時54分
社内サーバでmailqを管理する簡易的なWebアプリを作っててはまったのでメモ。
目的
メールの即時配信をやめ、キューに溜めてWeb経由で閲覧・配信・削除をできるようにする。
CentOS / postfix
手順
-
1)postfixの設定(/etc/postfix/main.cf)に以下を追加してsmtpでの配信を即時配信ではなくメールキューに溜めるように設定。
-
-
2)phpでmailqueueの設定一覧を取得
-
|
$queue_list = shell_exec(escapeshellcmd(""/usr/sbin/postqueue -p"")) |
こちらはなんの問題もなく動いた
-
3)phpでmailqueueにあるメールを削除
-
|
$del_msg = shell_exec(escapeshellcmd("postsuper -d [キューID]")) |
こちらはさっぱり動かない。
戻り値も空なのでどうしたものか、、、とりあえず関数をsystemやpassthruに変えてみたけど変化なし。
標準エラー出力が取れていないのではと思い調べてみると後ろに”2>&1″を付けることで標準エラー出力も標準出力に吐き出せるので試してみる。
|
$del_msg = shell_exec(escapeshellcmd("postsuper -d [キューID] 2>&1")) |
これでもメッセージは何もでない。
コマンド自体間違っていないか実行したコマンドをechoしてターミナルから実行してみると正常に動作して消せる。
となると権限周りが怪しくなるのでsudoしてみることに。
|
$del_msg = shell_exec(escapeshellcmd("sudo postsuper -d [キューID] 2>&1")) |
とやっても何も動かない。
自分しか使っていないローカルマシンなのでセキュリティなど無視して以下に設定してみても駄目。
|
$: visudo #ADD apache ALL=(ALL) NOPASSWD: ALL |
しかし上記を追加してからエラーメッセージが表示されるようになった。
以下のようなもの。
|
sorry, you must have a tty to run sudo |
これでググってみるとvisudoで以下の行をコメントアウトすることにより解決するようだった。
|
$:vi /etc/sudoers Defaults requiretty ↓ #Defaults requiretty |
上で見事に解決。
無事にコマンドが実行されメールキューのメールが削除できました。
※自PC内のVMだからやりたい放題やっていますが外部サーバ等の場合はこの記事の内容はセキュリティ上問題が多いのでおすすめしません。
PHP DomDocumentがインストールできない為Simple XML に書き直す場合
2011年12月14日 19時01分
XMLを出力するためにDomDocumentを使用して作成していたのだが開発環境にはライブラリが入っていたが本番環境には’–disable-dom’オプションが付いていてDomDocumentが使えない。
ライブラリをインストールする場合はapache再起動が必要になるため商用リリースしている場合は勿論許可が出にくい。
そんな状況に自分が陥ったのでSimple XMLに書き直した時のメモ。
XML定義
DomDocument
|
$dom = new DomDocument("1.0"); $dom->encoding = "UTF-8"; $dom->formatOutput = true; $idea_mail_mag_data = $dom->appendChild($dom->createElement("aaaa")); |
↓
Simple XML
|
$xml_root = '<?xml version="1.0" encoding="UTF-8"?><aaaa></aaaa>'; $xml = simplexml_load_string($xml_root); |
子供追加・属性設定
DomDocument
|
//aaaaにbbbbノード追加 $bbbb_node = $idea_mail_mag_data->appendChild($dom->createElement("bbbb")); //bbbbノードに属性flagを追加 $bbbb_node->setAttribute("flag", "1"); //テキストノード追加 $bbbb_node->appendChild($dom->createTextNode("ほげ")); //CDATAで括る場合 $bbbb_node->appendChild($dom->createCDATASection("ほげ")); |
↓
Simple XML
|
//aaaaにbbbbノード追加 $bbbb_node = $xml->addChild('bbbb'); //bbbbノードに属性flagを追加 $bbbb_node->addAttribute('flag', '1'); //テキストノード追加 $xml->addChild('bbbb', 'ほげ'); //CDATAで括る場合(対応関数がないので直書きする $xml->addChild('bbbb', '<![CDATA[ほげ]]>'); |
後はXML形式に出力。
DomDocumentの場合はただ関数を1つ呼び出すだけでよい。
DomDocument
Simple XMLの場合はどうやってもCDATASectionの対応がライブラリ側だけではエスケープされてしまい誤動作するので以下に記述されていた関数をかます等して外部で対応するしかない。
http://students.kiv.zcu.cz/doc/php5/manual/cs/ref.simplexml.php.html
Simple XML
|
function fixCDATA($string) { $find[] = '<![CDATA['; $replace[] = '<![CDATA['; $find[] = ']]>'; $replace[] = ']]>'; return $string = str_replace($find, $replace, $string); } // XML出力 echo fixCDATA($xml->asXml()); |
本番の動作環境はよく調べましょうというお話。