Note: I'm migrating from gonzalo123.com to here. When I finish I'll swap the DNS to here. The "official" blog will be always gonzalo123.com

      PHP and couchDB

      Last days I’ve been playing with couchDB and PHP. There are several ways to use couchDB with PHP. There also are extensions but I want to build a simple library and I will show now the code.

      CouchDB has a great RestFul API so I we want to use CouchDB we only need to perform http requests. I have done a small class to do the requests. You can see the code here. It’s a simple class that uses PHP’s curl functions.

      I come from relational database world. NoSQL is new for me. Maybe I’m wrong but I want to use INSERT, UPDATE, DELETE and SELECT statements in CouchDB in the same way I use them in Relational database.

      The class is focused in the HTTP Document API. There is a great tutorial here that explains the API. Now I’ll show the interface I’ve made to perform the statements with CouchDB.

      The examples assumes there are CouchDB host at localhost:5987. Also as I’ve said before the class focused only in HTTP Document API so first of all I create a new database called users using CouchDB’s web interface (http://localhost:5984/ \utils/). Now let’s start:

      INSERT

      $couchDb = new Nov_CouchDb('localhost', 5984);
      $couchDb->db('users')->insert('gonzalo', array('password' => "g1"));
      

      SELECT

      $data = $couchDb->db('users')->select('gonzalo')->asArray();
      print_r($data);
      

      UPDATE

      $couchDb->db('users')->update('gonzalo', array('password' => 'g2'));
      

      DELETE

      $out = $couchDb->db('users')->delete('gonzalo')->asArray();
      print_r($out);
      

      Basically Nov_CouchDb has a constructor that stores connection information into private member variables:

      class Nov_CouchDb
      {
          private $_protocol;
          private $_host;
          private $_port;
          private $_user;
          private $_password;
       
          public function __construct($host, $port=Nov_Http::DEF_PORT , $protocol=Nov_Http::HTTP, $user = null, $password=null)
          {
              $this->_host     = $host;
              $this->_port     = $port;
              $this->_protocol = $protocol;
              $this->_user     = $user;
              $this->_password = $password;
          }
      }
      

      There are also a public function called db. This function stores the database and returns the instance of the class (I like chainable functions)

      ...
          private $_db;
          /**
           * @param string $db
           * @return Nov_CouchDb
           */
          public function db($db)
          {
              $this->_db = $db;
              return $this;
          }
      ...
      

      And finally the main functions:

      SELECT

      public function select($key)
      {
          try {
              $out = Nov_Http::connect($this->_host, $this->_port, $this->_protocol)
                  ->setCredentials($this->_user, $this->_password)
                  ->doGet("{$this->_db}/{$key}");
          } catch (Nov_Http_Exception $e) {
              $this->_manageExceptions($e);
          }
          return new Nov_CouchDb_Resulset($out);
      }
      

      INSERT

      /**
       * @param string $key
       * @param array $values
       * @return Nov_CouchDb_Resulset
       */
      public function insert($key, $values)
      {
          try {
              $out = Nov_Http::connect($this->_host, $this->_port, $this->_protocol)
                  ->setCredentials($this->_user, $this->_password)
                  ->setHeaders(array('Content-Type' =>  'application/json'))
                  ->doPut("{$this->_db}/{$key}", json_encode($values));
          } catch (Nov_Http_Exception $e) {
              $this->_manageExceptions($e);
          }
          return new Nov_CouchDb_Resulset($out);
      }
      

      UPDATE

      /**
       * @param string $key
       * @param array $values
       * @return Nov_CouchDb_Resulset
       */
      public function update($key, $values)
      {
          try {
              $http = Nov_Http::connect($this->_host, $this->_port, $this->_protocol)
                  ->setCredentials($this->_user, $this->_password);
              $out = $http->doGet("{$this->_db}/{$key}");
              $reg = json_decode($out);
              $out = $http->setHeaders(array('Content-Type' =>  'application/json'))
                  ->doPut("{$this->_db}/{$key}", json_encode($reg));
          } catch (Nov_Http_Exception $e) {
              $this->_manageExceptions($e);
          }
          return new Nov_CouchDb_Resulset($out);
      }
      

      DELETE

      /**
       * @param string $key
       * @return Nov_CouchDb_Resulset
       */
      public function delete($key)
      {
          try {
              $http = Nov_Http::connect($this->_host, $this->_port, $this->_protocol)
                  ->setCredentials($this->_user, $this->_password);
              $out = $http->doGet("{$this->_db}/{$key}");
              $reg = json_decode($out);
              $out = $http->doDelete("{$this->_db}/{$key}", array('rev' => $reg->_rev));
          } catch (Nov_Http_Exception $e) {
              $this->_manageExceptions($e);
          }
          return new Nov_CouchDb_Resulset($out);
      }
      

      insert, update, delete and select returns an instance of Nov \CouchDb \Resulset. CouchDb API returns a json string. But sometimes I want a PHP array or maybe an object. I use Nov \CouchDb \Resulset to perform those transformations:

      // Different outputs
      $data = $couchDb->db('users')->select('dummy')->asArray();
      print_r($data);
       
      $data = $couchDb->db('users')->select('dummy')->asObject();
      print_r($data);
       
      $data = $couchDb->db('users')->select('dummy')->asJson();
      print_r($data);
      

      EXCEPTIONS

      CouuchDB API is a RestFul API so it uses HTTP exceptions when something wrong happens. I’ve done three exceptions. One generic and other two with the most common exception in relational databases: NoDataFound and DupValOnIndex. this is because I want do things like the following ones:

      try {
          $couchDb->db('users')->update('gonzalo', array('password' => 'g2'));
      } catch (Nov_CouchDb_Exception_NoDataFound $e) {
          echo "No data found \n";
      }
       
      $couchDb->db('users')->insert('gonzalo1', array('password' => "g1"));
      try {
          $couchDb->db('users')->insert('gonzalo1', array('password' => "g1"));
      } catch (Nov_CouchDb_Exception_DupValOnIndex $e) {
          echo "Dup Val On Index \n";
      }
      try {
          $couchDb->db('users')->delete('gonzalo');
      } catch (Nov_CouchDb_Exception_NoDataFound $e) {
          echo "No data found \n";
      }
      

      The source code is available on google code here

      comments powered by Disqus