Introduction

This guide provides information for developers who want to use the Couchbase PHP SDK to build applications that use Couchbase Server.

Getting Started

We will use PHP and access the Couchbase server as part of this exercise; the Couchbase Server can be part of a cluster or it can be stand-alone. This exercise will show you how to:

  • Download, install and configure the Couchbase PHP SDK

  • How to use Couchbase and PHP to generate a general page access counter and last-accessed date indicator script

This section assumes that you have the following items set up for your development environment:

  • PHP 5 and above installed. For more information, see PHP Manual,

  • Web server installed and configured to serve PHP pages,

  • Couchbase Server 1.8 or above installed, and available from your development environment. See Couchbase Downloads

This section also assumes you have downloaded and set up a compatible version of Couchbase Server and have at least one instance of Couchbase Server and one data bucket established. If you need to set up these items, you can do with the Couchbase Administrative Console, or Couchbase Command-Line Interface (CLI), or the Couchbase REST API. For information and instructions, see:

The TCP/IP port allocation on Windows by default includes a restricted number of ports available for client communication. For more information on this issue, including information on how to adjust the configuration and increase the available ports, see MSDN: Avoiding TCP/IP Port Exhaustion.

After you have your Couchbase Server set up and you have installed the Couchbase SDK, you can compile and run the following basic program.

Downloading and Installation

Follow these steps to install and set up the PHP SDK:

  1. Download the SDK for your system from the SDK page.

  2. Unpack the archive containing the SDK:

    shell> tar xzf php-ext-couchbase-$system-$arch.tar.gz
    

    The resulting directory includes a file couchbase.so which is the PHP extension for the SDK. Note the path to this file.

  3. Find the php.ini file for your PHP interpreter. Try:

    shell> phpi -i | grep ini
    

    The output provided will have configuration file that is loaded for PHP, for instance:

    Loaded Configuration File => /private/etc/php.ini
    
  4. Open the php.ini file and add the path to your couchbase.so file. For example:

    extension=/path/to/couchbase.so
    

Verify the SDK Install

To verify you have set up the PHP SDK correctly follow these steps:

  1. Create a new file named test.php andplace the following test code it:

    <?php
         $cb = new Couchbase("127.0.0.1:8091", "username", "password", "default");
         $cb->set("a", 1);
         var_dump($cb->get("a"));
     ?>
    
  2. Save the new script as test.php.

  3. Start your Couchbase Server. Note the ip address and port for Couchbase Server and any username and password.

  4. If needed, update the IP address, username and password in test.php with your Couchbase Server information.

  5. Run your test script:

    shell> php test.php
    

    Couchbase Server returns 1.

Accessing Couchbase from PHP

To demonstrate how to use Couchbase PHP SDK with Couchbase Server we will built a web page counter. The counter will record the last access date for a web page. we’ll implement those features in PHP using the Couchbase library.

To store data in Couchbase Server, you provide information in a way that is similar to a PHP Array. You can store a value with a key, then retrieve the value by the key. In this exercise, we will store and retrieve integer and string data.

In the first part of our PHP script, we create a connection with Couchbase Server:

<?php
#Create the Couchbase object
$cb_obj = new Couchbase("127.0.0.1:8091", "user", "pass", "default");

In the next section of our script, we find out the name of the script currently running on the web server. Typically the name would be for the counter PHP script itself:

#determine the name of the script currently running
$script_name=$_SERVER["SCRIPT_NAME"];

In this case we set the $script_name variable to be the script name that is stored in a PHP environment variable, SCRIPT_NAME. Then we try to retrieve an existing record for the key $script_name from Couchbase Server. This will tell us if the key already exists or not and wheter we need to create a new record with the key:

#if the script name doesn't exist as a Couchbase key then add

$script_access_count=$cb_obj->get($script_name);

if($cb_obj->getResultCode() == COUCHBASE_KEY_ENOENT){
    #the add will fail if it has already been added
   $cb_obj->add($script_name,0);
}

Then we use one of the Couchbase SDKs increment methods to add one to the page access count. We provide the key, which is the $script_name, to increase the counter by one. We also output the access count in a string:

#increment the integer associated with the script name
$access_count = $cb_obj->increment($script_name);

#print the current access count
echo "this page ($script_name) accessed $access_count times<br>";

In this final part of our access counter script, we retrieve the last date and time that the script had been accessed. Again, we use the key as a parameter to get the value from Couchbase Server:

#retrieve the last access date/time of the script.
#the key name is the script name prefixed with DATE::
$last_access_date=$cb_obj->get("DATE::" . $script_name);

#handle the case where this is the first access to the script
#and that key doesn't yet exist
if($last_access_date == NULL){
     $last_access_date = "never";
}
echo "this page last accessed: " . $last_access_date;

#save the current access date/time in a script
$cb_obj->set("DATE::" . $script_name,date("F j, Y, g:i:s a "));
?>

You can save this sample can be saved into a PHP file in a directory on your web server, such as test.php

When you load test.php page you’ll see something like this on the first load:

this page (/test.php) accessed 1 times
this page last accessed: never

And like this on subsequent loads, with the access count incrementing and the date/time increasing:

this page (/test.php) accessed 2 times
this page last accessed: June 1, 2011, 10:06:04 am

Reload the script a few times in rapid succession and you’ll see a spike in traffic in the Couchbase Web UI. So, what exactly is our script doing to achieve this?

The first line of the script creates a Couchbase object ( $cb_obj ). The parameters define a Couchbase server hostname and port as well as user credentials and the default bucket name to the server pool that we’ll be accessing.

If you are running Couchbase on a single node, you specify its hostname and port. If you are running a multi-node cluster, you only need to point to a single node in a cluster as the PHP extension will transparently determine any cluster topology and route requests to the right servers as well as react on topolgy changes.

$cb_obj = new Couchbase("localhost", "user", "pass", "default");

We then get the "SCRIPT_NAME" value from the $_SERVER Array, which tells us in which script this PHP code is currently running.

$script_name=$_SERVER["SCRIPT_NAME"];

Now we connect to Couchbase to retrieve the integer access count associated with this script using the script name (determined above) as the key.

$script_access_count=$cb_obj->get($script_name);

If there is no such key in Couchbase (because the page has not previously been accessed), the request returns a NULL value, and the result code of the call to the get method is the Couchbase constant COUCHBASE_KEY_ENOENT (resource not found). In this case we use the add method to set the value to zero. If, between the failed get and add method calls, the key has already been added by another process, the add will fail and we will not overwrite the added value. This sort of attention to concurrency issues is overkill for the current application, as a missed counting of a single script access is unlikely to be critical; however, it illustrates how to write Couchbase code to avoid unintentionally overwriting keys:

if($cb_obj->getResultCode() == COUCHBASE_KEY_ENOENT){
       $cb_obj->add($script_name,0);
}

The key associated with the script name count is then incremented by one for the current script access, and that incremented value is returned and printed out. The increment method is atomic, consisting of both an increment and retrieval of the resultant value. If the Couchbase server receives two such requests, they will be queued for action in the order they were received and return the correct count to each requesting process.

