CouchDB for PHP developers – CRUD

couchdb_1

Apache CouchDB™ commonly referred to as just CouchDB is an open source NoSQL database that uses JSON for storing data in form of documents, JavaScript as its query language using MapReduce queries, and regular HTTP for an API.
There is an excellent, free book called CouchDB The Definitive Guide available online at http://guide.couchdb.org. If you haven’t read it, I strongly advise doing so.

Working with JavaScript Object Notation (aka JSON) in PHP is a breeze. The best thing about JSON in PHP is that there is no required installation of external libraries needed, as JSON support is part of the PHP core:

  • json_decode – Decodes a JSON string
  • json_encode – Returns the JSON representation of a value

When it comes to API communication through HTTP, you are also pretty well covered here. PHP supports libcurl, a library that allows you to connect and communicate to many different types of servers with many different types of protocols. Among other protocols, libcurl supports supports http and https. cURL functions is probably more familiar term for this. Although this is such a frequently used library, some servers might not have it installed, so be sure to check if cURL is installed (for example, function_exists(‘curl_version’)).

The Futon

Another great thing about CouchDB is that it comes with a native web-based interface built into it, sort of like phpMyAdmin for MySQL. This interface is called Futon. It provides a basic interface to the majority of the functionality, including the ability to create, update, delete and view documents and views. Reason why we are bringing this up, is to that you can check the results of all of the API calls we have run so far. For more information on Futon itself, check out the official documentation page http://docs.couchdb.org/en/latest/intro.html#using-futon.

You should be able to access Futon via the following URL http://127.0.0.1:5984/_utils/.

So now that we have a support JSON handling, HTTP communication and a interface to check our results, we can move on with some practical examples.

Note: In most of the following examples, I am assuming that you used the Futon to set the username/password on a database. If you haven’t, you can comment out the line of code with CURLOPT_USERPWD.

Now, lets jump on to some practical examples.

Check if CouchDB is running

You can check if CouchDB is running just by executing HTTP GET request at http://127.0.0.1:5984 URL. If all is OK, you should be able to see a “Welcome” message as a part of larger JSON object.

<?php
 
$ch = curl_init();
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/* JSON string
{
  "couchdb": "Welcome",
  "uuid": "fd53dde57b4f2ead04267c54139358a7",
  "version": "1.3.1",
  "vendor": {
    "version": "1.3.1",
    "name": "The Apache Software Foundation"
  }
}
*/

Get a list of databases

Try not to get confused with terminology “CouchDB” vs “databases”. CouchDB is a database management system (DMS), which means it can hold multiple databases. A database is a bucket that holds “related data”, such as products.

<?php
 
$ch = curl_init();
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/_all_dbs');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/*
string(36) "["_replicator","_users","products"] "
*/

Create a database

In this example we will create an empty database called customers. For this, we need to use HTTP PUT request.

<?php
 
$table = ‘customers’;
$ch = curl_init();
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/'.$table);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/*
string(12) "{"ok":true} "
*/

Get an UUID from CouchDB

If you find it impractical to generate your own UUID’s, you can ask CouchDB to give you one. If you need more than one UUID, you can pass in the ?count=5 HTTP parameter to request 5 UUIDs, or any other number you need.

<?php
 
$ch = curl_init();
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/_uuids');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
 
$response = curl_exec($ch);
$_response = json_decode($response, true);
 
$UUID = $_response['uuids'];
 
curl_close($ch);
 
/*
$UUID: string(32) "c2449e8c6cb8cb938ee507e281003348"
*/

Create a document

To create new document you can either use a POST operation or a PUT operation.

In this example we are creating a document (an entry, a row, a record) within the customers database.

Each document in CouchDB has an ID. This ID is unique per database. You are free to choose any string to be the ID, although CouchDB recommends a UUID (or GUID). In the example above I showed you how to fetch the UUID from CouchDB itself. Since ID is a required parameter that needs to be passed with create a document request, we can either:
request it from CouchDB
use some other unique string for it.
For our customers table, we will use username field for ID as shown in the example below. Please note that this is not the best decision, as it is recommended to use the UUID for ID. However, for the sake of simplicity and easier overview we will use username.

<?php
 
$ch = curl_init();
 
