です。探しても無かったので作りました。ライセンスはBSDで。
検証は、PHP 5.3 + CouchDBv0.91 @ Ubuntu9.04です
<?php class CouchdbWapper{ private $dbaddress; private $dbname; private $ngObj; private $default_couchdb_port="5984"; function __construct($dbaddress="localhost",$dbname="mydb") { $this->dbaddress = $dbaddress; $this->dbname = $dbname; $this->ngObj = new stdClass; $this->ngObj->error = "NG"; } function createDB($dbname=""){ $res = $this->getDBinfo($dbname); if($res->error=="not_found"){ return $this->httpConnect("PUT",$this->dbaddress,$dbname); }else{ return $this->ngObj; } } function deleteDB($dbname=""){ $res = $this->getDBinfo($dbname); if($res->error==""){ return $this->httpConnect("DELETE",$this->dbaddress,$dbname); }else{ return $this->ngObj; } } function getDBinfo($dbname=""){ if($dbname=="")$dbname = $this->dbname; return $this->httpConnect("GET",$this->dbaddress,$dbname); } function getRevs($dbname="",$id=""){ if($dbname=="")$dbname = $this->dbname; if($id!=""){ return $this->httpConnect("GET",$this->dbaddress,$dbname."/".$id."?revs=true"); }else{ return $this->ngObj; } } function get($dbname="",$id=""){ if($dbname=="")$dbname = $this->dbname; if($id!=""){ $id!=urlencode($id); return $this->httpConnect("GET",$this->dbaddress,$dbname."/".$id); }else{ return $this->ngObj; } } function getDesign($dbname="",$design_name=""){ if($dbname=="")$dbname = $this->dbname; if($design_name!=""){ return $this->httpConnect("GET",$this->dbaddress,$dbname."/_design/".$design_name); }else{ return $this->ngObj; } } function getView($dbname="",$design_name="",$view_name=""){ if($dbname=="")$dbname = $this->dbname; if($design_name!="" && $view_name!= ""){ return $this->httpConnect("GET",$this->dbaddress,$dbname."/_design/".$design_name."/_view/".$view_name); }else{ return $this->ngObj; } } function put($dbname="",$id="",$rev="",$data=array('test1'=>'wwwwww')){ if($dbname=="")$dbname = $this->dbname; if($id != "" && $rev!=""){ $data["_rev"] = $rev; return $this->httpConnect("PUT",$this->dbaddress,$dbname."/".$id,$data); }else{ return $this->ngObj; } } function putDesign($dbname="",$design_name="",$rev="3-22222222",$data=array('test1'=>'wwwwww')){ if($dbname=="")$dbname = $this->dbname; if($design_name != "" && $rev!=""){ $data["_rev"] = $rev; return $this->httpConnect("PUT",$this->dbaddress,$dbname."/_design/".$design_name,$data); }else{ return $this->ngObj; } } function orverrideDesign($dbname="",$design_name="",$data=array('test1'=>'wwwwww')){ if($dbname=="")$dbname = $this->dbname; if($design_name != "" ){ $dataCurrent = $this->getDesign($dbname,$design_name); if($dataCurrent->_id==""){ return $this->postDesign($dbname,$design_name,$data); }else{ return $this->putDesign($dbname,$design_name,$dataCurrent->_rev,$data); } }else{ return $this->ngObj; } } function post($dbname="",$data=array('test1'=>'test2','testA'=>'testB')){ if($dbname=="")$dbname = $this->dbname; return $this->httpConnect("POST",$this->dbaddress,$dbname,$data); } function postDesign($dbname="",$design_name="",$data=array('test1'=>'wwwwww')){ if($dbname=="")$dbname = $this->dbname; if($design_name != "" ){ return $this->httpConnect("PUT",$this->dbaddress,$dbname."/_design/".$design_name,$data); }else{ return $this->ngObj; } } function delete($dbname="",$_id="",$_rev=""){ if($dbname=="")$dbname = $this->dbname; if($_id!="" && $_rev!=""){ return $this->httpConnect("DELETE",$this->dbaddress,$dbname."/".$_id."?rev=".$_rev); }else{ return $this->ngObj; } } private function httpConnect($method,$host = "localhost",$path="",$post=""){ if($path=="")$path = $this->dbname; $request = "$method /$path HTTP/1.1\n"; $request .= "Host: $host\n"; $request .= "User-Agent: PHP/".phpversion()."\n"; if ((strtoupper($method) == "POST" || strtoupper($method) == "PUT") && $post!="") { $postdata = json_encode($post); $request .= "Content-Type: application/json\n"; $request .= "Content-Length: ".strlen($postdata)."\n"; $request .= "Accept: application/json\n"; $request .= "Accept-Encoding: gzip,deflate\n"; $request .= "Keep-Alive: 300\n"; $request .= "\n"; $request .= $postdata;//; }else{ $request .= "\n"; } $fp = fsockopen($host, $this->default_couchdb_port); if (!$fp) { echo "fp"; die("ERROR\n"); } fputs($fp, $request,strlen($request)); $response = ""; $length = 0; $nowlen = 0; $isBodyFlag = false; $isInChankFlag = false; $isChankedFlag = false; $ress = array(); while (!feof($fp)) { $res =fgets($fp, 128);//1 row Read $isAddFlag = true; array_push($ress,$res); if($length==0 && preg_match("/Content-Length:\s([0-9]+)/",$res,$match)){ $length = $match[1]; }else if($length==0 && preg_match("/Transfer-Encoding: chunked/",$res,$match)){ $isInChankFlag = true; $isChankedFlag = true; }else if($isBodyFlag!=true && $res == "\r\n" && ($isInChankFlag==true ||$length>0)){ $isBodyFlag=true; }else if($isInChankFlag==true && $isBodyFlag==true){ $torkens = explode("\r\n",$res); $length = hexdec($torkens[0]); $isInChankFlag = false; array_pop($ress); $nowlen = 0; if($length<1) break; }else if($isBodyFlag==true){ $nowlen+=strlen($res); if($nowlen >= $length){ if($isChankedFlag ==true){ $isInChankFlag=true; }else{ break; } } } if($res=="" || $res=="\n"){ break; } } fclose($fp); $respons = explode("\r\n\r\n",implode("",$ress)); $values = array(); for($i=1;$i<count($respons);$i++){ array_push($values,$respons[$i]); } $value = implode("",$values); $resdata = json_decode($value); if($resdata==NULL){ $resdata = new stdClass; $resdata->count = json_decode($resV,true); } return $resdata; } }
CouchDBに関しては
インストール
へびのぬけがら: Ubuntu に Apache CouchDB をインストールする
とりあえず0.8でよければ。
http://blog.livedoor.jp/paarasu_memo/archives/706901.html
ソースからビルドするならこちらが役に立ちますが、パスが若干間違ってます。
/usr/local/couchdbというディレクトリは作成され無いですね。
0.10.0でもいけるようです。
解説
Web 時代の非リレーショナルデータベース: 第 1 回 Apache CouchDB の概要とインストール
Web 時代の非リレーショナルデータベース: 第 2 回 Apache CouchDB と Ruby on Rails を使って wiki アプリケーションを作成する
Web 時代の非リレーショナルデータベース: 第 3 回 Apache CouchDB で MapReduce フレームワークに基づく問いあわせを行う
Web 時代の非リレーショナルデータベース: 第 4 回 Apache CouchDB の便利な機能を習得する
Web 時代の非リレーショナルデータベース: 第 5 回 Apache CouchDB の最新機能を知り、適用の勘所を掴む
ちょっとデザインのとり方変わってて困った。