$access_count = $cb_obj->increment($script_name);
echo "this page ($script_name) accessed $access_count times<br>";

To retrieve and update the last access date of the script we’re doing something similar to what we did for the script access count, however, instead of adding and incrementing an integer, we’re adding and updating a string.

As a key for the date any given script was accessed, we’ve prepended the string "DATE::" to the beginning of the script name; thus the key for the last access date of our test.php script is "DATE::test.php". We first try to get the date of last access and assign it to the $last_access_date variable. If this fails (the get method returns a Boolean NULL value and the subsequent getResultCode call returns COUCHBASE_KEY_ENOENT ) that means it hasn’t yet been set, so the script has not previously been accessed. In that case we’ll set $last_access_date to “never”. We then print out the value of $last_access_date.

$last_access_date=$cb_obj->get("DATE::" . $script_name);
 if($cb_obj->getResultCode() == COUCHBASE_KEY_ENOENT){
    $last_access_date = "never";
}
echo "this page last accessed: " . $last_access_date;

We now set the access date for this access of the script for retrieval on the next access.

$cb_obj->set("DATE::" . $script_name,date("F j, Y, g:i:s a "));

And that’s the end of the script. There is no method in the Couchbase library to close the connection to the server, however it will automatically be closed at the end of script execution.

Conclusion

This has been a brief outline of some basic features of the Couchbase API in PHP. We’ve used the add, get, set, increment and getResultCode methods of the Couchbase class to store and retrieve integers and strings. There are a number of other methods that allow for scalable development in a multiprocess and multi-server environment.

Tutorial

This tutorial will guide you through development of an application using PHP and Couchbase.

SQL databases and key-value stores such as Couchbase are general solutions to the web development problem of maintaining applications state across multiple systems and over time; as such they are similar, but there are many important differences. Most PHP developers are familiar with SQL databases, so the emphasis on the Couchbase implementation will be on how it differs from using SQL.

Prerequisites

This section assumes that you have installed Couchbase PHP SDK, that your web server is properly configured to serve PHP pages and that you’ve installed the Couchbase server on your development machine. We assume you have at least one instance of Couchbase Server and one data bucket established. If you need to set up these items in Couchbase Server, you can do with the Couchbase Administrative Console, or Couchbase Command-Line Interface (CLI), or the Couchbase REST API. For information and instructions, see:

After you have your Couchbase Server set up and you have installed the Couchbase SDK, you can compile and run the following basic program.

Example Application: WebChat

The demonstration application provides a means of chatting over the web: WebChat. It’s a rudimentary implementation with various features specifically designed to demonstrate the PHP/Couchbase interface. It allows user registration, login, logout as well as adding chat messages, viewing them and deleting them. To do this it uses add, increment, delete and append Couchbase key manipulation methods.

Database design

One of the first things usually undertaken in an SQL-based web application development project is the creation of a schema: the structure of database tables and their relationship. Couchbase has no tables. Like a PHP Array data type, all we have are key-value pairs to work with. On top of that, there is no mechanism for enumerating the keys you’ve created, so unless you know the keys to ask for you won’t be able to find any of your data.

Workflow

Our WebChat workflow will be simple. If you try to access the system and aren’t logged in it will route you to a login page (login.php). If you’re not registered, you can go to the registration page (register.php), and from there log in. Once you’re logged in, you are routed to the chat page (chat.php) and can engage in chat with other logged-in users: you can add a comment or delete your own comments. From there you can log out (logout.php). This workflow is summarized in Figure 1.

Let’s think a little bit about how we’re going to store our user information. As mentioned previously, there are no SQL style schemas in Couchbase, only keys and values. In addition, we can’t enumerate a list of keys in the Couchbase bucket we’re using. This means we have to know what we’re looking for before we look; we can’t select * from TABLE as we would using an SQL query. Also, even assuming we’ve only got one application using the given bucket, care must be taken in key naming conventions so that collisions don’t occur with keys of different types.

For our keys, we’ll prefix each key first with the application name, then the key type, for example a user named jsmith will get a user key in Couchbase of chat::user::jsmith, where the value associated with that key will contain the account information. We’re prefacing the user key with the application name in case we later choose to share this bucket with another application; if all applications follow this convention we’re creating a namespace for each application and we can be avoid key collisions between apps.

For the user comments we’ll keep a single key that lists the maximum comment number so far achieved, and the comments themselves will have keys containing their comment number, for example, chat::COMMENT#23

This is another method of determining the keys for values we may want to retrieve, somewhat different from that of the user list discussed above.

Though we won’t be implementing an administration function for managing users in this example application, we want to design our data model to support that possibility. This means that it should be possible to enumerate all users. To allow this, for each user we add, we’ll append the username to a string held in the key chat::userlist. We’ll be using the API append() method to that this. append() is functionally equivalent to doing a get() on the key, appending the new user to the returned text, and storing it again. The append() method requires less code and is also atomic, while a get, modify, and update sequence would not be.

The value held by a given key is of a default maximum size of 1 megabyte, though it can be increased with server side configuration. This should be kept in mind if you are, for example, doing many appends in long running or large-scale applications that are likely to exceed this limit.

Project Directory Structure

WebChat follows a standard structure for small and medium sized PHP projects, which is shown in the list below. The base directory contains PHP scripts corresponding to application views that the user will see (login.php, logout.php, register.php, chat.php), while a subdirectory (here named include) contains utility classes for page layout (header.php, footer.php) and a library file (include.php) of classes that do most of the work of the application. Finally the css directory contains our application specific style sheet (chat.css) which makes the generated web pages pretty and helps to avoid cluttering our PHP files with excessive HTML formatting.

  • index.php

  • login.php

  • logout.php

  • register.php

  • chat.php

  • css

    • chat.css
  • include

    • include.php

    • header.php

    • footer.php

We’ll discuss each of these files in turn to explain how the application works, with the exception of chat.css, which makes the output prettier, but doesn’t affect the way it works. All the files are available in the provided supplemental file Zip file.

Supporting PHP files

The first file, index.php (Listing 1), provides a redirect. If a user attempts to access the root directory, we’ll redirect to chat.php that will, in turn, redirect the page to login.php if they’re not already logged in.

Listing 1: index.php

<?php
    header("Location: chat.php");
    exit;
?>

Listing 2 shows the header file which sets the stylesheet, the page title and sets up the HTML markup.

Listing 2: header.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
     <meta http-equiv="content-type" content="text/html; charset=utf-8" />
      <title><?php
echo ($title);
?></title>
     <link rel="stylesheet" href="css/chat.css" type="text/css"
    media="screen" /> </head>
<body>
<div id="frame">
<div id="header">
     <h1><?php
echo ($APP_NAME);
?></h1>
</div>

Listing 3 shows footer.php, which displays login status and closes off the markup.

Listing 3: footer.php

<div id="footer">
    <?php
    if(empty($_SESSION{"userid"})){
        echo("Not logged in.<br>");
?>
    <a href="login.php">Login here</a>
    <?php
}else{
echo("Logged in as user <i>" . $_SESSION{"userid"} . "</i>");
echo("<br>");
echo("<a href='logout.php'>Logout</a>");
}?>
</div>
</div>
</body>
</html>