$customer = array(
	'firstname' => 'Branko',
	'lastname' => 'Ajzele',
	'username' => 'ajzele',
	'email' => 'branko.ajzele@example.com',
	'pass' => md5('myPass123')
);
 
$payload = json_encode($customer);
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/customers/'.$customer['username']);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); /* or PUT */
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/*
string(69) "{"ok":true,"id":"ajzele","rev":"1-c3fde3a56fe3c3490448a8e34166b4ec"} "
*/

Get a document

To retrieve a document, simply perform a GET operation at the document’s URL like shown below. Here we are using $documentID = ‘ajzele’; to fetch the document we just created in previous example.

<?php
 
$ch = curl_init();
 
$documentID = 'ajzele';
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/customers/'.$documentID);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/*
string(200) "{"_id":"ajzele","_rev":"1-c3fde3a56fe3c3490448a8e34166b4ec","firstname":"Branko","lastname":"Ajzele","username":"ajzele","email":"branko.ajzele@example.com","pass":"433484b5317340f5c28e085bfffc78be"} "
*/

Update existing document

Note the _rev value 1-c3fde3a56fe3c3490448a8e34166b4ec in Create a document example. Prefix 1 means first revision. If you try to execute the same create a document request multiple times, you would get Document update conflict. error message. This is because CouchDB sees your request as update. If you want to update or delete a document, CouchDB expects you to include the _rev field of the revision you wish to change. When CouchDB accepts the change, it will generate a new revision number.

In order to update our previously create document, we need to pass it the _rev number we got from CouchDB when we created the document. Below is an example of such request, note how it is almost identical.

<?php
 
$ch = curl_init();
 
$customer = array(
	'firstname' => 'Branko_2',
	'lastname' => 'Ajzele_2',
	'username' => 'ajzele',
	'email' => 'branko.ajzele@example.com',
	'pass' => md5('myPass123')
);
 
$customer['_rev'] = '1-c3fde3a56fe3c3490448a8e34166b4ec';
 
$payload = json_encode($customer);
 
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:5984/customers/'.$customer['username']);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); /* or PUT */
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/*
string(69) "{"ok":true,"id":"ajzele","rev":"2-6a7e68954964a35d9415eb10142d17fc"} "
*/

Creating a document with attachment

CouchDB documents can have attachments. They can be any data (pdf, image, music, video…). It is important to know that attachments are added only to an existing documents. Process of adding an attachment is considered a document update. Since each document update requires a revision number, so does the process of adding attachment.

<?php
 
$ch = curl_init();
 
$database = 'customers';
$documentID = 'ajzele';
$revision = '2-6a7e68954964a35d9415eb10142d17fc';
 
$attachment = 'inkscape-0.48.4-1-win32.exe';
$repository = 'C:/Users/branko/Downloads/';
 
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$contentType = finfo_file($finfo, $repository.$attachment);
 
$payload = file_get_contents($repository.$attachment);
 
curl_setopt($ch, CURLOPT_URL, sprintf('http://127.0.0.1:5984/%s/%s/%s?rev=%s', $database, $documentID, $attachment, $revision));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
//curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: '.$contentType,
	'Accept: */*'
));
 
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
 
$response = curl_exec($ch);
 
curl_close($ch);
 
/*
string(69) "{"ok":true,"id":"ajzele","rev":"3-4b53bf95181e2461cc4b417507cf1e45"} "
*/

Attachments are stored under the root _attachments key of a JSON document, in a form like shown below.

"_attachments": {
   "inkscape-0.48.4-1-win32.exe": {
	   "content_type": "application/x-dosexec",
	   "revpos": 5,
	   "digest": "md5-4lZleB3ePMxCaF7QraQEQg==",
	   "length": 34702513,
	   "stub": true
   },
   "Magento_Community_1-7_User_Guide.zip": {
	   "content_type": "application/zip",
	   "revpos": 3,
	   "digest": "md5-j9E1m4ejrc7LtlRuKgq8cA==",
	   "length": 9034796,
	   "stub": true
   }
}

Delete a document

To delete a document you need to perform a HTTP DELETE operation at the document’s location, passing the rev parameter with the document’s current revision.

<?php
 
$ch = curl_init();
 
$database = 'customers';
$documentID = 'ajzele';
$revision = '7-6f74f3f827fa594ef7bf3293490e5d79';
 
