当然ながら、言語ごとに真偽判定(true/false)の基準が違います。
特にスクリプト系の言語では、明示的に型を指定しないことが多いので、たまに問題になります。
たまたま手元にあった環境で、どんな値が真に判定されるのか、というのをまとめてみました。
新しい言語に突撃するときのメモ代わりにでもして頂ければ幸いです。
検証コードイメージ
a = 0
if a
print 'true'
else
print 'false'
end

凡例:
× は、コンパイルエラー
ー は、言語仕様にその値が存在しない
備考:
*”" というのは、ナル文字の値を指す(\0なので、実体はゼロという整数値)
array[] というのは、各言語での空の配列を指す
※1 C言語にfalseは存在しない
※2 配列のアドレスを指すため、真と評価される
※3 noticeが発生するが、設定や@で抑制可能
こうしてみると、やはりPHPは変態です。’0′ をfalseと判定する言語はあまりないですね。Webに特化しているのがよくわかります。$_GETなどは文字列で渡ってくるので、確かに手抜きに便利仕様です。
空配列をfalseと判定するのが、PythonとPHPというなんだかおもしろい組み合わせになりました。
良く忘れるけど、rubyはゼロという数字をtrueに判定するので注意が必要ですね。
結局、ミスのしようが無い Java / C# は安全で好きです。
また、ゼロは false、ほかは true と割り切ったC言語も、シンプルで好きです。
PHPでXML-RPCサーバを作るには、IXRのライブラリが簡単です。
PEAR::XML_RPC2も良いですが、こっちの方がCakePHPで使うには良さそうですね。
以下のページで、CakePHPでの使い方もまとまっています。
http://bakery.cakephp.org/articles/view/how-to-create-an-xml-rpc-server-with-cakephp
基本的に、インデックスアクションでレシーバを登録するだけで、後は各アクションでPHPのオブジェクトをreturnできます。
あまりに簡単すぎて、基本的なことを調べるのがめんどくさくなります。
たとえば、base64やdateTimeで囲んだ値を返したいときはどうしたら良いでしょうか?
このようにやればOKです。
function _hogeAction($data) {
return new IXR_Base64($bytedata);
}
function _piyoAction($data) {
return new IXR_Date(time());
}
Base64は、内部でbase64_encodeが呼ばれるので、バイトデータを直接渡すようにします。
dateは、タイムスタンプ値かISO形式を渡します。
dateのパースは、あまり柔軟性は無いので気をつけてください。
function parseIso($iso) {
$this->year = substr($iso, 0, 4);
$this->month = substr($iso, 4, 2);
$this->day = substr($iso, 6, 2);
$this->hour = substr($iso, 9, 2);
$this->minute = substr($iso, 12, 2);
$this->second = substr($iso, 15, 2);
}
CakePHPでfindする際、belongsToしているオブジェクトを条件にすることができます。
//例:datas → categories で、dataはcategoryに属している(data belongsto category)
$datas = $this->Data->find('all', array(
'conditions' => array('Category.id' => 5)
));
しかし、hasManyしているものに関しては、そのまま実行すると unknown column と怒られてしまいます。
hasManyでは、デフォルトでJOINされないためです。
hasAndBelongsToManyでも、同じことが発生します。
これを回避するには、明示的なJOINを実行する必要があります。
たとえば、データが複数のカテゴリに属するように、data hasandbelongstomany category にした場合、以下のように指定します。
//例:datas← categories_datas→ categories で、
//hasAndBelongsToManyしている
$datas = $this->Data->find('all', array(
'joins' => array(array(
'type' => 'LEFT',
'alias' => 'CategoriesData',
'table' => 'categories_datas',
)),
'conditions' => 'CategoriesData.data_id = Data.id'
));
joinsは配列なので、いったん取得して[]演算子で追加するか、このように最初から二重の配列で指定してあげる必要があります。
(もちろん、既存のJOINを消してしまわないかチェックしつつ)
ところで、hasAndBelongsToManyでググると、途中で「破産」がたっぷり出てきた後、↓のようになって若干悲しくなりますね・・・