Like pieces of bread around a sandwich, the header and footer are boring but mandatory items included at the top and bottom of every page output by our application. Like sandwiches, all the interesting stuff happens between the bread.

include.php contains the meat of our application, and you’ll see it included first at the top of every PHP page, even before the header.php file. It starts the PHP session and contains a variety of constants used elsewhere in the application and the User, Comment and CouchbaseSingleton classes that do the bulk of the work in this application.

The first two clauses of include.php (Listing 4) set the error output and warnings to maximum and direct their output to the web server. While this is something we would turn off on a production web server, its helpful to see all warnings and errors while in development. The global constants are accessible by other pages and classes called after this file has been included.

Listing 4: include.php constants and settings

error_reporting(E_ALL);
ini_set("display_errors", 1);

//start our session
session_start();

//Global constants
$APP_NAME="PHP Couchbase WebChat";
define('APP_PREFIX',"chat");
define('KEY_DELIM',"::");
define('COUCHBASE_SERVER',"localhost:8091");
define('COUCHBASE_USER','Administrator');
define('COUCHBASE_PASS','asdasd');
define('COUCHBASE_BUCKET','default');

The $APP_NAME variable is output by the header at the top of every page.

The constants that are set using the define function are used by the classes defined later in the file. APP_PREFIX (chat) is added to the front of every key avoid potential key name collisions with other applications using the same bucket. KEY_DELIM (set to two colons “::”)is used to delimit the various portions of the keys; so, for example, the key for comment number 99 will be the concatenation of APP_PREFIX, KEY_DELIM, the key type (in this case comment), the KEY_DELIM again and the comment number: chat::comment::99.

COUCHBASE_SERVER, COUCHBASE_USER, COUCHBASE_PASS and COUCHBASE_BUCKET indicate the location of the Couchbase server and bucket we’ll be connecting to. You can change these to match the address and port of your own server.

The next part of the include.php file contains the three classes that do most of the work: CouchbaseSingleton, User and Comment.

The CouchbaseSingleton class (Listing 5) is a wrapper for the Couchbase library class. Both the User and Comment class (which we’ll see next) require a Couchbase library connection to the Couchbase server.

Listing 5: include.php CouchbaseSingleton class

/**
* Singleton Couchbase class
* This keeps a single global copy of the Couchbase
* Couchbase connection.
*/
class CouchbaseSingleton{
    private static $instance;
    private static $cb_obj;

    /**
    * Construct the object
    */
    private function __construct() {
    }

    /**
    * Initialize this class after construction
    */
    private function initialize(){
        self::$cb_obj = new Couchbase(COUCHBASE_SERVER, COUCHBASE_USER, COUCHBASE_PASS, COUCHBASE_BUCKET);
        self::$cb_obj->setOption(COUCHBASE_OPT_COMPRESSER,false);
    }

    /**
    * Return the singleton instance, constructing and
    * and initializing it if it doesn't already exist
    */
    public static function getInstance() {
        if(!self::$instance) {
            self::$instance = new self();
            self::$instance->initialize();
        }
        return self::$instance;
    }

    /**
    * Return the Couchbase object held by the singleton
    */
    public static function getCouchbase(){
        return(self::$cb_obj);
    }
}

Rather than have more than one Couchbase library instance created, we use CouchbaseSingleton to ensure we initialize and use only one copy per invocation of the application. When the static method getInstance() is called, it creates a CouchbaseSingleton instance and initializes a Couchbase instance, which may be retrieved using the getCouchbase() method. If a Couchbase connection is required, the call: CouchbaseSingleton::getInstance()->getCouchbase() will provide a reference with the appropriately initialized Couchbase server information and avoid recreating one. Though this is overkill for the current implementation, if it were to get significantly more complex (as applications tend to), it avoids the issue of multiple Couchbase library instances being instantiated by different classes.

The Couchbase library has limited functionality for connecting to servers; it does not directly support vBuckets or SASL authentication. You can, however, configure multiple servers with associated weights (connection priorities) by specifying hostname, port and weight. One solution is to use client-side Moxi to act as a proxy service to the Couchbase Server cluster.

The key method of the CouchbaseSingleton class is initialize(), which configures the connection to the Couchbase server. In initialize()we turn off compression using: setOption(COUCHBASE_OPT_COMPRESSER,false) as the Couchbase append method is only supported if the Couchbase records are not compressed.

The User class (Listing 6) handles user related actions; registration, login and logout.

Listing 6: include.php User class

/**
 * User class
 * This handles user interactions with Couchbase through
 * the Couchbase interface.
 */
class User {
    private $last_error_string;
    /**
     * Create a user account based on provided userid
     * and password.
     * @param string $userid
     * @param string $password
     * @return boolean
     */
    public function createUserAccount($userid, $password) {
        $error = "";
        if(!preg_match("/^\w{4,10}$/", $userid)) {
            $error .= "Illegal userid '<i>$userid</i>'<br>";
        }
        if(!preg_match("/^.{4,10}/", $password)) {
            $error .= "Password must have between 4 and 10 characters";
        }
        if($error != "") {
            $this -> last_error_string = $error;
            return false;
        }

        $cb_obj = CouchbaseSingleton::getInstance() -> getCouchbase();
        //check to see if the userid already exists
        $userid_key = APP_PREFIX . KEY_DELIM . "user" .
KEY_DELIM . $userid;
        $passwordHash = sha1($password);
        if($cb_obj -> add($userid_key, $passwordHash)) {
        //now that we've added the userid key we'll add it to the userlist
            $userlist_key = APP_PREFIX . KEY_DELIM . "userlist";
            if(!$cb_obj -> add($userlist_key, $userid)) {
                $cb_obj -> append($userlist_key, KEY_DELIM . $userid);
            }
            return true;
        } else {
            $result_code = $cb_obj -> getResultCode();
            if($result_code == COUCHBASE_KEY_EEXISTS) {
                $this -> last_error_string .=
                "User id '<i>$userid</i>' exists, please choose another.";
            } else {
                $this -> last_error_string .=
                "Error, please contact administrator:" .
                $cb_obj -> getResultMessage();
            }
            return false;
        }
    }

    /**
     * Attempt to login the user
     * @param string $userid
     * @param string $password
     * @return boolean
     */
    public function loginUser($userid, $password) {
        $cb_obj = CouchbaseSingleton::getInstance() -> getCouchbase();
        //check to sees if userid exists with the same password hashed
        $userid_key = APP_PREFIX . KEY_DELIM .
 "user" . KEY_DELIM . $userid;
        $submitted_passwordHash = sha1($password);
        $db_passwordHash = $cb_obj -> get($userid_key);
        if($db_passwordHash == false) {
            return (false);
        }
        //do we match the password?
        if($db_passwordHash == $submitted_passwordHash) {
            $_SESSION{"userid"} = $userid;
            return true;
        } else {
            return false;
        }
    }

    /**
     * Log the user out
     */
    public function logoutUser() {
        session_unset();
        session_destroy();
    }

    /**
     * Get the error string from the last action
     * @return string
     */
    public function getLastErrorString() {
        return $this -> last_error_string;
    }
}