curl_setopt($ch, CURLOPT_URL, sprintf('http://127.0.0.1:5984/%s/%s?rev=%s', $database, $documentID, $revision));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
	'Content-type: application/json',
	'Accept: */*'
));
 
curl_setopt($ch, CURLOPT_USERPWD, 'myDBusername:myDBpass');
 
$response = curl_exec($ch);
 
curl_close($ch);
/*
string(69) "{"ok":true,"id":"ajzele","rev":"8-80af68b3814813ebc57bb70e73b8524a"} "
*/

Interesting enough that the DELETE action, besides just deleting the document from database, also returns the increased revision number.

Summary

In this article we covered several basic but essential CRUD use cases, based on which you can start building your own application. Even doe there are already several PHP libraries out there available for working with CouchDB, we focused on doing the same with basic cURL as this is something every PHP developer should know how to do.
The next follow up article CouchDB for PHP developers – Searching/Querying will cover CouchDB Map/Reduce functions that we will use for Searching/Querying the database.


12 comments

  1. class ….

    <?php
    
    class Wbb_CouchDB
    {
    
    	/**
    	 * The Server API Url .
    	 *
    	 * @var string
    	 */
    	public $server_api_url;
    
    	/**
    	 * The Server Database Username
    	 *
    	 * @var bool
    	 */
    	private $_my_db_username;
    
    	/**
    	 * The Server Database Password
    	 *
    	 * @var bool
    	 */
    	private $_my_db_password;
    
    	/**
    	 * Curl Connection instance
    	 *
    	 * @var
    	 */
    	private $_curl_initialization;
    
    	/**
    	 * Wbb_CouchDB constructor.
    	 *
    	 * @param string $server_api_url
    	 * @param bool   $my_db_username
    	 * @param bool   $my_db_password
    	 */
    	public function __construct ( $server_api_url = '' , $my_db_username = FALSE , $my_db_password = FALSE )
    	{
    
    		// The Server API Url .
    		$this->server_api_url = $server_api_url;
    
    		// The Server Database Username
    		$this->_my_db_username = $my_db_username;
    
    		// The Server Database Password
    		$this->_my_db_password = $my_db_password;
    
    	}
    
    	/**
    	 * Initialize Curl Connection .
    	 */
    	public function InitConnection ()
    	{
    
    		$this->_curl_initialization = curl_init ();
    
    	}
    
    	/**
    	 * Close Curl Connection
    	 */
    	public function CloseConnection ()
    	{
    		curl_close ( $this->_curl_initialization );
    	}
    
    	/**
    	 * Check if CouchDB is running
    	 *
    	 * You can check if CouchDB is running just by executing HTTP GET request at http://127.0.0.1:5984 URL. If all is
    	 * OK, you should be able to see a “Welcome” message as a part of larger JSON object.
    	 *
    	 * @return mixed
    	 */
    	public function isRunning ()
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    
    	}
    
    	/**
    	 * Get a list of databases
    	 *
    	 * Try not to get confused with terminology “CouchDB” vs “databases”. CouchDB is a database management system
    	 * (DMS), which means it can hold multiple databases. A database is a bucket that holds “related data”, such as
    	 * products.
    	 *
    	 */
    	public function getAllDbs ()
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url . '/_all_dbs' );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    	}
    
    	/**
    	 * @param $db_name
    	 *
    	 * Create a database
    	 *
    	 * In this example we will create an empty database called customers. For this, we need to use HTTP PUT request.
    	 *
    	 * @return mixed
    	 */
    	public function createDb ( $db_name )
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url . '/' . $db_name );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'PUT' );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    
    	}
    
    	/**
    	 * Get an UUID from CouchDB
    	 *
    	 * If you find it impractical to generate your own UUID’s, you can ask CouchDB to give you one. If you need more
    	 * than one UUID, you can pass in the ?count=5 HTTP parameter to request 5 UUIDs, or any other number you need.
    	 */
    	public function GetUUID ()
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url . '/_uuids' );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'GET' );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		$response  = curl_exec ( $this->_curl_initialization );
    		$_response = json_decode ( $response , TRUE );
    
    		$UUID = $_response[ 'uuids' ];
    
    		return $UUID;
    
    	}
    
    	/**
    	 * Create a document
    	 *
    	 * To create new document you can either use a POST operation or a PUT operation.
    	 *
    	 * In this example we are creating a document (an entry, a row, a record) within the customers database.
    	 *
    	 * Each document in CouchDB has an ID. This ID is unique per database. You are free to choose any string to be the
    	 * ID, although CouchDB recommends a UUID (or GUID). In the example above I showed you how to fetch the UUID from
    	 * CouchDB itself. Since ID is a required parameter that needs to be passed with create a document request, we can
    	 * either: request it from CouchDB use some other unique string for it. For our customers table, we will use
    	 * username field for ID as shown in the example below. Please note that this is not the best decision, as it is
    	 * recommended to use the UUID for ID. However, for the sake of simplicity and easier overview we will use
    	 * username.
    	 *
    	 *
    	 * @param array $document_data
    	 * @param       $database
    	 * @param       $document
    	 *
    	 * @return mixed
    	 */
    	public function createDocument ( $document_data = array () , $database , $document )
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url . '/' . $database . '/' . $document );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'PUT' ); /* or PUT */
    		curl_setopt ( $this->_curl_initialization , CURLOPT_POSTFIELDS , json_encode ( $document_data ) );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    	}
    
    	/**
    	 * Creating a document with attachment
    	 *
    	 * CouchDB documents can have attachments. They can be any data (pdf, image, music, video…). It is important to
    	 * know that attachments are added only to an existing documents. Process of adding an attachment is considered a
    	 * document update. Since each document update requires a revision number, so does the process of adding
    	 * attachment.
    	 *
    	 * @param $database
    	 * @param $documentID
    	 * @param $revision
    	 * @param $attachment
    	 *
    	 * @return mixed
    	 */
    	public function createAttachmentDocument ( $database , $documentID , $revision , $attachment )
    	{
    
    		$finfo       = finfo_open ( FILEINFO_MIME_TYPE );
    		$contentType = finfo_file ( $finfo , $attachment );
    		$payload     = file_get_contents ( $attachment );
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , sprintf ( $this->server_api_url . '/%s/%s/%s?rev=%s' , $database , $documentID , $attachment , $revision ) );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'PUT' );
    		//curl_setopt( $this->_curl_initialization, CURLOPT_POST, true);
    		curl_setopt ( $this->_curl_initialization , CURLOPT_POSTFIELDS , $payload );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: ' . $contentType ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    
    	}
    
    	/**
    	 * Get a document
    	 *
    	 *
    	 * To retrieve a document, simply perform a GET operation at the document’s URL like shown below. Here we are using
    	 * $documentID = ‘ajzele’; to fetch the document we just created in previous example.
    	 *
    	 * @param $database
    	 * @param $documentID
    	 *
    	 * @return mixed
    	 */
    	public function getDocument ( $database , $documentID )
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url . '/' . $database . '/' . $documentID );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'GET' );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    
    	}
    
    	/**
    	 *
    	 * Update existing document
    	 *
    	 * Note the _rev value $document_rev (1-c3fde3a56fe3c3490448a8e34166b4ec) in Create a document example. Prefix 1
    	 * means first revision. If you try to execute the same create a document request multiple times, you would get
    	 * Document update conflict. error message. This is because CouchDB sees your request as update. If you want to
    	 * update or delete a document, CouchDB expects you to include the _rev field of the revision you wish to change.
    	 * When CouchDB accepts the change, it will generate a new revision number.
    	 *
    	 * In order to update our previously create document, we need to pass it the _rev number we got from CouchDB when
    	 * we created the document. Below is an example of such request, note how it is almost identical.
    	 *
    	 * @param array $document_data
    	 * @param       $database
    	 * @param       $document
    	 * @param bool  $document_rev
    	 *
    	 * @return mixed
    	 */
    	public function updateDocument ( $document_data = array () , $database , $document , $document_rev = FALSE )
    	{
    
    		if ( $document_rev )
    		{
    
    			$document_data[ '_rev' ] = $document_rev;
    		}
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , $this->server_api_url . '/' . $database . '/' . $document );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'PUT' ); /* or PUT */
    		curl_setopt ( $this->_curl_initialization , CURLOPT_POSTFIELDS , json_encode ( $document_data ) );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    
    	}
    
    	/**
    	 * Delete a document
    	 *
    	 * To delete a document you need to perform a HTTP DELETE operation at the document’s location, passing the rev
    	 * parameter with the document’s current revision.
    	 *
    	 * @param $database
    	 * @param $documentID
    	 * @param $revision
    	 *
    	 * @return mixed
    	 */
    	public function deleteDocument ( $database , $documentID , $revision )
    	{
    
    		curl_setopt ( $this->_curl_initialization , CURLOPT_URL , sprintf ( $this->_my_db_username . '/%s/%s?rev=%s' , $database , $documentID , $revision ) );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_CUSTOMREQUEST , 'DELETE' );
    		curl_setopt ( $this->_curl_initialization , CURLOPT_RETURNTRANSFER , TRUE );
    		curl_setopt (
    			$this->_curl_initialization , CURLOPT_HTTPHEADER , array (
    				                            'Content-type: application/json' ,
    				                            'Accept: */*' ,
    			                            )
    		);
    
    		if ( $this->_my_db_password && $this->_my_db_username )
    		{
    			curl_setopt ( $this->_curl_initialization , CURLOPT_USERPWD , $this->_my_db_username . ':' . $this->_my_db_password );
    		}
    
    		$response = curl_exec ( $this->_curl_initialization );
    
    		return $response;
    
    	}
    
    }
  2. Is there a link to the follow up article you mentioned on searching/querying… I was unable to get a hit on that with google or see it in your dev-talk feed… Thanks! Enjoyed this article.

  3. Hi 🙂 can you help me? I use XAMPP on my Windows 7 O.S and I’ve just installed couchdb for windows.
    How can I create a connection between xampp php and couchdb server?

  4. Robert… it’s pretty easy to update a document w/ the wrapper I linked. Assuming that you have a “relax” object, it’s:

    $document = $db->get_doc( whatever your id is );
    $document[key to change’] = “value”;
    $db->save($document);

  5. Hi there …

    if you want to update an document with other values with php … just do the following … get rev id firom the document … and change the value in the json array and put it up …

    public function update_data($doc, $jsonkey, $jsonvalue) {

    $resp = $this->couch->send(“GET”, “/somedb/”.$doc);
    $arr = json_decode($resp, true);

    $arr[$jsonkey] = $jsonvalue;

    $update = json_encode($arr);

    $this->couch->send(“PUT”, “/somedb/”.$doc, $update);

    }

    and here the class :

    class CouchSimple {
    function CouchSimple($options) {
    foreach($options AS $key => $value) {
    $this->$key = $value;
    }
    }

    function send($method, $url, $post_data = NULL) {
    $s = fsockopen($this->host, $this->port, $errno, $errstr);
    if(!$s) {
    echo “$errno: $errstr\n”;
    return false;
    }

    $request = “$method $url HTTP/1.0\r\nHost: $this->host\r\n”;

    if($post_data) {
    $request .= “Content-Length: “.strlen($post_data).”\r\n\r\n”;
    $request .= “$post_data\r\n”;
    }
    else {
    $request .= “\r\n”;
    }

    fwrite($s, $request);
    $response = “”;

    while(!feof($s)) {
    $response .= fgets($s);
    }

    list($this->headers, $this->body) = explode(“\r\n\r\n”, $response);
    return $this->body;
    }
    }

  6. https://github.com/barnjamin/relax/blob/master/relax.php is a simply PHP wrapper for Couchdb. It’s something that I use very frequently and handles a majority of things. There are a couple of errors in the repo that I’ll need to push out there, but nothing that isn’t easy to fix (e.g.: “Etag” vs “ETag”). If you’ve got and questions about using the wrapper, let me know.

  7. @MagePsycho

    Thanks for the feedback.

    Regarding the “CouchDB vs MongoDB”, we actually haven’t chose anything, if your asking us as company. Its just me personally playing with CouchDB 🙂 Reason why I like it slightly/tiny more than CouchDB is the HTTP/REST approach.

    Regarding the possible PHP extension/wrapper class, yes there are plenty out there. None does not seem to be absolute #1, so I played with the basic cURL approach (given that every PHP developer should know how to handle it like that).

    So basically this is just me playing/studying 🙂

  8. Just wondering why you guys choose couchDB instead of MongoDB.
    Also if it’s possible to use PHP extension or wrapper class for couchDB, it would be better.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.