1<?php defined('SYSPATH') OR die('No direct script access.'); 2/** 3 * Database query builder for JOIN statements. See [Query Builder](/database/query/builder) for usage and examples. 4 * 5 * @package Kohana/Database 6 * @category Query 7 * @author Kohana Team 8 * @copyright (c) 2008-2009 Kohana Team 9 * @license http://kohanaphp.com/license 10 */ 11class Kohana_Database_Query_Builder_Join extends Database_Query_Builder { 12 13 // Type of JOIN 14 protected $_type; 15 16 // JOIN ... 17 protected $_table; 18 19 // ON ... 20 protected $_on = array(); 21 22 // USING ... 23 protected $_using = array(); 24 25 /** 26 * Creates a new JOIN statement for a table. Optionally, the type of JOIN 27 * can be specified as the second parameter. 28 * 29 * @param mixed $table column name or array($column, $alias) or object 30 * @param string $type type of JOIN: INNER, RIGHT, LEFT, etc 31 * @return void 32 */ 33 public function __construct($table, $type = NULL) 34 { 35 // Set the table to JOIN on 36 $this->_table = $table; 37 38 if ($type !== NULL) 39 { 40 // Set the JOIN type 41 $this->_type = (string) $type; 42 } 43 } 44 45 /** 46 * Adds a new condition for joining. 47 * 48 * @param mixed $c1 column name or array($column, $alias) or object 49 * @param string $op logic operator 50 * @param mixed $c2 column name or array($column, $alias) or object 51 * @return $this 52 */ 53 public function on($c1, $op, $c2) 54 { 55 if ( ! empty($this->_using)) 56 { 57 throw new Kohana_Exception('JOIN ... ON ... cannot be combined with JOIN ... USING ...'); 58 } 59 60 $this->_on[] = array($c1, $op, $c2); 61 62 return $this; 63 } 64 65 /** 66 * Adds a new condition for joining. 67 * 68 * @param string $columns column name 69 * @return $this 70 */ 71 public function using($columns) 72 { 73 if ( ! empty($this->_on)) 74 { 75 throw new Kohana_Exception('JOIN ... ON ... cannot be combined with JOIN ... USING ...'); 76 } 77 78 $columns = func_get_args(); 79 80 $this->_using = array_merge($this->_using, $columns); 81 82 return $this; 83 } 84 85 /** 86 * Compile the SQL partial for a JOIN statement and return it. 87 * 88 * @param mixed $db Database instance or name of instance 89 * @return string 90 */ 91 public function compile($db = NULL) 92 { 93 if ( ! is_object($db)) 94 { 95 // Get the database instance 96 $db = Database::instance($db); 97 } 98 99 if ($this->_type) 100 { 101 $sql = strtoupper($this->_type).' JOIN'; 102 } 103 else 104 { 105 $sql = 'JOIN'; 106 } 107 108 // Quote the table name that is being joined 109 $sql .= ' '.$db->quote_table($this->_table); 110 111 if ( ! empty($this->_using)) 112 { 113 // Quote and concat the columns 114 $sql .= ' USING ('.implode(', ', array_map(array($db, 'quote_column'), $this->_using)).')'; 115 } 116 else 117 { 118 $conditions = array(); 119 foreach ($this->_on as $condition) 120 { 121 // Split the condition 122 list($c1, $op, $c2) = $condition; 123 124 if ($op) 125 { 126 // Make the operator uppercase and spaced 127 $op = ' '.strtoupper($op); 128 } 129 130 // Quote each of the columns used for the condition 131 $conditions[] = $db->quote_column($c1).$op.' '.$db->quote_column($c2); 132 } 133 134 // Concat the conditions "... AND ..." 135 $sql .= ' ON ('.implode(' AND ', $conditions).')'; 136 } 137 138 return $sql; 139 } 140 141 public function reset() 142 { 143 $this->_type = 144 $this->_table = NULL; 145 146 $this->_on = array(); 147 } 148 149} // End Database_Query_Builder_Join 150