The createUser method is called from the register.php file, which we’ll see later. It checks that the userid and password are of the correct format (userid 4-10 alphanumeric or underscore characters, password 4-10 characters), then attempts to add the new user to the database. The key is of the format: Chat::user::$userid, and the value is the sha1 hash of the password. If it fails (the method returns false), we set a private class error variable $last_error_string, which can be retrieved using the getLastErrorString method. There are many possible failure modes for an add (see the Couchbase documentation; in this case we’re only dealing with one explicitly, where the user id is already taken. In that case the error code is COUCHBASE_KEY_EEXISTS. All other error cases are converted to text using the getResultMessage() method for text display to the user.

If the user id addition is successful then we add it to the user list (stored in the chat::userlist key) with the append method. This will result in a value for the userlist of the form bjones::fdavis::jsmith enumerating all user ids that have successfully created accounts. Though we don’t currently use this elsewhere in the application, if we were to create a user management administration view, we’d need some way to find the full list of user ids. This list is where we would get that information.

The loginUser method of the User class is called from the login.php page. It retrieves the user id record (if it exists) from Couchbase, and then compares the retrieved sha1 hash with the hash of the provided password. If they match, the user is logged in by setting the userid value in the session variable.

The logout method is particularly simple; it destroys the PHP session for the current user.

The Comments class (Listing 7) manages adding, listing and deleting comments.

Listing 7: include.php Comment

/**  * Comments class for managing comments in Couchbase
  * through the Couchbase library
  */
class Comments {
     /**
      * Return the last n comments
      * @param integer $count
      * @return Array
      */
     public function getLastComments($count) {
         $cb_obj = CouchbaseSingleton::getInstance() -> getCouchbase();
         $comment_count_key = APP_PREFIX . KEY_DELIM . "chatcount";
         $script_comment_count = $cb_obj -> get($comment_count_key);
         $comment_key_list = array();
         for($i = $script_comment_count; $i > 0 &&
              $i > ($script_comment_count - $count); $i--) {
              array_push($comment_key_list, "COMMENT#" . $i);
         }
         $null = null;
         return ($cb_obj -> getMulti($comment_key_list,
             $null, Couchbase::GET_PRESERVE_ORDER));
     }
     /**
      * Add a comment to the comment list
     * @param string
     */
    public function addComment($comment) {
         $cb_obj = CouchbaseSingleton::getInstance() -> getCouchbase();
         if($comment != "") {
             $comment_count_key = APP_PREFIX . KEY_DELIM . "chatcount";
             $comment_count = $cb_obj -> get($comment_count_key);
             if($cb_obj -> getResultCode() == COUCHBASE_KEY_ENOENT) {
                 $cb_obj -> add($comment_count_key, 0);
             }
             $script_comment_count = $cb_obj -> increment($comment_count_key);
             $cb_obj -> add("COMMENT#" . $script_comment_count, $_SESSION{"userid"} .
              KEY_DELIM . $_POST["comment"]);
         }
     }
     /**
      * delete a comment from the list by number
      * @param integer $number
      */
     public function deleteComment($number) {
         $cb_obj = CouchbaseSingleton::getInstance() -> getCouchbase();
         $comment_key = "COMMENT#" . $number;
         $result = $cb_obj -> get($comment_key);
         $elements = explode(KEY_DELIM, $result);
         $userid = array_shift($elements);
         //make sure user who created is deleting
         if($userid == $_SESSION{"userid"}) {
             $result = $cb_obj -> delete($comment_key);
         }
     }
 }
 ?>

The addComment method takes the provided comment and adds it to the Couchbase database. The current comment number is stored in the $comment_count_key key (chat::chatcount). To add the comment to the database, the comment count key is incremented and we take the resultant number as our next comment number. Couchbase guarantees that the increment and retrieval are atomic, so we can be sure that we won’t collide with comment key number generated by another instance of the web application. The key for the comment is created, of the form chat::COMMENT#9. The corresponding comment value is of the form userid::comment, so that the comment is prepended by the identity of the submitter. We could serialize a data structure into the value if desired; however we’ve chosen to use text here for the sake of simplicity and clarity.

The deleteComment method takes a comment number as an argument and deletes that comment if the same user who submitted the comment requested the action.

The getLastComments method returns the specified number of comments in an array, counting backwards from the most current comment. The current comment count is retrieved to determine the most recent comment number. From this, an Array of keys is generated counting backwards from that comment, and the Couchbase getMulti method is used to retrieve them all simultaneously, which is more efficient than looping and retrieving each individually. The results are returned in an Array with the key being the request key and the value being the value retrieved from Couchbase. If a key doesn’t exist because that comment has been deleted, the value returned is empty.

The next few listings describe pages that provide views of the application; login, logout, register and chat.

The login view (Figure 2) is a userid and password form.

The login code (login.php, Listing 8) passes the userid and password fields to the createUser method of the User class we saw previously in include/include.inc.

Listing 8: login.php8

<?php
include_once ("include/include.php");

$loginfailed = "";
if(!empty($_POST{"userid"})) {
    $user = new User();
    if(!$user -> loginUser($_POST{"userid"}, $_POST{"password"})) {
        $loginfailed = "Login attempt failed";
    }
}

if(!empty($_SESSION{"userid"})) {
    header("Location: chat.php");
    exit ;
}

$title = "Login";
include_once ("include/header.php");
?>
<div id="content">
    <h2>Login to MemChat</h2>
    <?php echo $loginfailed
    ?><br>
    <form method="post" action="login.php" id="loginform" style="width:40%">
        <fieldset>
            <label for="userid">
                User id:
            </label>
            <input type="text" name="userid" length=20>
            <label for="password">
                Password:
            </label>
            <input type="password" name="password" id="password" length=20>
            <input type="submit" name="login" id="registration">
        </fieldset>
    </form>
    Register
    <a href="register.php">here</a> if you don't have an account.
</div>
<?php
include_once ("include/footer.php");
?>

If the user is already logged in (i.e., there is a value for $_SESSION{"userid"} ), they are immediately redirected to the chat.php file. If there is an error on login (in which case the loginUser method returns false) the login page is shown again with a login error.

The logout screen (Figure 3) just indicates the logged out status of the user.

The logout code (logout.php, Listing 9) calls the User class logoutUse r method, which we’ve seen already, then clears the current user PHP session.

Listing 9: logout.php

<?php
    include_once("include/include.php");
    $userid=$_SESSION{"userid"};
    $title="Logout";
    include_once("include/header.php");
    $user = new User();
    $user->logoutUser();
    echo("$userid logged out");
    include_once("include/footer.php");
?>

The register screen (Figure 4), is similar to the login page and provides a userid and password form.

The register code (register.php, Listing 10) is similar to login; it takes a userid and password and calls the User class createUserAccount method; if an error is returned (for example the userid already exists) then the error is displayed.

Listing 10: register.php

<?php
    include_once("include/include.php");
    $title="Register User";
    include_once("include/header.php");
    $result = false;
    //opening the register page logs you out
    $user=new User();
    $user->logoutUser();
    if(!empty($_POST{"userid"})){
        $userid=$_POST{"userid"};
        $result = $user->createUserAccount($_POST{"userid"},$_POST{"password"});
        if($result == true){
            echo     "<div id='error'>" .
                    "User id '<i>$userid</i>' successfully created.
<br> " .
                    "<a href='login.php'>Login here</a>" .
                    "</div>";
        }else{
            echo "<div id='error'>" . $user->getLastErrorString() .
"</div>";
        }
    }
    if($result != true){
?>
<div id="content">
    <h2>Register to use WebChat</h2>
    <form method="post" action="register.php" id="registrationform"
style="width:40%">
        <fieldset>
            <label for="userid">
                User id:
            </label>
            <input type="text" name="userid" id="userid">
            <label for="password">
                Password:
            </label>
            <input type="password" name="password" id="password">
            <input type="submit" name="registration" id="registration">
        </fieldset>
    </form>
    <small>
        <i>
        User id must have between 4 and 10 characters.
        <br>
        Only letters, numbers and underscore characters are permitted
        </i>
    </small>
</div>
<?php
}
include_once("include/footer.php");
?>

The chat view (Figure 5) displays the user chat form (a text field and a button), and the last ten submitted comments. The delete buttons in the “Action” allow a user to delete their own comments.

The chat view (chat.php, Listing 11) has the most user interaction and behavioral complexity, however the bulk of this behavior is implemented in the Comments class; the chat.php code is relatively simple.

Listing 11. chat.php

<?php
include_once ("include/include.php");
if(empty($_SESSION{"userid"})) {
    header("Location: login.php");
}
$title = "Chat";
include_once ("include/header.php");
?>
<form method="post" action="chat.php" id="chat">
    <div>
    <input type="text" name="comment" id="comment" maxlength="50" size="50"/>
    <input type="submit" name="submitcomment" id="submitcomment" value="Submit
 comment" />
    </div>
</form>
<br>

<?php
$comments = new Comments();
if(!empty($_POST{"comment"})) {
    $comments -> addComment($_POST{"comment"});
}
if(!empty($_POST{"delete"})) {
    $comments -> deleteComment($_POST{"commentnum"});
}
$comment_list = $comments -> getLastComments(10);
$keys = array_keys($comment_list);
?>
<table>
    <tr>
        <th width="10%" align="center">Comment #</th>
        <th>Action</th>
        <th>User ID</th>
        <th width="60%">Comment</th>
    </tr>
    <?php
    foreach($keys as $key) {
        echo "<tr>\n";
        $result = explode(KEY_DELIM, $comment_list{$key});
        $userid = array_shift($result);
        $message = implode(KEY_DELIM, $result);
        $commentnum = array_pop(explode("#", $key));
        $actionlink = "";
        if(empty($userid)) {
            $userid = "?";
            $message = "<i>deleted</i>";
        }
        if($_SESSION{"userid"} == $userid) {
            $actionlink =
"<form method='post' action='chat.php' id='message" . $commentnum . "'>";
            $actionlink .= "<input type='hidden' value='$commentnum'
 name='commentnum'>";
            $actionlink .= '<input type="submit" value="delete" name="delete"
style="background: none; border: none; font-style: italic;" >';
            $actionlink .= "</form>";
        }

echo("<td>$commentnum</td><td>$actionlink</td><td>
$userid</td><td>$message</td>\n");
        echo "</tr>\n";
    }
    ?>
</table>
<?php
include_once ("include/footer.php");
?>

If a non-logged in user accesses the chat view, they are immediately routed to the login page. If they are logged in, a chat form is displayed with the last 10 comments shown in decreasing order (i.e. increasing in age as they go down the page). If the currently logged in user created a given comment, a button to delete it is shown in the action column (Figure 5) for that comment. The delete button looks like a link, but it is actually a borderless button on a form that does a POST submission to the chat.php page. Comment class methods handle both comment submission and comment deletion.

WebChat is an example application that outlines various features of Couchbase as they apply to PHP development. We’ve demonstrated how to add, delete, append and retrieve data from Couchbase using the Couchbase library in addition to identifying error states. This example should give you a clear idea of how to begin using Couchbase with your own PHP application.

Migrate to Couchbase

This chapter explains how to move existing codebases to the Couchbase PHP API.

Migrating from ext/memcached

ext/memcached is a popular PHP extension for memcached. You can use Couchbase Server in places where you use memcached today and take advantage of Couchbase Server’s unique features like scaling over multiple physical machines, persistence or view querying (2.0 or later) as well as many others.

This section will explain how to migrate an existing codebase from ext/memcached to ext/couchbase.

ext/couchbase is our new PHP extension around libcouchbase, our also new C-library for connecting to Couchbase Server. ext/couchbase is mostly API compatible with ext/memcached. However, we made a few changes to take advantage of libcouchbase’s unique features.

You can use ext/memcached with Couchbase Server just fine (using the binary protocol), so why would you want to migrate to ext/couchbase?

Easy! ext/memcached is what we call a “dumb-client” while ext/couchbase is a “smart client”. This isn’t meant to sound any derogatory, of course, but points to the fact that with memcached you always have a single server to connect to or you are manually managing multiple ones. Couchbase server can manage multiple servers for you, so you still only connect to one physical node, but ext/couchbase is “smart” enough to figure out which server to talk to for a given operation.

And like we said earlier, you get first class access to all the other features Couchbase has over memcached. We hope that is all reason enough to migrate. Now let’s go.

The Differences

Let’s start with a list of the differences.

Extension Methods

This list shows the differences between the ext/memcached and the ext/couchbase APIs.

__construct([string $cluster_url = http://default:@localhost:8091/default[, $persistent = true]])

The constructor for ext/couchbase takes a string identifying one of the cluster nodes. From there ext/couchbase figures out all the other nodes in a cluster automatically, whereas in ext/memcached you’d have to use multiple calls to the addServer() method, that doesn’t exist in ext/couchbase.

ext/memcached’s $persistent_id parameter allows you to tie specific instances of Memcached to persistent connections. In ext/couchbase connections are persistent by default and you can turn them off with the second optional parameter to __construct() and setting it to false

Performance Considerations

Note that calling new Couchbase($url) will make a REST call to Couchbase Server to determine the cluster topology. This is a relatively expensive call and that’s the reason why we use persistent connections by default, so that this call doesn’t have to be made more often then necessary, and most importantly not on every user-request.

That means, if you have any code that calls new Memcached(); in a tight loop, you want to move the call to new Couchbase(); to outside of that loop. If you compare performance between ext/memcached and ext/couchbase and find ext/couchbase to run at ½ the speed of ext/memcached, look for places where new Couchbase(); is called in a loop or otherwise repeatedly.

addByKey(), setByKey(), replaceByKey(), getByKey(), deleteByKey(), appendByKey(), prependByKey(), getDelayedByKey(), setMultiByKey(), getMultiByKey(), addServer(), addServers(), getServerbyKey(), getServerList()

With ext/couchbase you no langer have to manually manage multiple memcached instances. All methods that are related to that use case aren’t supported by ext/couchbase.

append($key, $value, [int $expiration[, float $cas_token]])

append()’s signature in ext/couchbase is almost identical append() to ext/memcached. The only difference is two optional arguments: int $expiration and float $cas_token. $expliration lets you updated the expiration time for a key and $cas_token allows you to make the append operation fail if they key’s existing cas_token has changed.

append() keeps working like you expect it, but you get the new case functionality if you like to use that.

prepend($key, $value, [int $expiration[, float $cas_token]])

prepend()’s signature in ext/couchbase is almost identical prepend() to ext/memcached. The only difference is two optional arguments: int $expiration and float $cas_token. $expliration lets you updated the expiration time for a key and $cas_token allows you to make the prepend operation fail if they key’s existing cas_token has changed.

prepend() keeps working like you expect it, but you get the new case functionality if you like to use that.

decrement(string $key[, int $offset = 1[, bool $create = false[, int $expiration = 0[, int $initial = 0]]]])

decrement() adds three more optional parameters.

bool create = false determines whether ext/couchbase should create the key if it doesn’t exist. With this you can model cases where you want to avoid decrementing non-existent keys. The default is false, do not create non existent keys.

int $expiration = 0 lets you set a new expiration time for the key. The default is 0, do not expire.

int initial = 0 allows you to specify an initial value in case you set create = true. This allows you to start at an arbitrary value without the need for running extra operations.

decrement() will work like it does in ext/memcached, but you will be able to use more features with the optional arguments.

increment(string $key[, int $offset = -1[, bool $create = false[, int $expiration = 0[, int $initial = 0]]]])

increment() adds three more optional parameters.

bool create = false determines whether ext/couchbase should create the key if it doesn’t exist. With this you can model cases where you want to avoid incrementing non-existent keys. The default is false, do not create non existent keys.

int $expiration = 0 lets you set a new expiration time for the key. The default is 0, do not expire.

int initial = 0 allows you to specify an initial value in case you set create = true. This allows you to start at an arbitrary value without the need for running extra operations.

increment() will work like it does in ext/memcached, but you will be able to use more features with the optional arguments.

delete(string $key[, float $cas_token])

delete() changes the second optional argument from int $time to float $cas_token. Delete with a timeout isn’t supported by Couchbase, we hence don’t allow a timeout to be specified with a delete().

Instead delete() gains the opportunity to use a cas value, so you can avoid deleting a key with a changed cas value.

If you rely on delete() with a time, you need to rework that part of your application.

flush()

Like delete(), flush() doesn’t support flushing after a timeout.

If you rely on flush() with a time, you need to rework that part of your application.

Extension Constants

Both ext/memcached and ext/couchbase use a number of constants throughout the API. Most notably result codes and configuration options.

For many constants, you can just switch the Memcached:: (or MEMCACHED_) prefix to the Couchbase:: (or COUCHBASE_) prefix. The constants below are the exception to this rule.

Memcached::OPT_HASH

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_DEFAULT

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_MD5

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_CRC

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_FNV1_64

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_FNV1A_64

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_FNV1_32

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_FNV1A_32

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_HSIEH

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::HASH_MURMUR

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_DISTRIBUTION

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::DISTRIBUTION_MODULA

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::DISTRIBUTION_CONSISTENT

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_LIBKETAMA_COMPATIBLE

ext/couchbase handles distribution of keys over a cluster automatically. For that reasons specifying a hash algorithm doesn’t make much sense. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_BUFFER_WRITES

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_BINARY_PROTOCOL

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_NO_BLOCK

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_TCP_NODELAY

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_SOCKET_SEND_SIZE

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_SOCKET_RECV_SIZE

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_CONNECT_TIMEOUT

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_RETRY_TIMEOUT

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_SEND_TIMEOUT

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_RECV_TIMEOUT

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_POLL_TIMEOUT

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_CACHE_LOOKUPS

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::OPT_SERVER_FAILURE_LIMIT

ext/couchbase handles low-level network settings transparently. There is no equivalent for this constant in ext/couchbase.

Memcached::HAVE_IGBINARY

There is no equivalent for this constant in ext/couchbase.

Memcached::HAVE_JSON

There is no equivalent for this constant in ext/couchbase. JSON support is always included.

Memcached::GET_PRESERVE_ORDER

There is no equivalent for this constant in ext/couchbase.

Memcached::RES_SUCCESS

The ext/couchbase equivalent of this constant are Couchbase::SUCCESS and COUCHBASE_SUCCESS respectively.

Memcached::RES_FAILURE

The ext/couchbase equivalent of this constant are Couchbase::ERROR and COUCHBASE_ERROR respectively.

Memcached::RES_HOST_LOOKUP_FAILURE

The ext/couchbase equivalent of this constant are Couchbase::UNKNOWN_HOST and COUCHBASE_UNKNOWN_HOST respectively.

Memcached::RES_PROTOCOL_ERROR

The ext/couchbase equivalent of this constant are Couchbase::PROTOCOL_ERROR and COUCHBASE_PROTOCOL_ERROR respectively.

Memcached::RES_CLIENT_ERROR

There is no equivalent of this constant in ext/couchbase.

Memcached::RES_SERVER_ERROR

There is no equivalent of this constant in ext/couchbase.

Memcached::RES_WRITE_FAILURE

The ext/couchbase equivalent of this constant are Couchbase::NETWORK_ERROR and COUCHBASE_NETWORK_ERROR respectively.

Memcached::RES_DATA_EXISTS

The ext/couchbase equivalent of this constant are Couchbase::KEY_EEXISTS and COUCHBASE_KEY_EEXISTS respectively.

Memcached::RES_NOTSTORED

The ext/couchbase equivalent of this constant are Couchbase::NOT_STORED and COUCHBASE_NOT_STORED respectively.

Memcached::RES_NOTFOUND

The ext/couchbase equivalent of this constant are Couchbase::KEY_ENOENT and COUCHBASE_KEY_ENOENT respectively.

Memcached::RES_PARTIAL_READ

The ext/couchbase equivalent of this constant are Couchbase::PROTOCOL_ERROR and COUCHBASE_PROTOCOL_ERROR respectively.

Memcached::RES_SOME_ERRORS

There is no equivalent of this constant in ext/couchbase.

Memcached::RES_NO_SERVERS

There is no equivalent of this constant in ext/couchbase.

Memcached::RES_END

There is no equivalent of this constant in ext/couchbase.

Memcached::RES_BAD_KEY_PROVIDED

There is no equivalent of this constant in ext/couchbase.

Memcached::RES_CONNECTION_SOCKET_CREATE_FAILURE

The ext/couchbase equivalent of this constant are Couchbase::NETWORK_ERROR and COUCHBASE_NETWORK_ERROR respectively.

Memcached::RES_PAYLOAD_FAILURE

The ext/couchbase equivalent of this constant are Couchbase::PROTOCOL_ERROR and COUCHBASE_PROTOCOL_ERROR respectively.

PHP Method Summary

Connection Operations

An example below on creating a single connection to the default bucket at Couchbase Server:

$cb = new Couchbase("192.168.1.200:8091", "user", "pass");

The Couchbase PHP SDK can also create a persistent connection which can be used for multiple request and response from processes. When you use a persistent connection, the first connection request from an SDK will take longer than subsequent SDK requests. Each subsequent request from a client application automatically reuses the existing instance of the client and the connections for that client. The following example demonstrates how you create a persistent connection:

$cb = new Couchbase("192.168.1.200:8091", "user", "pass", true);

The parameters you use include host:port, username, password, bucket name, and a boolean. The boolean set to true indicates that you want to create a persistent connection. By default connections are not persistent.

When you use a persistent connection, the first request from a client application will typically require more CPU and time to create a connection, compared to operations that rely on an existing connection. Subsequent requests from a client application will automatically reuse this existing persistent connection based upon the name of the connection.

Be aware many web servers such as Apache will automatically take control of the connection instance and may destroy but also rebuild a connection after a certain number of requests. This is part of the web server functioning, and enables the web server to create a pool of reuseable connections.

To plan for redundancy in the event of a failure of the Couchbase Server node you specify to the client library, you may wish to supply multiple hosts. For example:

$hosts = array(
    "server1",
    "server2"
);

$cb = new Couchbase($hosts,
    "user",
    "pass",
    "bucket",
    true);

With this method of building the connection, the client will try each of the hosts specified in the order specified until it either connects with and establishes a connection to a cluster or it runs out of hosts to try.

API Call $object->addServer($host, $port [, $weight ])
Asynchronous no
Description Add a server to the connection pool
Returns scalar ( Binary object )
Arguments
string $host Addresses a server by hostname or numeric IP address
integer $port Specifies a TCP port number
integer $weight Defines the relative weight of a server in the connection pool.

API Call $object->getOption($option)
Asynchronous no
Description Retrieve an option
Returns scalar ( Binary object )
Arguments
int $option Option controlling connection or server behavior

API Call $object->setOption($option, $mixed)
Asynchronous no
Description Specify an option
Returns boolean ( Boolean (true/false) )
Arguments
int $option Option controlling connection or server behavior
scalar $mixed Option value (constant, number, or string)

Storage Operations

API Call $object->add($key, $value [, $expiry ] [, $persistto ] [, $replicateto ])
Asynchronous no
Description Add a value with the specified key that does not already exist. Will fail if the key/value pair already exist.
Returns scalar ; supported values:
COUCHBASE_E2BIG
COUCHBASE_EINTERNAL
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
$persistto Specify the number of nodes on which the document must be persisted to before returning.
$replicateto Specify the number of nodes on which the document must be replicated to before returning
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->replace($key, $value [, $expiry ] [, $casunique ] [, $persistto ] [, $replicateto ])
Asynchronous no
Description Update an existing key with a new value
Returns scalar ; supported values:
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
$casunique Unique value used to verify a key/value combination
$persistto Specify the number of nodes on which the document must be persisted to before returning.
$replicateto Specify the number of nodes on which the document must be replicated to before returning
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->set($key, $value [, $expiry ] [, $casunique ] [, $persistto ] [, $replicateto ])
Asynchronous no
Description Store a value using the specified key, whether the key already exists or not. Will overwrite a value if the given key/value already exists.
Returns scalar ; supported values:
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
$casunique Unique value used to verify a key/value combination
$persistto Specify the number of nodes on which the document must be persisted to before returning.
$replicateto Specify the number of nodes on which the document must be replicated to before returning
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->addByKey($master_key, $key, $value [, $expiry ])
Asynchronous no
Description Store a value with a server key
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).

API Call $object->setByKey($master_key, $key, $value [, $expiry ])
Asynchronous no
Description Store a value using the specified key, whether the key already exists or not. Will overwrite a value if the given key/value already exists.
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).

API Call $object->setMultiByKey($array [, $expiry ])
Asynchronous no
Description Set multiple key/value items at once on a specific server
Returns scalar ( Binary object )
Arguments
array $array List of things
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).

API Call $object->setMulti($kvarray [, $expiry ])
Asynchronous no
Description Set multiple key/value items at once; updates supplied array for successful operation.
Returns boolean ; supported values:
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
COUCHBASE_SUCCESS
Arguments
array $kvarray List of key/value pairs
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->flush()
Asynchronous no
Description Deletes all values from the corresponding bucket
Returns boolean ; supported values:
COUCHBASE_ETMPFAIL
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_SUCCESS
Arguments
None
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

Retrieve Operations

API Call $object->get($key [, $callback ] [, $casunique ])
Asynchronous no
Description Get one or more key values
Returns scalar ; supported values:
COUCHBASE_KEY_ENOENT
object
Arguments
string $key Document ID used to identify the value
mixed $callback Callback function or method to be called
$casunique Unique value used to verify a key/value combination
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->getMulti($keycollection [, $casarray ])
Asynchronous no
Description Get one or more key values
Returns array ( Array of key/value pairs for each document, or key/error condition for each failure )
Arguments
array $keycollection One or more keys used to reference a value
array $casarray Array of unique values used to verify a key/value combination

API Call $object->getDelayed($keyn [, $with_cas ] [, $callback ])
Asynchronous yes
Description Get one or more key values
Returns boolean ; supported values:
COUCHBASE_KEY_ENOENT
COUCHBASE_SUCCESS
Arguments
array $keyn One or more keys used to reference a value
boolean $with_cas Whether to return the CAS value for a document
mixed $callback Callback function or method to be called

API Call $object->fetch($key [, $keyn ])
Asynchronous yes
Description Fetch the next delayed result set document
Returns array ( An array of the next document retrieved, or NULL if no more documents )
Arguments
string $key Document ID used to identify the value
array $keyn One or more keys used to reference a value

API Call $object->fetchAll($key [, $keyn ])
Asynchronous yes
Description Fetch all the delayed result set documents
Returns array ( An array of all the remaining documents retrieved, or NULL if no more documents )
Arguments
string $key Document ID used to identify the value
array $keyn One or more keys used to reference a value

API Call $object->getByKey($master_key, $key [, $cache_callback ] [, $casunique ])
Asynchronous no
Description Get one or more key values
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
scalar $cache_callback Function to be called in the form function($key, $value)
$casunique Unique value used to verify a key/value combination

API Call $object->getDelayedByKey($master_key, $keyn [, $with_cas ] [, $callback ])
Asynchronous no
Description Get one or more key values
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
array $keyn One or more keys used to reference a value
boolean $with_cas Whether to return the CAS value for a document
mixed $callback Callback function or method to be called

API Call $object->getMultiByKey($master_key, $keyn [, $cas_token ] [, $flags ])
Asynchronous no
Description Get one or more key values
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
array $keyn One or more keys used to reference a value
float $cas_token CAS token for conditional operations
$flags Flags for storage options. Flags are ignored by the server byt preserved for use by the client.

API Call $object->getResultCode()
Asynchronous no
Description Returns the result code for the last operation
Returns ()
Arguments
None

API Call $object->getResultMessage()
Asynchronous no
Description Returns the result message for the last operation
Returns ()
Arguments
None

API Call $object->getVersion()
Asynchronous no
Description Returns the versions of all servers in the server pool
Returns array ; supported values:
array
Arguments
None

Update Operations

API Call $object->append($key, $value [, $expiry ] [, $casunique ] [, $persistto ] [, $replicateto ])
Asynchronous no
Description Append a value to an existing key
Returns scalar ; supported values:
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
$casunique Unique value used to verify a key/value combination
$persistto Specify the number of nodes on which the document must be persisted to before returning.
$replicateto Specify the number of nodes on which the document must be replicated to before returning
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->cas($casunique, $key, $value [, $expiry ])
Asynchronous no
Description Compare and set a value providing the supplied CAS key matches
Returns boolean ; supported values:
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_EEXISTS
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
COUCHBASE_SUCCESS
Arguments
$casunique Unique value used to verify a key/value combination
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->decrement($key, $offset)
Asynchronous no
Description Decrement the value of an existing numeric key. The Couchbase Server stores numbers as unsigned values. Therefore the lowest you can decrement is to zero.
Returns scalar ; supported values:
COUCHBASE_DELTA_BADVAL
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
scalar
Arguments
string $key Document ID used to identify the value
$offset Integer offset value to increment/decrement (default 1)
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->delete($key [, $casunique ])
Asynchronous no
Description Delete a key/value
Returns scalar ; supported values:
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
string $key Document ID used to identify the value
$casunique Unique value used to verify a key/value combination

API Call $object->increment($key [, $offset ] [, $create ] [, $expiry ] [, $initial ])
Asynchronous no
Description Increment the value of an existing numeric key. Couchbase Server stores numbers as unsigned numbers, therefore if you try to increment an existing negative number, it will cause an integer overflow and return a non-logical numeric result. If a key does not exist, this method will initialize it with the zero or a specified value.
Returns scalar ; supported values:
COUCHBASE_DELTA_BADVAL
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
scalar
Arguments
string $key Document ID used to identify the value
$offset Integer offset value to increment/decrement (default 1)
boolean $create Create the document if it does not already exist
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
boolean $initial Initial value for the document
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->prepend($key, $value [, $expiry ] [, $casunique ] [, $persistto ] [, $replicateto ])
Asynchronous no
Description Prepend a value to an existing key
Returns scalar ; supported values:
COUCHBASE_E2BIG
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
$casunique Unique value used to verify a key/value combination
$persistto Specify the number of nodes on which the document must be persisted to before returning.
$replicateto Specify the number of nodes on which the document must be replicated to before returning
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->appendByKey($master_key, $key, $value [, $expiry ])
Asynchronous no
Description Append to a key on a specific server
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).

