├── .htaccess
├── README.md
├── config.php
├── index.php
└── lib
├── arrest-mysql.php
└── db.php
/.htaccess:
--------------------------------------------------------------------------------
1 |
50 | * $db_config = array(
51 | * 'server' => 'localhost',
52 | * 'database' => '',
53 | * 'username' => '',
54 | * 'password' => '',
55 | * 'verbose' => false
56 | * );
57 | *
58 | * @param string $base_uri Optional base URI if not in root folder
59 | * @access public
60 | */
61 | public function __construct($db_config, $base_uri = '')
62 | {
63 | $this->db = new Database($db_config);
64 | if(!$this->db->init()) throw new Exception($this->db->get_error());
65 |
66 | $this->db_structure = $this->map_db($db_config['database']);
67 | $this->segments = $this->get_uri_segments($base_uri);
68 | $this->table_index = array();
69 | }
70 |
71 | /**
72 | * Handle the REST calls and map them to corresponding CRUD
73 | *
74 | * @access public
75 | */
76 | public function rest()
77 | {
78 | header('Content-type: application/json');
79 | /*
80 | create > POST /table
81 | read > GET /table[/id]
82 | update > PUT /table/id
83 | delete > DELETE /table/id
84 | */
85 | switch ($_SERVER['REQUEST_METHOD']) {
86 | case 'POST':
87 | $this->create();
88 | break;
89 | case 'GET':
90 | $this->read();
91 | break;
92 | case 'PUT':
93 | $this->update();
94 | break;
95 | case 'DELETE':
96 | $this->delete();
97 | break;
98 | }
99 | }
100 |
101 | /**
102 | * Add a custom index (usually primary key) for a table
103 | *
104 | * @param string $table Name of the table
105 | * @param string $field Name of the index field
106 | * @access public
107 | */
108 | public function set_table_index($table, $field)
109 | {
110 | $this->table_index[$table] = $field;
111 | }
112 |
113 | /**
114 | * Map the stucture of the MySQL db to an array
115 | *
116 | * @param string $database Name of the database
117 | * @return array Returns array of db structure
118 | * @access private
119 | */
120 | private function map_db($database)
121 | {
122 | // Map db structure to array
123 | $tables_arr = array();
124 | $this->db->query('SHOW TABLES FROM '. $database);
125 | while($table = $this->db->fetch_array()){
126 | if(isset($table['Tables_in_'. $database])){
127 | $table_name = $table['Tables_in_'. $database];
128 | $tables_arr[$table_name] = array();
129 | }
130 | }
131 | foreach($tables_arr as $table_name=>$val){
132 | $this->db->query('SHOW COLUMNS FROM '. $table_name);
133 | $fields = $this->db->fetch_all();
134 | $tables_arr[$table_name] = $fields;
135 | }
136 | return $tables_arr;
137 | }
138 |
139 | /**
140 | * Get the URI segments from the URL
141 | *
142 | * @param string $base_uri Optional base URI if not in root folder
143 | * @return array Returns array of URI segments
144 | * @access private
145 | */
146 | private function get_uri_segments($base_uri)
147 | {
148 | // Fix REQUEST_URI if required
149 | if(!isset($_SERVER['REQUEST_URI'])){
150 | $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'], 1);
151 | if(isset($_SERVER['QUERY_STRING'])) $_SERVER['REQUEST_URI'] .= '?'. $_SERVER['QUERY_STRING'];
152 | }
153 |
154 | $url = '';
155 | $request_url = $_SERVER['REQUEST_URI'];
156 | $script_url = $_SERVER['PHP_SELF'];
157 | $request_url = str_replace($base_uri, '', $request_url);
158 | if($request_url != $script_url) $url = trim(preg_replace('/'. str_replace('/', '\/', str_replace('index.php', '', $script_url)) .'/', '', $request_url, 1), '/');
159 | $url = rtrim(preg_replace('/\?.*/', '', $url), '/');
160 |
161 | return explode('/', $url);
162 | }
163 |
164 | /**
165 | * Get a URI segment
166 | *
167 | * @param int $index Index of the URI segment
168 | * @return mixed Returns URI segment or false if none exists
169 | * @access private
170 | */
171 | private function segment($index)
172 | {
173 | if(isset($this->segments[$index])) return $this->segments[$index];
174 | return false;
175 | }
176 |
177 | /**
178 | * Handles a POST and inserts into the database
179 | *
180 | * @access private
181 | */
182 | private function create()
183 | {
184 | $table = $this->segment(0);
185 |
186 | if(!$table || !isset($this->db_structure[$table])){
187 | $error = array('error' => array(
188 | 'message' => 'Not Found',
189 | 'code' => 404
190 | ));
191 | die(json_encode($error));
192 | }
193 |
194 | if($data = $this->_post()){
195 | $this->db->insert($table, $data)
196 | ->query();
197 | $success = array('success' => array(
198 | 'message' => 'Success',
199 | 'code' => 200
200 | ));
201 | die(json_encode($success));
202 | } else {
203 | $error = array('error' => array(
204 | 'message' => 'No Content',
205 | 'code' => 204
206 | ));
207 | die(json_encode($error));
208 | }
209 | }
210 |
211 | /**
212 | * Handles a GET and reads from the database
213 | *
214 | * @access private
215 | */
216 | private function read()
217 | {
218 | $table = $this->segment(0);
219 | $id = intval($this->segment(1));
220 |
221 | if(!$table || !isset($this->db_structure[$table])){
222 | $error = array('error' => array(
223 | 'message' => 'Not Found',
224 | 'code' => 404
225 | ));
226 | die(json_encode($error));
227 | }
228 |
229 | if($id && is_int($id)) {
230 | $index = 'id';
231 | if(isset($this->table_index[$table])) $index = $this->table_index[$table];
232 | $this->db->select('*')
233 | ->from($table)
234 | ->where($index, $id)
235 | ->query();
236 | if($result = $this->db->fetch_array()){
237 | die(json_encode($result));
238 | } else {
239 | $error = array('error' => array(
240 | 'message' => 'No Content',
241 | 'code' => 204
242 | ));
243 | die(json_encode($error));
244 | }
245 | } else {
246 | $this->db->select('*')
247 | ->from($table)
248 | ->order_by($this->_get('order_by'), $this->_get('order'))
249 | ->limit(intval($this->_get('limit')), intval($this->_get('offset')))
250 | ->query();
251 | if($result = $this->db->fetch_all()){
252 | die(json_encode($result));
253 | } else {
254 | $error = array('error' => array(
255 | 'message' => 'No Content',
256 | 'code' => 204
257 | ));
258 | die(json_encode($error));
259 | }
260 | }
261 | }
262 |
263 | /**
264 | * Handles a PUT and updates the database
265 | *
266 | * @access private
267 | */
268 | private function update()
269 | {
270 | $table = $this->segment(0);
271 | $id = intval($this->segment(1));
272 |
273 | if(!$table || !isset($this->db_structure[$table]) || !$id){
274 | $error = array('error' => array(
275 | 'message' => 'Not Found',
276 | 'code' => 404
277 | ));
278 | die(json_encode($error));
279 | }
280 |
281 | $index = 'id';
282 | if(isset($this->table_index[$table])) $index = $this->table_index[$table];
283 | $this->db->select('*')
284 | ->from($table)
285 | ->where($index, $id)
286 | ->query();
287 | if($result = $this->db->fetch_array()){
288 | $this->db->update($table)
289 | ->set($this->_put())
290 | ->where($index, $id)
291 | ->query();
292 | $success = array('success' => array(
293 | 'message' => 'Success',
294 | 'code' => 200
295 | ));
296 | die(json_encode($success));
297 | } else {
298 | $error = array('error' => array(
299 | 'message' => 'No Content',
300 | 'code' => 204
301 | ));
302 | die(json_encode($error));
303 | }
304 | }
305 |
306 | /**
307 | * Handles a DELETE and deletes from the database
308 | *
309 | * @access private
310 | */
311 | private function delete()
312 | {
313 | $table = $this->segment(0);
314 | $id = intval($this->segment(1));
315 |
316 | if(!$table || !isset($this->db_structure[$table]) || !$id){
317 | $error = array('error' => array(
318 | 'message' => 'Not Found',
319 | 'code' => 404
320 | ));
321 | die(json_encode($error));
322 | }
323 |
324 | $index = 'id';
325 | if(isset($this->table_index[$table])) $index = $this->table_index[$table];
326 | $this->db->select('*')
327 | ->from($table)
328 | ->where($index, $id)
329 | ->query();
330 | if($result = $this->db->fetch_array()){
331 | $this->db->delete($table)
332 | ->where($index, $id)
333 | ->query();
334 | $success = array('success' => array(
335 | 'message' => 'Success',
336 | 'code' => 200
337 | ));
338 | die(json_encode($success));
339 | } else {
340 | $error = array('error' => array(
341 | 'message' => 'No Content',
342 | 'code' => 204
343 | ));
344 | die(json_encode($error));
345 | }
346 | }
347 |
348 | /**
349 | * Helper function to retrieve $_GET variables
350 | *
351 | * @param string $index Optional $_GET index
352 | * @return mixed Returns the $_GET var at the specified index,
353 | * the whole $_GET array or false
354 | * @access private
355 | */
356 | private function _get($index = '')
357 | {
358 | if($index){
359 | if(isset($_GET[$index]) && $_GET[$index]) return strip_tags($_GET[$index]);
360 | } else {
361 | if(isset($_GET) && !empty($_GET)) return $_GET;
362 | }
363 | return false;
364 | }
365 |
366 | /**
367 | * Helper function to retrieve $_POST variables
368 | *
369 | * @param string $index Optional $_POST index
370 | * @return mixed Returns the $_POST var at the specified index,
371 | * the whole $_POST array or false
372 | * @access private
373 | */
374 | private function _post($index = '')
375 | {
376 | if($index){
377 | if(isset($_POST[$index]) && $_POST[$index]) return $_POST[$index];
378 | } else {
379 | if(isset($_POST) && !empty($_POST)) return $_POST;
380 | }
381 | return false;
382 | }
383 |
384 | /**
385 | * Helper function to retrieve PUT variables
386 | *
387 | * @return mixed Returns the contents of PUT as an array
388 | * @access private
389 | */
390 | private function _put()
391 | {
392 | $output = array();
393 | parse_str(file_get_contents('php://input'), $output);
394 | return $output;
395 | }
396 |
397 | }
398 |
399 | ?>
--------------------------------------------------------------------------------
/lib/db.php:
--------------------------------------------------------------------------------
1 | _config = $config;
19 | }
20 |
21 | /*
22 | * Initializes the database. Checks the configuration, connects, selects database.
23 | */
24 | public function init() {
25 | if(!$this->__check_config()) {
26 | return false;
27 | }
28 |
29 | if(!$this->__connect()) {
30 | return false;
31 | }
32 |
33 | if(!$this->__select_db()) {
34 | return false;
35 | }
36 |
37 | return true;
38 | }
39 |
40 | /*
41 | * Checks the configuration for blanks.
42 | */
43 | private function __check_config() {
44 | $config = $this->_config;
45 |
46 | if(empty($config["server"]) || empty($config["username"]) || empty($config["database"])) {
47 | $this->_error = "Configuration details were blank.";
48 | return false;
49 | }
50 |
51 | $this->_verbose = ($config["verbose"]) ? true : false;
52 |
53 | return true;
54 | }
55 |
56 | /*
57 | * Connects to the database.
58 | */
59 | private function __connect() {
60 | $connection = @mysql_connect($this->_config["server"], $this->_config["username"], $this->_config["password"]);
61 |
62 | if(!$connection) {
63 | $this->_error = ($this->_verbose) ? mysql_error() : "Could not connect to database.";
64 | return false;
65 | }
66 |
67 | return true;
68 | }
69 |
70 | /*
71 | * Selects the database to be working with.
72 | */
73 | private function __select_db() {
74 | $database = @mysql_select_db($this->_config["database"]);
75 |
76 | if(!$database) {
77 | $this->_error = ($this->_verbose) ? mysql_error() : "Could not select database.";
78 | return false;
79 | }
80 |
81 | return true;
82 | }
83 |
84 | /*
85 | * SELECT starter. $fields can be either a string or an array of strings to select.
86 | */
87 | public function select($fields) {
88 | $query = "SELECT";
89 |
90 | if(!empty($fields) && !is_array($fields)) {
91 | $query .= " {$fields}";
92 | } else if(is_array($fields)) {
93 | $query .= " `";
94 | $query .= implode("`,`", $fields);
95 | $query .= "`";
96 | } else {
97 | $query .= " *";
98 | }
99 |
100 | $this->_buildQuery = $query;
101 | return $this;
102 | }
103 |
104 | /*
105 | * Adds where the SELECT is going to be coming from (table wise).
106 | * select("*")
107 | * select("username")
108 | * select(array("username", "password"))
109 | */
110 | public function from($table) {
111 | $this->_buildQuery .= " FROM `{$table}`";
112 | return $this;
113 | }
114 |
115 | /*
116 | * UPDATE starter.
117 | * update("users")
118 | */
119 | public function update($table) {
120 | $this->_buildQuery = "UPDATE `{$table}`";
121 | return $this;
122 | }
123 |
124 | /*
125 | * DELETE starter.
126 | * delete("users")
127 | */
128 | public function delete($table) {
129 | $this->_buildQuery = "DELETE FROM `{$table}`";
130 | return $this;
131 | }
132 |
133 | /*
134 | * INSERT starter. $data is an array matched columns to values:
135 | * $data = array("username" => "Caleb", "email" => "caleb@mingle-graphics.com");
136 | * insert("users", array("username" => "Caleb", "password" => "hash"))
137 | */
138 | public function insert($table, $data) {
139 | $query = "INSERT INTO `{$table}` (";
140 | $keys = array_keys($data);
141 | $values = array_values($data);
142 |
143 | $query .= implode(", ", $keys);
144 | $query .= ") VALUES (";
145 |
146 | $array = array();
147 |
148 | foreach($values as $value) {
149 | $array[] = "'{$value}'";
150 | }
151 |
152 | $query .= implode(", ", $array) . ")";
153 |
154 | $this->_buildQuery = $query;
155 | return $this;
156 | }
157 |
158 | /*
159 | * SET. $data is an array matched key => value.
160 | * set(array("username" => "Caleb"))
161 | */
162 | public function set($data) {
163 | if(!is_array($data)) return $this;
164 |
165 | $query = "SET ";
166 | $array = array();
167 |
168 | foreach($data as $key => $value) {
169 | $array[] = "`{$key}`='{$value}'";
170 | }
171 |
172 | $query .= implode(", ", $array);
173 |
174 | $this->_buildQuery .= " " . $query;
175 | return $this;
176 | }
177 |
178 | /*
179 | * WHERE. $fields and $values can either be strings or arrays based on how many you need.
180 | * $operators can be an array to add in <, >, etc. Must match the index for $fields and $values.
181 | * where("username", "Caleb")
182 | * where(array("username", "password"), array("Caleb", "testing"))
183 | * where(array("username", "level"), array("Caleb", "10"), array("=", "<"))
184 | */
185 | public function where($fields, $values, $operators = '') {
186 | if(!is_array($fields) && !is_array($values)) {
187 | $operator = (empty($operators)) ? '=' : $operators[0];
188 | $query = " WHERE `{$fields}` {$operator} '{$values}'";
189 | } else {
190 | $array = array_combine($fields, $values);
191 | $query = " WHERE ";
192 |
193 | $data = array();
194 | $counter = 0;
195 |
196 | foreach($array as $key => $value) {
197 |
198 | $operator = (!empty($operators) && !empty($operators[$counter])) ? $operators[$counter] : '=';
199 |
200 | $data[] = "`{$key}` {$operator} '{$value}'";
201 |
202 | $counter++;
203 | }
204 |
205 | $query .= implode(" AND ", $data);
206 | }
207 |
208 | $this->_buildQuery .= $query;
209 | return $this;
210 | }
211 |
212 | /*
213 | * Order By:
214 | * order_by("username", "asc")
215 | */
216 | public function order_by($field, $direction = 'asc') {
217 | if($field) $this->_buildQuery .= " ORDER BY `{$field}` " . strtoupper($direction);
218 | return $this;
219 | }
220 |
221 | /*
222 | * Limit:
223 | * limit(1)
224 | * limit(1, 0)
225 | */
226 | public function limit($max, $min = '0') {
227 | if($max) $this->_buildQuery .= " LIMIT {$min},{$max}";
228 | return $this;
229 | }
230 |
231 | /*
232 | * Will return the object of data from the query.
233 | */
234 | public function fetch_object() {
235 | $object = @mysql_fetch_object($this->_query);
236 |
237 | if(!$object && $this->_verbose) {
238 | $this->_error = mysql_error();
239 | }
240 |
241 | return $object;
242 | }
243 |
244 | /*
245 | * Will return the array of data from the query.
246 | */
247 | public function fetch_array() {
248 | $array = @mysql_fetch_array($this->_query);
249 | if($array){
250 | foreach($array as $key=>$val){
251 | if(is_numeric($key)){
252 | unset($array[$key]);
253 | }
254 | }
255 | }
256 |
257 | if(!$array && $this->_verbose) {
258 | $this->_error = mysql_error();
259 | }
260 |
261 | return $array;
262 | }
263 |
264 | public function fetch_all() {
265 | $results = array();
266 | while($array = @mysql_fetch_array($this->_query)){
267 | foreach($array as $key=>$val){
268 | if(is_numeric($key)){
269 | unset($array[$key]);
270 | }
271 | }
272 | $results[] = $array;
273 | }
274 |
275 |
276 |
277 | if(!$array && $this->_verbose) {
278 | $this->_error = mysql_error();
279 | }
280 |
281 | return $results;
282 | }
283 |
284 | /*
285 | * Will return the number or rows affected from the query.
286 | */
287 | public function num_rows() {
288 | $num = @mysql_num_rows($this->_query);
289 |
290 | if(!$num && $this->_verbose) {
291 | $this->_error = mysql_error();
292 | }
293 |
294 | return $num;
295 | }
296 |
297 | /*
298 | * If $query_text is blank, query will be performed on the built query stored.
299 | */
300 | public function query($query_text = '') {
301 | $query_text = ($query_text == '') ? $this->_buildQuery : $query_text;
302 |
303 | $query = @mysql_query($query_text);
304 |
305 | if(!$query && $this->_verbose) {
306 | echo "
" . mysql_error() . "
"; 308 | } 309 | 310 | $this->_query = $query; 311 | 312 | return $this; 313 | } 314 | 315 | /* 316 | * Will return the current built query story in $this->_buildQuery; 317 | */ 318 | public function get_query() { 319 | return $this->_buildQuery; 320 | } 321 | 322 | /* 323 | * Will return the current stored error. 324 | */ 325 | public function get_error() { 326 | return $this->_error; 327 | } 328 | } 329 | 330 | ?> --------------------------------------------------------------------------------