Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 280 lines (236 sloc) 11.01 kB
cd88857 @kallaspriit Updates README.md.
authored
1 Cassandra PHP Client Library
2 ============================
3
6eaaccd @kallaspriit Updated README.md with logo.
authored
4 ![Cassandra PHP Client Library logo](http://dl.dropbox.com/u/8855759/cpcl/logo.png "CPCL logo")
cd88857 @kallaspriit Updates README.md.
authored
5
5529e56 @kallaspriit Added markdown README.md file.
authored
6 Cassandra PHP Client Library or **CPCL** for short allows for **managing and querying your Cassandra cluster**. It's a **high-level library** performing all the rather complex low-level heavy lifting and provides a **simple to learn and use interface**.
7
8 Features
9 --------
10 - simple and intuitive interface
11 - well covered with unit tests (> 90%)
12 - support for multiple server pools using named singletons
13 - requires including a single file
14 - uses reasonable defaults through-out
15 - powerful syntax for querying data
16 - enables managing keyspaces and column-families
17 - automatic packing of datatypes using column metadata
18 - retries failed queries using back-off strategy
19 - built with performance in mind (caches schema description etc)
20 - well documented API and a working example
21
22 Class diagram
23 -------------
70e94ca @kallaspriit Updated placement strategies.
authored
24 ![CPCL class diagram](https://github.com/kallaspriit/Cassandra-PHP-Client-Library/blob/master/doc/class-diagram.png?raw=true "Cassandra PHP Client Library class diagram")
5529e56 @kallaspriit Added markdown README.md file.
authored
25
26 The library uses the very permissive [MIT licence](http://en.wikipedia.org/wiki/MIT_License) which means you can **do pretty much anything you like with it**.
27
28 Example
29 -------
30 The following example covers most of what you need to know to use this library. It should work out-of-box on a machine with default cassandra setup running. The example file is contained in the download.
31
32 [Click here](https://github.com/kallaspriit/Cassandra-PHP-Client-Library/blob/master/example.php "Cassandra PHP Client Library example code") for prettier code.
33
34 <?php
35
36 // show all the errors
37 error_reporting(E_ALL);
38
39 // the only file that needs including into your project
40 require_once 'Cassandra.php';
41
42 // list of seed servers to randomly connect to
43 // all the parameters are optional and default to given values
44 $servers = array(
45 array(
46 'host' => '127.0.0.1',
47 'port' => 9160,
48 'use-framed-transport' => true,
49 'send-timeout-ms' => 1000,
50 'receive-timeout-ms' => 1000
51 )
52 );
53
54 // create a named singleton, the second parameter name defaults to "main"
55 // you can have several named singletons with different server pools
56 $cassandra = Cassandra::createInstance($servers);
57
58 // at any point in code, you can get the named singleton instance, the name
59 // again defaults to "main" so no need to define it if using single instance
60 $cassandra2 = Cassandra::getInstance();
61
62 // drop the example keyspace and ignore errors should it not exist
63 try {
64 $cassandra->dropKeyspace('CassandraExample');
65 } catch (Exception $e) {}
66
67
68 // create a new keyspace, accepts extra parameters for replication options
69 // normally you don't do it every time
70 $cassandra->createKeyspace('CassandraExample');
71
72 // start using the created keyspace
73 $cassandra->useKeyspace('CassandraExample');
74
75 // if a request fails, it will be retried for this many times, each time backing
76 // down for a bit longer period to prevent floods; defaults to 5
77 $cassandra->setMaxCallRetries(5);
78
79 // create a standard column family with given column metadata
80 $cassandra->createStandardColumnFamily(
81 'CassandraExample', // keyspace name
82 'user', // the column-family name
83 array( // list of columns with metadata
84 array(
85 'name' => 'name',
86 'type' => Cassandra::TYPE_UTF8,
87 'index-type' => Cassandra::INDEX_KEYS, // create secondary index
88 'index-name' => 'NameIdx'
89 ),
90 array(
91 'name' => 'email',
92 'type' => Cassandra::TYPE_UTF8
93 ),
94 array(
95 'name' => 'age',
96 'type' => Cassandra::TYPE_INTEGER,
97 'index-type' => Cassandra::INDEX_KEYS,
98 'index-name' => 'AgeIdx'
99 )
100 )
101 // actually accepts more parameters with reasonable defaults
102 );
103
104 // create a super column family
105 $cassandra->createSuperColumnFamily(
106 'CassandraExample',
107 'cities',
108 array(
109 array(
110 'name' => 'population',
111 'type' => Cassandra::TYPE_INTEGER
112 ),
113 array(
114 'name' => 'comment',
115 'type' => Cassandra::TYPE_UTF8
116 )
117 ),
118 // see the definition for these additional optional parameters
119 Cassandra::TYPE_UTF8,
120 Cassandra::TYPE_UTF8,
121 Cassandra::TYPE_UTF8,
122 'Capitals supercolumn test',
123 1000,
124 1000,
125 0.5
126 );
127
128 // lets fetch and display the schema of created keyspace
129 $schema = $cassandra->getKeyspaceSchema('CassandraExample');
130 echo 'Schema: <pre>'.print_r($schema, true).'</pre><hr/>';
131 /*
132 // should we need to, we can access the low-level client directly
133 $version = $cassandra->getConnection()->getClient()->describe_version();
134 echo 'Version directly: <pre>'.print_r($version, true).'</pre><hr/>';
135 */
136 // if implemented, use the wrapped methods as these are smarter - can retry etc
137 $version = $cassandra->getVersion();
138 echo 'Version through wrapper: <pre>'.print_r($version, true).'</pre><hr/>';
139
140 // cluster is a pool of connections
141 $cluster = $cassandra->getCluster();
142 echo 'Cluster: <pre>'.print_r($cluster, true).'</pre><hr/>';
143
144 // you can ask the cluster for a connection to a random seed server from pool
145 $connection = $cluster->getConnection();
146 echo 'Connection: <pre>'.print_r($connection, true).'</pre><hr/>';
147
148 // access column family, using the singleton syntax
149 // there is shorter "cf" methid that is an alias to "columnFamily"
150 $userColumnFamily = Cassandra::getInstance()->columnFamily('user');
151 echo 'Column family "user": <pre>'.print_r($userColumnFamily, true).'</pre><hr/>';
152
153 // lets insert some test data using the convinience method "set" of Cassandra
154 // the syntax is COLUMN_FAMILY_NAME.KEY_NAME
155 $cassandra->set(
156 'user.john',
157 array(
158 'email' => 'john@smith.com',
159 'name' => 'John Smith',
160 'age' => 34
161 )
162 );
163
164 // when inserting data, it's ok if key name contains ".", no need to escape them
165 $cassandra->set(
166 'user.jane.doe',
167 array(
168 'email' => 'jane@doe.com',
169 'name' => 'Jane Doe',
170 'age' => 24
171 )
172 );
173
174 // longer way of inserting data, first getting the column family
175 $cassandra->cf('user')->set(
176 'chuck', // key name
177 array( // column names and values
178 'email' => 'chuck@norris.com',
179 'name' => 'Chuck Norris',
180 'age' => 24
181 ),
182 Cassandra::CONSISTENCY_QUORUM // optional consistency to use
183 // also accepts optional custom timestamp and time to live
184 );
185
186 // lets fetch all the information about user john
187 $john = $cassandra->get('user.john');
188 echo 'User "john": <pre>'.print_r($john, true).'</pre><hr/>';
189
190 // since the jane key "jane.doe" includes a ".", we have to escape it
191 $jane = $cassandra->get('user.'.Cassandra::escape('jane.doe'));
192 echo 'User "jane.doe": <pre>'.print_r($jane, true).'</pre><hr/>';
193
194 // there is some syntatic sugar on the query of Cassandra::get() allowing you
195 // to fetch specific columns, ranges of them, limit amount etc. for example,
196 // lets only fetch columns name and age
197 $chuck = $cassandra->get('user.chuck:name,age');
198 echo 'User "chuck", name and age: <pre>'.print_r($chuck, true).'</pre><hr/>';
199
200 // fetch all solumns from age to name (gets all columns in-between too)
201 $chuck2 = $cassandra->get('user.chuck:age-name');
202 echo 'User "chuck", columns ago to name: <pre>'.print_r($chuck2, true).'</pre><hr/>';
203
204 // the range columns do not need to exist, we can get character ranges
205 $chuck3 = $cassandra->get('user.chuck:a-z');
206 echo 'User "chuck", columns a-z: <pre>'.print_r($chuck3, true).'</pre><hr/>';
207
208 // when performing range queries, we can also limit the number of columns
209 // returned (2); also the method accepts consistency level as second parameter
210 $chuck4 = $cassandra->get('user.chuck:a-z|2', Cassandra::CONSISTENCY_ALL);
211 echo 'User "chuck", columns a-z, limited to 2 columns: <pre>'.print_r($chuck4, true).'</pre><hr/>';
212
213 // the Cassandra::get() is a convinience method proxying to lower level
214 // CassandraColumnFamily::get(), no need to worry about escaping with this.
215 // column family has additional methods getAll(), getColumns(), getColumnRange()
216 // that all map to lower level get() calls with more appopriate parameters
217 $jane2 = $cassandra->cf('user')->get('jane.doe');
218 echo 'User "jane.doe", lower level api: <pre>'.print_r($jane2, true).'</pre><hr/>';
219
220 // we defined a secondary index on "age" column of "user" column family so we
221 // can use CassandraColumnFamily::getWhere() to fetch users of specific age.
222 // this returns an iterator that you can go over with foreach or use the
223 // getAll() method that fetches all the data and returns an array
224 $aged24 = $cassandra->cf('user')->getWhere(array('age' => 24));
225 echo 'Users at age 24: <pre>'.print_r($aged24->getAll(), true).'</pre><hr/>';
226
227 // if we know we are going to need to values of several keys, we can request
228 // them in a single query for better performance
229 $chuckAndJohn = $cassandra->cf('user')->getMultiple(array('chuck', 'john'));
230 echo 'Users "chuck" and "john": <pre>'.print_r($chuckAndJohn, true).'</pre><hr/>';
231
232 /* Uncomment this when using order preserving partitioner
233 // we can fetch a range of keys but this is predictable only if using an
234 // order preserving partitioner, Cassandra defaults to random one
235 // again as there may be more results than it's reasonable to fetch in a single
236 // query, an iterator is returned that can make several smaller range queries
237 // as the data is iterated
238 $usersAZ = $cassandra->cf('user')->getKeyRange('a', 'z');
239 echo 'Users with keys in range a-z: <pre>'.print_r($usersAZ->getAll(), true).'</pre><hr/>';
240 */
241
242 // find the number of columns a key has, we could also request for ranges
243 $chuckColumnCount = $cassandra->cf('user')->getColumnCount('chuck');
244 echo 'User "chuck" column count: <pre>'.print_r($chuckColumnCount, true).'</pre><hr/>';
245
246 // we can find column counts for several keys at once
247 $chuckJaneColumnCounts = $cassandra->cf('user')->getColumnCounts(array('chuck', 'jane.doe'));
248 echo 'User "chuck" and "jane.doe" column counts: <pre>'.print_r($chuckJaneColumnCounts, true).'</pre><hr/>';
249
250 // setting supercolumn values is similar to normal column families
251 $cassandra->set(
252 'cities.Estonia',
253 array(
254 'Tallinn' => array(
255 'population' => '411980',
256 'comment' => 'Capital of Estonia',
257 'size' => 'big'
258 ),
259 'Tartu' => array(
260 'population' => '98589',
261 'comment' => 'City of good thoughts',
262 'size' => 'medium'
263 )
264 )
265 );
266
267 // fetch all columns of Tartu in Estonia of cities
268 $tartu = $cassandra->cf('cities')->getAll('Estonia', 'Tartu');
269 echo 'Super-column cities.Estonia.Tartu: <pre>'.print_r($tartu, true).'</pre><hr/>';
270
271 // we could also use the higher level Cassandra::get() to fetch supercolumn info
272 // we can still use the additional filters of columns
273 $tallinn = $cassandra->get('cities.Estonia.Tallinn:population,size');
274 echo 'Super-column cities.Estonia.Tallinn: <pre>'.print_r($tallinn, true).'</pre><hr/>';
275
276 // you can delete all the data in a column family using "truncate"
277 $cassandra->truncate('user');
278
279 // you may choose to drop an entire keyspace
280 $cassandra->dropKeyspace('CassandraExample');
Something went wrong with that request. Please try again.