API Call $object->prependByKey($master_key, $key, $value)
Asynchronous no
Description Prepend a value to a key on a specific server
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
object $value Value to be stored

API Call $object->replaceByKey($master_key, $key, $value [, $expiry ])
Asynchronous no
Description Replace a value on a specific server
Returns scalar ( Binary object )
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).

API Call $object->deleteByKey($master_key, $key)
Asynchronous no
Description Delete a key/value on a specific server
Returns scalar ; supported values:
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
docid
Arguments
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

API Call $object->casByKey($casunique, $master_key, $key, $value [, $expiry ])
Asynchronous no
Description Compare and set a value providing the supplied CAS key matches
Returns scalar ( Binary object )
Arguments
$casunique Unique value used to verify a key/value combination
$master_key Master key used for consistent server references
string $key Document ID used to identify the value
object $value Value to be stored
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).

API Call $object->touch($key, $expiry)
Asynchronous no
Description Update the expiry time of an item
Returns boolean ; supported values:
COUCHBASE_ENOMEM
COUCHBASE_ETMPFAIL
COUCHBASE_KEY_ENOENT
COUCHBASE_NOT_MY_VBUCKET
COUCHBASE_NOT_STORED
COUCHBASE_SUCCESS
Arguments
string $key Document ID used to identify the value
$expiry Expiry time for key. Values larger than 30*24*60*60 seconds (30 days) are interpreted as absolute times (from the epoch).
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