hasAndBelongsToManyで検索する途中
伊藤です。
Linux/Mac上で開発されていたコードをWindows上でXAMPP(Apache, MySQL, PHP)を使って動かそうとしたところ、動かないコードがありました。
それはファイル操作のrenameです。
windowsではファイルオープン中にrenameやunlinkでファイルをリネームしたり、削除したりすることができないようです。
Rubyのメーリングリストでも、話題になっていました。(PHPとは関係ないですが、プラットフォームの問題だと思いますので同じでしょう)
http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=view;name=Windows+%A4%CE+IO
対策としては、きちんとcloseしてからrename, unlinkすればOKでした。
また、Windowsでは、rename(old, new)としたときにnewのパスに既にファイルが存在していると、
エラーになるという報告もありますので、併せて気をつけたいですね。
http://ml.php.gr.jp/pipermail/php-users/2005-October/027828.html
UNIX互換OSばかり使っていると、Windowsでの開発のハマりどころを忘れてしまいそうです^^;
ではでは
WordPressはXML-RPC対応で、地味に色々な対応プログラムが出ていますね。
XML-RPCのライブラリを使ってAPIをたたけば、たいていの操作はできますが、
お手軽に使うならライブラリを使いたいです。
PHPのライブラリでは、↓のものがシンプルにまとまっていて使いやすかったです。
http://sourceforge.jp/projects/wpapiclient1/
ただし、WordPress 2.9.2 + PHP5.3 で試したところ、
日付がおかしくなる(1999年11月になってしまう)問題が発生したため、以下のように修正しました。
wordpress/core/Util.class.php
static function createDateTime($timestamp)
{
$timestamp = date('Ym\TH:i:s', $timestamp); //'c' を 'Ymd\TH:i:s' に置換する
xmlrpc_set_type($timestamp, 'datetime');
return $timestamp;
}
date()の結果の違いが原因です。
‘c’ → 20100510T10:00:00+09:00
‘Ymd\TH:i:s’ → 20100510T10:00:00
このように、「c」だとタイムゾーンを表す値が入ってしまいます。
date関数
しかし、XML-RPC で dateTime.iso8601 形式を使う場合、タイムゾーンの指定はできない仕様のため、不正な日時と見なされてしまうようです。
Ymd\TH:i:s のように手動で指定することで、正しいフォーマットに指定できますね。
伊藤です。
サーバで動いているWordPressをローカルで再現して、テーマを編集したいときのやりかたを紹介します。
ローカルはWindows+XAMPPを想定していますが、基本的にapacheとmysqlを使っているならとくにどんな環境でもいけそうです。
- ファイル一式をサーバから持ってくる。これはtarで固めてscpなどでよいでしょう。
- サーバのデータベースデータを持ってくる。mysqldumpやphpMyAdminのエクスポートなどを使いましょう。
- ローカルのMySQLにデータベースを作る(wp-config.phpを参考に)
- ローカルのMySQLにユーザを作る(wp-config.phpを参考に)
- ローカルのMySQLにサーバのデータベースデータを流しこむ。 mysql -u root < serverdata.sql
- ローカルのphpMyAdminでwp_optionsテーブルのsiteurl, homeを編集する(ローカルで運用したいURLに変更)
- ローカルのApacheでDocumentRootやAliasを設定する
基本的にはこれでOKでした。
コマンド作業などをもうすこし補足しておきます。
サーバ上のファイルを固めてダウンロード
$ sudo tar cvzf /home/myself/blog.tar.gz /path/to/blog
blog.tar.gzのダウンロードはWinSCPなどを使うとよいでしょう。
サーバのデータベースデータをもってくる
$ mysqldump -u root wordpress > /home/myself/blog.sql
MySQLのrootパスワードをきちんと設定している場合は-pオプションをつけて入力します。
MySQLのrootを使えない場合はwp-config.phpを参考に、wordpress用ユーザでDBを指定して出力させます。
$ mysqldump -u USER -p DATABASE > /home/myself/blog.sql
Enter password: (PASSWORD)
blog.sqlのダウンロードはWinSCPなどを使うとよいでしょう。
ローカルのMySQLにDB, ユーザを作る
コマンドプロンプトでxamppのmysqlを起動しましょう。
この例ではmysql.exeまでの絶対パスを記述していますが、環境に合わせてこのパスを書き換えてください。
> C:\Users\tomotaka\Documents\xampp\mysql\bin\mysql -u root
mysql> CREATE DATABASE `(DB名)`;
mysql> GRANT ALL ON `(DB名)`.* TO '(ユーザ名)'@localhost IDENTIFIED BY '(パスワード)';
mysql> \q
これでデータベースとユーザができましたね。
あとはサーバ上の記事データを流し込みましょう。
ローカルのMySQLにデータを流し込む
> C:\Users\tomotaka\Documents\xampp\mysql\bin\mysql -u root < C:\Users\tomotaka\Documents\blog.sql
簡単です。
phpMyAdminでwp_optionsを編集
- phpMyAdminに入る
- wordpressのDBを選択する(流しこみが成功してればある)
- wp_optionsのテーブルを選択して、表示する
- option_nameカラムがsiteurlの行のエンピツマークをクリックして編集モードになる
- サーバで運用してたブログのアドレスが入っているが、ローカルで使うアドレスに書きかえる
- option_nameカラムがhomeの行のエンピツマークをクリックして編集モードになる
- サーバで運用してたブログのアドレスが入っているが、ローカルで使うアドレスに書きかえる
こんなかんじ。
以上です!
みなさんの快適なWordPress生活のお役に立てば幸いです。
Webサービスにたくさんリクエストを投げるとき、1つ1つレスポンスを待っていると遅いので、同時に処理した方が良いですね。
(そもそも、WebサービスでAPIをたたく回数は最小限にするべきですが)
PHPならcurl_setoptをつかえば良さそうです。
http://php.net/manual/ja/function.curl-multi-add-handle.php
$mh = curl_multi_init();
$ch = array();
foreach ($urls as $index => $url) {
$ch[$index] = curl_init();
curl_setopt($ch[$index], CURLOPT_URL, $uri);
curl_setopt($ch[$index], CURLOPT_HEADER, $header);
curl_setopt($ch[$index], CURLOPT_RETURNTRANSFER, 1);
curl_multi_add_handle($mh, $ch[$index]);
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while($running > 0);
$result = array();
foreach($ch as $curl) {
$result[] = curl_multi_getcontent($curl);
curl_multi_remove_handle($mh, $curl);
}
curl_multi_close($mh);
rubyなら、素直にスレッドを使うのが簡単そうです。
require 'uri'
require 'net/http'
threads = []
datas.each do |data|
threads << Thread.new do
#dataを使ったHTTP処理
end
end
threads.each do |th|
th.join
end
CakePHPのAuthコンポーネントで、ログイン後のアクションを指定するには、
//app_controller::beforeFiler()あたり
$this->Auth->loginRedirect(array('controller' => 'users', 'action' => 'index'));
といったことをしますが、セッションの状態によって、動作しないことがあります。
安全にやるなら、
//app_controller::beforeFitler()あたり
$this->Auth->autoRedirect = false;
//ログインアクション
$this->redirect('users', 'index');
のようにやるのが良さそうです。
CakePHPの基本ですが、modelのbeforeSaveは大変便利です。
たとえば、「最終更新ユーザID」を保存するときは、
//app/app_controller.php
class AppController extends Controller {
public function beforeFilter() {
Configure::write('logined_user_id', $this->Auth->user('id');
}
}
//app/models/hoge_model.php
class HogeModel extends AppModel {
public function beforeSave() {
$this->data[$this->alias]['user_id'] = Configure::read('logined_user_id');
return true;
}
}
たったこれだけですし、応用も利きますね。
なお、モデルから他のモデルを使う際は、以下のように明示的にnewしておく必要があります。
class HogeModel extends AppModel {
public function beforeSave() {
App::import('Model', 'PiyoModel');
$PiyoModel = new PiyoModel();
//$PiyoModel->find('all'); などできる
}
}
hasManyやbelongsToのassociationが設定されている場合は、この手続きは不要なので、設定しておいてContainableで外すというのも楽かもしれません。
HTMLヘルパーでリンクを張る際、
$html->link('りんく!', '/pages/index');
などとやりますが、画像にリンクを張る際は
$html->link($html->image('btn.png'), '/pages/index',
null, null, false);
とやらないと、エスケープされてしまっていました。
CakePHP 1.3では、ルールが変わって、
$html->link($html->image('btn.png'), '/pages/index',
array('escape' => false));
のようにやるようです。