2009年11月3日火曜日
PHPで記述されたプログラムをcronで定期的に実行する方法
TwitterとGoogle Mapを活用したウェブアプリ(http://www.communitycast.jp/)、Twitterとパノラマを活用したウェブアプリ(http://www.francis-hope.jp/lab/panorama_tweet/)では、ウェブサーバーに設置したPHPプログラムでTwitterの投稿を定期的に取得し、MySQLに投稿内容を格納している。PHPと言うと、クライアント側のウェブブラウザからGet、Postでアクセスする際に使われるケースが多いが、サーバー側でのプログラムとしても利用することができる。その方法を以下に紹介しよう。
ウェブサーバーに設置したプログラムは以下の通りだ。ファイル名はabc.phpとしよう。
ユーザー名、パスワード、IPアドレスは*とさせて頂いた。
ここで重要なのは、1行目の #!/usr/local/Zend/Core/cgi-bin/php -q だ。※サーバー環境に応じてディレクトリは変更してください。
通常は2行目以降のようなPHPを記述していると思うが、サーバーでcronから実行させるためには1行目を追加する必要がある。このあたりは、shellプログラムのファイルの1行目にプログラムへのパスを記述するのと同じ感覚だ。
続いて、cronの設定方法。
上記コマンドをlinuxのコマンドプロンプトで実行する。/etc/cron.dディレクトリ配下にabcというファイルが生成される。ファイルの中身は */2 * * * * root /usr/local/Zend/Core/cgi-bin/php /abc.php となる。2分置きにrootユーザーで/abc.phpというプログラムを実行するという意味だ。ディレクトリ、実行ユーザー、時刻、または時間間隔の設定は必要に応じて変更してください。
ウェブサーバーに設置したプログラムは以下の通りだ。ファイル名はabc.phpとしよう。
#!/usr/local/Zend/Core/cgi-bin/php -q
<?php
$mysqlDatabase = "***.***.***.***";
$mysqlUsername = "***";
$mysqlPassword = "******";
$databaseName = array("***");
$enc_disp = "UTF-8";
$enc_db = "UTF-8";
// データの文字コードを変換する関数
function cnv_enc($string, $to, $from) {
$det_enc = mb_detect_encoding($string, "auto");
if ($det_enc and $det_enc != $to) {
return mb_convert_encoding($string, $to, $det_enc);
} else {
return $string;
}
}
// MySQLへ接続する
$link = mysql_pconnect($mysqlDatabase, $mysqlUsername, $mysqlPassword) or die("データベースへの接続に失敗しました。");
// MySQLへの接続をUTF-8に設定する
mysql_query("SET NAMES UTF8", $link);
// MySQLデータベースを選択する
mysql_select_db($databaseName[0], $link) or die("データベースの選択に失敗しました。");
// MySQLクエリを生成する
$q1 = "SELECT MAX(ID) AS MAX_ID FROM TWEET_PANORAMA";
// MySQLクエリを実行する
$r1 = mysql_query($q1, $link) or die("クエリの実行に失敗しました。SQL:".$q1);
$maxId = 1;
if (mysql_num_rows($r1) > 0) {
$row = mysql_fetch_object($r1);
$maxId = $row->MAX_ID + 1;
}
mysql_free_result($r1);
$user = "******";
$pwd = "******";
// Twitterに問い合わせる
$ch = curl_init();
if ($maxId < 4000000000) { $host = "http://twitter.com/statuses/friends_timeline.xml?count=100"; } else { $host = "http://twitter.com/statuses/friends_timeline.xml?since_id=".$maxId."&count=100"; } curl_setopt($ch, CURLOPT_URL, $host); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_USERPWD, "$user:$pwd"); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); $result = curl_exec($ch); curl_close($ch); $xml = simplexml_load_string($result) or die("XMLパースエラー"); // 値を参照する foreach ($xml->status as $status) {
$CREATED_AT = sprintf('%s', mysql_real_escape_string(cnv_enc($status->created_at, $enc_db, $enc_disp), $link));
$ID = sprintf('%s', mysql_real_escape_string(cnv_enc($status->id, $enc_db, $enc_disp), $link));
$TEXT = sprintf('%s', mysql_real_escape_string(cnv_enc($status->text, $enc_db, $enc_disp), $link));
$USER_ID = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->id, $enc_db, $enc_disp), $link));
$USER_NAME = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->name, $enc_db, $enc_disp), $link));
$USER_SCREEN_NAME = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->screen_name, $enc_db, $enc_disp), $link));
$USER_PROFILE_IMAGE_URL = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->profile_image_url, $enc_db, $enc_disp), $link));
$USER_DESCRIPTION = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->description, $enc_db, $enc_disp), $link));
// MySQL文を生成する
$q4 = "INSERT INTO TWEET_PANORAMA (";
$q4 .= "CREATED_AT, ";
$q4 .= "ID, ";
$q4 .= "TEXT, ";
$q4 .= "USER_ID, ";
$q4 .= "USER_NAME, ";
$q4 .= "USER_SCREEN_NAME, ";
$q4 .= "USER_PROFILE_IMAGE_URL, ";
$q4 .= "USER_DESCRIPTION";
$q4 .= ") VALUES (";
$q4 .= "'".$CREATED_AT."', ";
$q4 .= "'".$ID."', ";
$q4 .= "'".$TEXT."', ";
$q4 .= "'".$USER_ID."', ";
$q4 .= "'".$USER_NAME."', ";
$q4 .= "'".$USER_SCREEN_NAME."', ";
$q4 .= "'".$USER_PROFILE_IMAGE_URL."', ";
$q4 .= "'".$USER_DESCRIPTION."'";
$q4 .= ")";
// MySQL文を実行する
$r4 = mysql_query($q4, $link) or die("クエリの実行に失敗しました。SQL:".$q4);
}
?>
<?php
$mysqlDatabase = "***.***.***.***";
$mysqlUsername = "***";
$mysqlPassword = "******";
$databaseName = array("***");
$enc_disp = "UTF-8";
$enc_db = "UTF-8";
// データの文字コードを変換する関数
function cnv_enc($string, $to, $from) {
$det_enc = mb_detect_encoding($string, "auto");
if ($det_enc and $det_enc != $to) {
return mb_convert_encoding($string, $to, $det_enc);
} else {
return $string;
}
}
// MySQLへ接続する
$link = mysql_pconnect($mysqlDatabase, $mysqlUsername, $mysqlPassword) or die("データベースへの接続に失敗しました。");
// MySQLへの接続をUTF-8に設定する
mysql_query("SET NAMES UTF8", $link);
// MySQLデータベースを選択する
mysql_select_db($databaseName[0], $link) or die("データベースの選択に失敗しました。");
// MySQLクエリを生成する
$q1 = "SELECT MAX(ID) AS MAX_ID FROM TWEET_PANORAMA";
// MySQLクエリを実行する
$r1 = mysql_query($q1, $link) or die("クエリの実行に失敗しました。SQL:".$q1);
$maxId = 1;
if (mysql_num_rows($r1) > 0) {
$row = mysql_fetch_object($r1);
$maxId = $row->MAX_ID + 1;
}
mysql_free_result($r1);
$user = "******";
$pwd = "******";
// Twitterに問い合わせる
$ch = curl_init();
if ($maxId < 4000000000) { $host = "http://twitter.com/statuses/friends_timeline.xml?count=100"; } else { $host = "http://twitter.com/statuses/friends_timeline.xml?since_id=".$maxId."&count=100"; } curl_setopt($ch, CURLOPT_URL, $host); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_USERPWD, "$user:$pwd"); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); $result = curl_exec($ch); curl_close($ch); $xml = simplexml_load_string($result) or die("XMLパースエラー"); // 値を参照する foreach ($xml->status as $status) {
$CREATED_AT = sprintf('%s', mysql_real_escape_string(cnv_enc($status->created_at, $enc_db, $enc_disp), $link));
$ID = sprintf('%s', mysql_real_escape_string(cnv_enc($status->id, $enc_db, $enc_disp), $link));
$TEXT = sprintf('%s', mysql_real_escape_string(cnv_enc($status->text, $enc_db, $enc_disp), $link));
$USER_ID = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->id, $enc_db, $enc_disp), $link));
$USER_NAME = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->name, $enc_db, $enc_disp), $link));
$USER_SCREEN_NAME = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->screen_name, $enc_db, $enc_disp), $link));
$USER_PROFILE_IMAGE_URL = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->profile_image_url, $enc_db, $enc_disp), $link));
$USER_DESCRIPTION = sprintf('%s', mysql_real_escape_string(cnv_enc($status->user->description, $enc_db, $enc_disp), $link));
// MySQL文を生成する
$q4 = "INSERT INTO TWEET_PANORAMA (";
$q4 .= "CREATED_AT, ";
$q4 .= "ID, ";
$q4 .= "TEXT, ";
$q4 .= "USER_ID, ";
$q4 .= "USER_NAME, ";
$q4 .= "USER_SCREEN_NAME, ";
$q4 .= "USER_PROFILE_IMAGE_URL, ";
$q4 .= "USER_DESCRIPTION";
$q4 .= ") VALUES (";
$q4 .= "'".$CREATED_AT."', ";
$q4 .= "'".$ID."', ";
$q4 .= "'".$TEXT."', ";
$q4 .= "'".$USER_ID."', ";
$q4 .= "'".$USER_NAME."', ";
$q4 .= "'".$USER_SCREEN_NAME."', ";
$q4 .= "'".$USER_PROFILE_IMAGE_URL."', ";
$q4 .= "'".$USER_DESCRIPTION."'";
$q4 .= ")";
// MySQL文を実行する
$r4 = mysql_query($q4, $link) or die("クエリの実行に失敗しました。SQL:".$q4);
}
?>
ユーザー名、パスワード、IPアドレスは*とさせて頂いた。
ここで重要なのは、1行目の #!/usr/local/Zend/Core/cgi-bin/php -q だ。※サーバー環境に応じてディレクトリは変更してください。
通常は2行目以降のようなPHPを記述していると思うが、サーバーでcronから実行させるためには1行目を追加する必要がある。このあたりは、shellプログラムのファイルの1行目にプログラムへのパスを記述するのと同じ感覚だ。
続いて、cronの設定方法。
echo "*/2 * * * * root /usr/local/Zend/Core/cgi-bin/php /abc.php" > /etc/cron.d/abc
上記コマンドをlinuxのコマンドプロンプトで実行する。/etc/cron.dディレクトリ配下にabcというファイルが生成される。ファイルの中身は */2 * * * * root /usr/local/Zend/Core/cgi-bin/php /abc.php となる。2分置きにrootユーザーで/abc.phpというプログラムを実行するという意味だ。ディレクトリ、実行ユーザー、時刻、または時間間隔の設定は必要に応じて変更してください。
ご質問のある方は気楽に問い合わせてください。
有限会社フランシスホープ 岡田 治
okadao@francis-hope.jp
パノラマの撮影制作サービスのフランシスホープ
Follow okadao on Twitter
有限会社フランシスホープ 岡田 治
okadao@francis-hope.jp
パノラマの撮影制作サービスのフランシスホープ
Follow okadao on Twitter
2009年10月6日火曜日
javascriptで数値を3桁区切りで表示する方法
ネットショップなどで金額を3桁毎にカンマで区切って表示させる場合があります。他方、消費税、合計金額の計算も必要で、DBにカンマ付きの文字列として格納することにも計算時にカンマを取り除かねばならないという不便さがあります。DBにはカンマ区切りのない数値として格納し、ブラウザ側のjavascriptやサーバー側のjava、phpでは数値として計算に使用し、ブラウザでjavascriptを用いて表示させる時にのみ3桁区切りすることが適切かと思います。
ところで、javascriptで数値を3桁区切りする場合、下記のとおり、正規表現というのを用いて行うのが簡単です。
function addFigure(str) {
var num = new String(str).replace(/,/g, "");
while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
return num;
}
var num = new String(str).replace(/,/g, "");
while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
return num;
}
上記プログラムを解説します。
var num = new String(str).replace(/,/g, "");
は、str文字列のカンマ(,)をすべて""で置き換え、その結果をnumに代入するというコードです。replace(",", "")だとstr文字列中の最初のカンマ(,)のみを取り除くことができます。正規表現で記述すると、replace(/,/, "")です。str文字列の全てのカンマ(,)を取り除くには、gオプションをつけて、replace(/,/g, "")と記述します。while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
続いて、num.replace(/^(-?\d+)(\d{3})/, "$1,$2")部分を解説します。正規表現では最初の「()」と次の「()」の値を$1、$2で取得することができます。^(-?/d+)でnumの前からの数字を取得し、後で$1として参照できます。(\d{3})でnumの後ろから3桁分の数字を取得し、後で$2として参照できます。なお、^(-?/d+)の部分は、numの後ろから3桁分として(\d{3})で切り出された部分を除いた数字が入ります。また、/^(-?\d+)(\d{3})/は元のnumが抽出されます。
例えばnum="123456789"の場合、$1には"123456"、$2には"789"が入ります。/^(-?\d+)(\d{3})/は"123456789"です。
/^(-?\d+)(\d{3})/の値と"$1,$2"が交換されることで、num.replace(/^(-?\d+)(\d{3})/, "$1,$2") = "123456,789"となります。
while(num != (num = ... ))の部分で、numが"123,456,789"となるまで繰り返します。
return num;
で、関数の呼び出し元に3桁区切りされた文字列が戻り値として返されます。
ご質問のある方は気楽に問い合わせてください。
有限会社フランシスホープ 岡田 治
okadao@francis-hope.jp
パノラマの撮影制作サービスのフランシスホープ
Follow okadao on Twitter
有限会社フランシスホープ 岡田 治
okadao@francis-hope.jp
パノラマの撮影制作サービスのフランシスホープ
Follow okadao on Twitter
登録:
投稿 (Atom)