Statistic Operations

API Call $object->getStats()
Asynchronous no
Description Get the database statistics
Returns array ; supported values:
COUCHBASE_EINTERNAL
COUCHBASE_ERROR
array
Arguments
None
Errors
CouchbaseAuthenticationException Authentication to the Couchbase cluster failed
CouchbaseException Base exception class for all Couchbase exceptions
CouchbaseIllegalKeyException The key provided is not a legal key identifier
CouchbaseLibcouchbaseException An error occurred within the libcouchbase library used by th PHP extension
CouchbaseServerException An error occurred within the Couchbase cluster

Appendix: Release Notes

The following sections provide release notes for individual release versions of Couchbase Client Library PHP. To browse or submit new issues, see Couchbase Client Library PHP Issues Tracker.

Release Notes for Couchbase Client Library PHP 1.0.5 GA (13 August 2012)

New Features and Behavior Changes in 1.0.5

  • Allow for multiple hosts to be specified either via an array or a semicolon delimited list

    This feature will configure the client library to automatically select another node from the cluster if the first node specified is down.

Fixes in 1.0.5

  • PCBC-77: Do not attempt to decompress uncompressed JSON.

    This change allows for interoperability between the Java client library and the PHP client library, even though the flags may be slightly different between the two.

  • PCBC-75: Correctly free persistent structures.

    Prior to this change, in some cases the client could encounter a segmentation fault while trying to use persistent connections.

