blob: 90f58ae0e6a47432a14f78155fcd0b3ac7bcf2b6 [file] [log] [blame]
adminac94f382006-09-24 20:28:12 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
admine334c472006-10-21 19:44:22 +000010 * @license http://www.codeignitor.com/user_guide/license.html
adminac94f382006-09-24 20:28:12 +000011 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
admine334c472006-10-21 19:44:22 +000015
adminac94f382006-09-24 20:28:12 +000016// ------------------------------------------------------------------------
17
18/**
19 * Active Record Class
admine334c472006-10-21 19:44:22 +000020 *
adminac94f382006-09-24 20:28:12 +000021 * This is the platform-independent base Active Record implementation class.
22 *
23 * @package CodeIgniter
24 * @subpackage Drivers
25 * @category Database
26 * @author Rick Ellis
27 * @link http://www.codeigniter.com/user_guide/database/
28 */
29class CI_DB_active_record extends CI_DB_driver {
30
31 var $ar_select = array();
32 var $ar_distinct = FALSE;
33 var $ar_from = array();
34 var $ar_join = array();
35 var $ar_where = array();
36 var $ar_like = array();
37 var $ar_groupby = array();
38 var $ar_having = array();
39 var $ar_limit = FALSE;
40 var $ar_offset = FALSE;
41 var $ar_order = FALSE;
42 var $ar_orderby = array();
43 var $ar_set = array();
44
45
46 /**
47 * Select
48 *
49 * Generates the SELECT portion of the query
50 *
51 * @access public
52 * @param string
53 * @return object
54 */
55 function select($select = '*')
56 {
57 if (is_string($select))
58 {
59 $select = explode(',', $select);
60 }
61
62 foreach ($select as $val)
63 {
64 $val = trim($val);
65
66 if ($val != '')
67 $this->ar_select[] = $val;
68 }
69 return $this;
70 }
71
72 // --------------------------------------------------------------------
73
74 /**
75 * DISTINCT
76 *
77 * Sets a flag which tells the query string compiler to add DISTINCT
78 *
79 * @access public
80 * @param bool
81 * @return object
82 */
83 function distinct($val = TRUE)
84 {
85 $this->ar_distinct = (is_bool($val)) ? $val : TRUE;
86 return $this;
87 }
88
89 // --------------------------------------------------------------------
90
91 /**
92 * From
93 *
94 * Generates the FROM portion of the query
95 *
96 * @access public
97 * @param mixed can be a string or array
98 * @return object
99 */
100 function from($from)
101 {
102 foreach ((array)$from as $val)
103 {
104 $this->ar_from[] = $this->dbprefix.$val;
105 }
106 return $this;
107 }
108
109 // --------------------------------------------------------------------
110
111 /**
112 * Join
113 *
114 * Generates the JOIN portion of the query
115 *
116 * @access public
117 * @param string
118 * @param string the join condition
119 * @param string the type of join
120 * @return object
121 */
122 function join($table, $cond, $type = '')
123 {
124 if ($type != '')
125 {
126 $type = strtoupper(trim($type));
127
adminee54c112006-09-28 17:13:38 +0000128 if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE))
adminac94f382006-09-24 20:28:12 +0000129 {
130 $type = '';
131 }
132 else
133 {
134 $type .= ' ';
135 }
136 }
137
admin402d1d52006-09-27 01:54:14 +0000138 $this->ar_join[] = $type.'JOIN '.$this->dbprefix.$table.' ON '.$cond;
adminac94f382006-09-24 20:28:12 +0000139 return $this;
140 }
141
142 // --------------------------------------------------------------------
143
144 /**
145 * Where
146 *
147 * Generates the WHERE portion of the query. Separates
148 * multiple calls with AND
149 *
150 * @access public
151 * @param mixed
152 * @param mixed
153 * @return object
154 */
155 function where($key, $value = NULL)
156 {
157 return $this->_where($key, $value, 'AND ');
158 }
159
160 // --------------------------------------------------------------------
161
162 /**
163 * OR Where
164 *
165 * Generates the WHERE portion of the query. Separates
166 * multiple calls with OR
167 *
168 * @access public
169 * @param mixed
170 * @param mixed
171 * @return object
172 */
173 function orwhere($key, $value = NULL)
174 {
175 return $this->_where($key, $value, 'OR ');
176 }
177
178 // --------------------------------------------------------------------
179
180 /**
181 * Where
182 *
183 * Called by where() or orwhere()
184 *
185 * @access private
186 * @param mixed
187 * @param mixed
188 * @param string
189 * @return object
190 */
191 function _where($key, $value = NULL, $type = 'AND ')
192 {
193 if ( ! is_array($key))
194 {
195 $key = array($key => $value);
196 }
197
198 foreach ($key as $k => $v)
199 {
200 $prefix = (count($this->ar_where) == 0) ? '' : $type;
201
202 if ( ! is_null($v))
203 {
204 if ( ! $this->_has_operator($k))
205 {
206 $k .= ' =';
207 }
208
209 $v = ' '.$this->escape($v);
210 }
211
212 $this->ar_where[] = $prefix.$k.$v;
213 }
214 return $this;
215 }
216
217
218
219 // --------------------------------------------------------------------
220
221 /**
222 * Like
223 *
224 * Generates a %LIKE% portion of the query. Separates
225 * multiple calls with AND
226 *
227 * @access public
228 * @param mixed
229 * @param mixed
230 * @return object
231 */
232 function like($field, $match = '')
233 {
234 return $this->_like($field, $match, 'AND ');
235 }
236
237 // --------------------------------------------------------------------
238
239 /**
240 * OR Like
241 *
242 * Generates a %LIKE% portion of the query. Separates
243 * multiple calls with OR
244 *
245 * @access public
246 * @param mixed
247 * @param mixed
248 * @return object
249 */
250 function orlike($field, $match = '')
251 {
252 return $this->_like($field, $match, 'OR ');
253 }
254
255 // --------------------------------------------------------------------
256
257 /**
258 * Like
259 *
260 * Called by like() or orlike()
261 *
262 * @access private
263 * @param mixed
264 * @param mixed
265 * @param string
266 * @return object
267 */
268 function _like($field, $match = '', $type = 'AND ')
269 {
270 if ( ! is_array($field))
271 {
272 $field = array($field => $match);
273 }
274
275 foreach ($field as $k => $v)
276 {
277 $prefix = (count($this->ar_like) == 0) ? '' : $type;
278
279 $v = $this->escape_str($v);
280
281 $this->ar_like[] = $prefix." $k LIKE '%{$v}%'";
282 }
283 return $this;
284 }
285
286 // --------------------------------------------------------------------
287
288 /**
289 * GROUP BY
290 *
291 * @access public
292 * @param string
293 * @return object
294 */
295 function groupby($by)
296 {
297 if (is_string($by))
298 {
299 $by = explode(',', $by);
300 }
301
302 foreach ($by as $val)
303 {
304 $val = trim($val);
305
306 if ($val != '')
307 $this->ar_groupby[] = $val;
308 }
309 return $this;
310 }
311
312 // --------------------------------------------------------------------
313
314 /**
315 * Sets the HAVING value
316 *
317 * Separates multiple calls with AND
318 *
319 * @access public
320 * @param string
321 * @param string
322 * @return object
323 */
324 function having($key, $value = '')
325 {
326 return $this->_having($key, $value, 'AND ');
327 }
328
329 // --------------------------------------------------------------------
330
331 /**
332 * Sets the OR HAVING value
333 *
334 * Separates multiple calls with OR
335 *
336 * @access public
337 * @param string
338 * @param string
339 * @return object
340 */
341 function orhaving($key, $value = '')
342 {
343 return $this->_having($key, $value, 'OR ');
344 }
345
346 // --------------------------------------------------------------------
347
348 /**
349 * Sets the HAVING values
350 *
351 * Called by having() or orhaving()
352 *
353 * @access private
354 * @param string
355 * @param string
356 * @return object
357 */
358 function _having($key, $value = '', $type = 'AND ')
359 {
360 if ( ! is_array($key))
361 {
362 $key = array($key => $value);
363 }
364
365 foreach ($key as $k => $v)
366 {
367 $prefix = (count($this->ar_having) == 0) ? '' : $type;
368
369 if ($v != '')
370 {
371 $v = ' '.$this->escape($v);
372 }
373
374 $this->ar_having[] = $prefix.$k.$v;
375 }
376 return $this;
377 }
378
379 // --------------------------------------------------------------------
380
381 /**
382 * Sets the ORDER BY value
383 *
384 * @access public
385 * @param string
386 * @param string direction: asc or desc
387 * @return object
388 */
389 function orderby($orderby, $direction = '')
390 {
391 if (trim($direction) != '')
392 {
adminee54c112006-09-28 17:13:38 +0000393 $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC', 'RAND()'), TRUE)) ? ' '.$direction : ' ASC';
adminac94f382006-09-24 20:28:12 +0000394 }
395
396 $this->ar_orderby[] = $orderby.$direction;
397 return $this;
398 }
399
400 // --------------------------------------------------------------------
401
402 /**
403 * Sets the LIMIT value
404 *
405 * @access public
406 * @param integer the limit value
407 * @param integer the offset value
408 * @return object
409 */
410 function limit($value, $offset = '')
411 {
412 $this->ar_limit = $value;
413
414 if ($offset != '')
415 $this->ar_offset = $offset;
416
417 return $this;
418 }
419
420 // --------------------------------------------------------------------
421
422 /**
423 * Sets the OFFSET value
424 *
425 * @access public
426 * @param integer the offset value
427 * @return object
428 */
429 function offset($value)
430 {
431 $this->ar_offset = $value;
432 return $this;
433 }
434
435 // --------------------------------------------------------------------
436
437 /**
438 * The "set" function. Allows key/value pairs to be set for inserting or updating
439 *
440 * @access public
441 * @param mixed
442 * @param string
443 * @return object
444 */
445 function set($key, $value = '')
446 {
447 $key = $this->_object_to_array($key);
448
449 if ( ! is_array($key))
450 {
451 $key = array($key => $value);
452 }
453
454 foreach ($key as $k => $v)
455 {
456 $this->ar_set[$k] = $this->escape($v);
457 }
458
459 return $this;
460 }
461
462 // --------------------------------------------------------------------
463
464 /**
465 * Get
466 *
467 * Compiles the select statement based on the other functions called
468 * and runs the query
469 *
470 * @access public
471 * @param string the limit clause
472 * @param string the offset clause
473 * @return object
474 */
475 function get($table = '', $limit = null, $offset = null)
476 {
477 if ($table != '')
478 {
479 $this->from($table);
480 }
481
482 if ( ! is_null($limit))
483 {
484 $this->limit($limit, $offset);
485 }
486
487 $sql = $this->_compile_select();
488
adminc50747c2006-11-03 17:17:02 +0000489 $result = $this->query($sql);
adminac94f382006-09-24 20:28:12 +0000490 $this->_reset_select();
adminc50747c2006-11-03 17:17:02 +0000491 return $result;
adminac94f382006-09-24 20:28:12 +0000492 }
493
494 // --------------------------------------------------------------------
495
496 /**
497 * GetWhere
498 *
499 * Allows the where clause, limit and offset to be added directly
500 *
501 * @access public
502 * @param string the where clause
503 * @param string the limit clause
504 * @param string the offset clause
505 * @return object
506 */
507 function getwhere($table = '', $where = null, $limit = null, $offset = null)
508 {
509 if ($table != '')
510 {
511 $this->from($table);
512 }
513
514 if ( ! is_null($where))
515 {
516 $this->where($where);
517 }
518
519 if ( ! is_null($limit))
520 {
521 $this->limit($limit, $offset);
522 }
523
524 $sql = $this->_compile_select();
525
adminc50747c2006-11-03 17:17:02 +0000526 $result = $this->query($sql);
adminac94f382006-09-24 20:28:12 +0000527 $this->_reset_select();
adminc50747c2006-11-03 17:17:02 +0000528 return $result;
adminac94f382006-09-24 20:28:12 +0000529 }
530
531 // --------------------------------------------------------------------
532
533 /**
534 * Insert
535 *
536 * Compiles an insert string and runs the query
537 *
538 * @access public
539 * @param string the table to retrieve the results from
540 * @param array an associative array of insert values
541 * @return object
542 */
543 function insert($table = '', $set = NULL)
544 {
545 if ( ! is_null($set))
546 {
547 $this->set($set);
548 }
549
550 if (count($this->ar_set) == 0)
551 {
admine334c472006-10-21 19:44:22 +0000552 if ($this->db_debug)
553 {
adminac94f382006-09-24 20:28:12 +0000554 return $this->display_error('db_must_use_set');
admine334c472006-10-21 19:44:22 +0000555 }
556 return FALSE;
adminac94f382006-09-24 20:28:12 +0000557 }
558
559 if ($table == '')
560 {
561 if ( ! isset($this->ar_from[0]))
562 {
563 if ($this->db_debug)
564 {
565 return $this->display_error('db_must_set_table');
566 }
567 return FALSE;
568 }
569
570 $table = $this->ar_from[0];
571 }
572
573 $sql = $this->_insert($this->dbprefix.$table, array_keys($this->ar_set), array_values($this->ar_set));
574
575 $this->_reset_write();
576 return $this->query($sql);
577 }
578
579 // --------------------------------------------------------------------
580
581 /**
582 * Update
583 *
584 * Compiles an update string and runs the query
585 *
586 * @access public
587 * @param string the table to retrieve the results from
588 * @param array an associative array of update values
589 * @param mixed the where clause
590 * @return object
591 */
592 function update($table = '', $set = NULL, $where = null)
593 {
594 if ( ! is_null($set))
595 {
596 $this->set($set);
597 }
598
599 if (count($this->ar_set) == 0)
600 {
admine334c472006-10-21 19:44:22 +0000601 if ($this->db_debug)
602 {
adminac94f382006-09-24 20:28:12 +0000603 return $this->display_error('db_must_use_set');
admine334c472006-10-21 19:44:22 +0000604 }
605 return FALSE;
adminac94f382006-09-24 20:28:12 +0000606 }
607
608 if ($table == '')
609 {
610 if ( ! isset($this->ar_from[0]))
611 {
612 if ($this->db_debug)
613 {
614 return $this->display_error('db_must_set_table');
615 }
616 return FALSE;
617 }
618
619 $table = $this->ar_from[0];
620 }
621
622 if ($where != null)
623 {
624 $this->where($where);
625 }
626
627 $sql = $this->_update($this->dbprefix.$table, $this->ar_set, $this->ar_where);
628
629 $this->_reset_write();
630 return $this->query($sql);
631 }
632
633 // --------------------------------------------------------------------
634
635 /**
636 * Delete
637 *
638 * Compiles a delete string and runs the query
639 *
640 * @access public
641 * @param string the table to retrieve the results from
642 * @param mixed the where clause
643 * @return object
644 */
645 function delete($table = '', $where = '')
646 {
647 if ($table == '')
648 {
649 if ( ! isset($this->ar_from[0]))
650 {
651 if ($this->db_debug)
652 {
653 return $this->display_error('db_must_set_table');
654 }
655 return FALSE;
656 }
657
658 $table = $this->ar_from[0];
659 }
660
661 if ($where != '')
662 {
663 $this->where($where);
664 }
665
666 if (count($this->ar_where) == 0)
667 {
admine334c472006-10-21 19:44:22 +0000668 if ($this->db_debug)
669 {
adminac94f382006-09-24 20:28:12 +0000670 return $this->display_error('db_del_must_use_where');
admine334c472006-10-21 19:44:22 +0000671 }
672 return FALSE;
adminac94f382006-09-24 20:28:12 +0000673 }
674
675 $sql = $this->_delete($this->dbprefix.$table, $this->ar_where);
676
677 $this->_reset_write();
678 return $this->query($sql);
679 }
680
681 // --------------------------------------------------------------------
682
683 /**
admine334c472006-10-21 19:44:22 +0000684 * Use Table - DEPRECATED
adminac94f382006-09-24 20:28:12 +0000685 *
686 * @deprecated use $this->db->from instead
687 */
688 function use_table($table)
689 {
690 return $this->from($table);
691 return $this;
692 }
693
694 // --------------------------------------------------------------------
695
696 /**
697 * ORDER BY - DEPRECATED
698 *
699 * @deprecated use $this->db->orderby() instead
700 */
701 function order_by($orderby, $direction = '')
702 {
703 return $this->orderby($orderby, $direction);
704 }
705
706 // --------------------------------------------------------------------
707
708 /**
709 * Tests whether the string has an SQL operator
710 *
711 * @access private
712 * @param string
713 * @return bool
714 */
715 function _has_operator($str)
716 {
717 $str = trim($str);
718 if ( ! preg_match("/(\s|<|>|!|=|is null|is not null)/i", $str))
719 {
720 return FALSE;
721 }
722
723 return TRUE;
724 }
725
726 // --------------------------------------------------------------------
727
728 /**
729 * Compile the SELECT statement
730 *
admine334c472006-10-21 19:44:22 +0000731 * Generates a query string based on which functions were used.
adminac94f382006-09-24 20:28:12 +0000732 * Should not be called directly. The get() function calls it.
733 *
734 * @access private
735 * @return string
736 */
737 function _compile_select()
738 {
739 $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
740
741 $sql .= (count($this->ar_select) == 0) ? '*' : implode(', ', $this->ar_select);
742
743 if (count($this->ar_from) > 0)
744 {
745 $sql .= "\nFROM ";
746 $sql .= implode(', ', $this->ar_from);
747 }
748
749 if (count($this->ar_join) > 0)
750 {
751 $sql .= "\n";
752 $sql .= implode("\n", $this->ar_join);
753 }
754
755 if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)
756 {
757 $sql .= "\nWHERE ";
758 }
759
760 $sql .= implode("\n", $this->ar_where);
761
762 if (count($this->ar_like) > 0)
763 {
764 if (count($this->ar_where) > 0)
765 {
766 $sql .= " AND ";
767 }
768
769 $sql .= implode("\n", $this->ar_like);
770 }
771
772 if (count($this->ar_groupby) > 0)
773 {
774 $sql .= "\nGROUP BY ";
775 $sql .= implode(', ', $this->ar_groupby);
776 }
777
778 if (count($this->ar_having) > 0)
779 {
780 $sql .= "\nHAVING ";
781 $sql .= implode("\n", $this->ar_having);
782 }
783
784 if (count($this->ar_orderby) > 0)
785 {
786 $sql .= "\nORDER BY ";
787 $sql .= implode(', ', $this->ar_orderby);
788
789 if ($this->ar_order !== FALSE)
790 {
791 $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';
792 }
793 }
794
795 if (is_numeric($this->ar_limit))
796 {
797 $sql .= "\n";
798 $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset);
799 }
800
801 return $sql;
802 }
803
804 // --------------------------------------------------------------------
805
806 /**
807 * Object to Array
808 *
adminfafe28b2006-10-21 19:08:17 +0000809 * Takes an object as input and converts the class variables to array key/vals
adminac94f382006-09-24 20:28:12 +0000810 *
811 * @access public
812 * @param object
813 * @return array
814 */
815 function _object_to_array($object)
816 {
817 if ( ! is_object($object))
818 {
819 return $object;
820 }
821
822 $array = array();
823 foreach (get_object_vars($object) as $key => $val)
824 {
825 if ( ! is_object($val) AND ! is_array($val))
826 {
827 $array[$key] = $val;
828 }
829 }
830
831 return $array;
832 }
833
834 // --------------------------------------------------------------------
835
836 /**
837 * Resets the active record values. Called by the get() function
838 *
839 * @access private
840 * @return void
841 */
842 function _reset_select()
843 {
844 $this->ar_select = array();
845 $this->ar_distinct = FALSE;
846 $this->ar_from = array();
847 $this->ar_join = array();
848 $this->ar_where = array();
849 $this->ar_like = array();
850 $this->ar_groupby = array();
851 $this->ar_having = array();
852 $this->ar_limit = FALSE;
853 $this->ar_offset = FALSE;
854 $this->ar_order = FALSE;
855 $this->ar_orderby = array();
856 }
857
858 // --------------------------------------------------------------------
859
860 /**
861 * Resets the active record "write" values.
862 *
863 * Called by the insert() or update() functions
864 *
865 * @access private
866 * @return void
867 */
868 function _reset_write()
869 {
870 $this->ar_set = array();
871 $this->ar_from = array();
872 $this->ar_where = array();
873 }
874
875}
876
877?>