Release Notes for Couchbase Client Library PHP 1.0.4 GA (7 June 2012)

This is a bugfix release of the Couchbase PHP SDK.

Fixes in 1.0.4

  • PCBC-65: Implement getResultMessage() and get_result_message()

  • PCBC-67: Add preserve_order flag to getMulti()

  • PCBC-66: null terminate keys in getMulti() responses

Release Notes for Couchbase Client Library PHP 1.0.3 GA (9 May 2012)

This is a bugfix release of the Couchbase PHP SDK.

Fixes in 1.0.3

  • Fix PCBC-61, compatibility with ext/memcached.

Release Notes for Couchbase Client Library PHP 1.0.2 GA (20 April 2012)

This is a bugfix release of the Couchbase PHP SDK.

Fixes in 1.0.2

  • Fixed PCBC-62 (Extension reports wrong version).

  • Fixed PCBC-54 (Converting numbers in responses).

Release Notes for Couchbase Client Library PHP 1.0.1 GA (5 March 2012)

This is a bugfix release of the Couchbase PHP SDK.

Fixes in 1.0.1

  • Fixed build on Windows.

  • Fixed argument parsing for ::increment().

Release Notes for Couchbase Client Library PHP 1.0.0 GA (1 March 2012)

This is the first stable release of the Couchbase PHP SDK.

New Features and Behavior Changes in 1.0.0

  • Implemented PCBC-38 (Change connect() signature to take a URL).

Fixes in 1.0.0

  • Fixed tests, various segfaults and memory leaks.

  • Fixed naming of constants and features.

  • Renamed version() method and function to Couchbase::getVersion and couchbase_get_version() respectively.

  • Fixed PCBC-37 (Segfault when invalid hostname is provided).

  • Update compatibility with more recent libcouchbase releases.

  • Allow creation of non-existent keys with arithmetic calls.