00001 <?php 00022 class axMySQLObject extends axBaseModel { 00023 00028 protected $_table; 00029 00034 protected $_structure; 00035 00039 protected function _init ($statement) { 00040 if (isset($this->_statements[$statement])) 00041 return $this->_statements[$statement]; 00042 00043 $pieces = array(); 00044 $columns = array(); 00045 foreach ($this->_structure as $column => $infs) { 00046 $columns[] = "`$column`"; 00047 if ($column == $this->_idKey && strpos($infs['EXTRA'], 'auto_increment') !== false) 00048 continue; 00049 $pieces[] = "`{$column}`=:{$column}"; 00050 } 00051 00052 switch ($statement) { 00053 case 'create': 00054 $query = "INSERT INTO {$this->_table} SET " . implode(',', $pieces); 00055 break; 00056 00057 case 'retrieve': 00058 $query = "SELECT " . implode(',', $columns) . " " . 00059 "FROM {$this->_table} " . 00060 "WHERE `{$this->_idKey}`=:{$this->_idKey}"; 00061 break; 00062 00063 case 'update': 00064 $query = "UPDATE {$this->_table} SET " . implode(',', $pieces) . " " . 00065 "WHERE `{$this->_idKey}`=:{$this->_idKey}"; 00066 break; 00067 00068 case 'delete': 00069 $query = "DELETE FROM {$this->_table} WHERE `{$this->_idKey}`=:{$this->_idKey}"; 00070 break; 00071 00072 default: 00073 throw new InvalidArgumentException("Invalid statement $statement"); 00074 } 00075 00076 return $this->_statements[$statement] = $this->_pdo->prepare($query); 00077 } 00078 00088 public function __construct (PDO $pdo, $id = null) { 00089 $args = func_get_args(); 00090 if (empty($args)) 00091 throw new InvalidArgumentException('Missing parameters: `$pdo`, `$table`'); 00092 00093 if (count($args) === 1) 00094 throw new InvalidArgumentException('Missing parameter: `$table`'); 00095 00096 if (!$args[0] instanceof PDO) 00097 throw new InvalidArgumentException('`$pdo` parameter must be a valid PDO instance'); 00098 00099 if (!is_string($args[1])) 00100 throw new InvalidArgumentException('`$tablename` parameter must be string'); 00101 00102 if (empty($args[1])) 00103 throw new InvalidArgumentException('`$tablename` parameter cannot be empty'); 00104 00105 list($pdo,$tablename,$id) = $args + array(null,'',null); 00106 00107 if (!$this->_getTableStructure($tablename)) 00108 throw new RuntimeException("Cannot determine {$tablename} structure"); 00109 00110 $this->_table = self::_sanitizeTablename($tablename); 00111 parent::__construct($pdo, $id); 00112 } 00113 00187 public static function all (PDO $pdo, array $search_params = array(), array $options = array()) { 00188 if (func_num_args() < 4) 00189 throw new InvalidArgumentException('Missing fourth parameter'); 00190 00191 $arg = func_get_arg(3); 00192 00193 if ($arg instanceof axModel) { 00194 $mysql_obj = $arg; 00195 } 00196 elseif (is_string($arg)) { 00197 try { 00198 $mysql_obj = new self($pdo, $arg); 00199 } 00200 catch (Exception $e) { 00201 trigger_error("Unable to create `axMySQLObject` instance: " . $e->getMessage(), E_USER_WARNING); 00202 return false; 00203 } 00204 } 00205 else { 00206 throw new InvalidArgumentException("Fourth argument is expected to be a valid `axModel` instance or ". 00207 "string, " . gettype($arg) . " given"); 00208 } 00209 00210 if (!isset($mysql_obj)) 00211 $mysql_obj = new self($table); 00212 00213 $query = "SELECT `" . implode('`,`', $mysql_obj->getColumns()) . "` FROM " . $mysql_obj->getTable(); 00214 $query .= self::_generateWhereClause($search_params); 00215 $query .= self::_generateOptionClause($options); 00216 00217 $stmt = $pdo->prepare($query); 00218 if ($stmt->execute($search_params)) { 00219 $stmt->setFetchMode(PDO::FETCH_INTO, $mysql_obj); 00220 00221 if (PHP_VERSION_ID < 50200) { 00222 $cquery = preg_replace('~SELECT.*FROM~', 'SELECT COUNT(*) FROM', $query); 00223 $cstmt = $pdo->prepare($query); 00224 !empty($search_params) ? $cstmt->execute($search_params) : $cstmt->execute(); 00225 $count = (int)$cstmt->fetchColumn(); 00226 $it->setCount($count); 00227 } 00228 00229 return new axPDOStatementIterator($stmt); 00230 } 00231 return false; 00232 } 00233 00237 public function getTable () { 00238 return $this->_table; 00239 } 00240 00244 public function getColumns () { 00245 return array_keys($this->_structure); 00246 } 00247 00252 public function getStructure () { 00253 return $this->_structure; 00254 } 00255 00267 protected function _getTableStructure ($table) { 00268 if (!is_string($table) || empty($table)) 00269 throw new InvalidArgumentException("First parameter is expected to be valid string"); 00270 00271 $table = self::_sanitizeTablename($table); 00272 00273 if ($stmt = Axiom::database()->query("DESC $table")) { 00274 $this->_structure = array(); 00275 foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $column) { 00276 if (isset($column['Key']) && strpos($column['Key'], 'PRI') !== false) 00277 $this->_idKey = $column['Field']; 00278 00279 $this->_structure[$column['Field']] = array_change_key_case($column, CASE_UPPER); 00280 } 00281 return true; 00282 } 00283 return false; 00284 } 00285 00299 protected static function _sanitizeTablename ($table) { 00300 return '`' . implode('`.`', explode('.', str_replace(array('`', ' '), '', $table))) . '`'; 00301 } 00302 00315 protected static function _generateSelectQuery ($tablename, 00316 array $columns = array(), 00317 array $search_params = array(), 00318 array $options = array()) { 00319 if (!$tablename) 00320 throw new InvalidArgumentException('`$tablename` cannot be empty'); 00321 00322 if (empty($columns)) 00323 $columns = '*'; 00324 else 00325 $columns = '`' . implode('`,`', $columns) . '`'; 00326 00327 $query = "SELECT {$columns} FROM " . self::_sanitizeTablename($tablename); 00328 $query .= self::_generateWhereClause($search_params); 00329 $query .= self::_generateOptionClause($options); 00330 00331 return $query; 00332 } 00333 00341 protected static function _generateInsertQuery ($tablename, array $columns) { 00342 } 00343 00351 protected static function _generateUpdateQuery ($tablename, array $columns, array $search_params = array()) { 00352 } 00353 00361 protected static function _generateDeleteQuery ($tablename, array $search_params = array()) { 00362 } 00363 00373 protected static function _generateWhereClause (array $search_params) { 00374 if (!empty($search_params)) { 00375 $pieces = array(); 00376 00377 foreach ($search_params as $key => $value) { 00378 if (preg_match('~\s*(?<field>\w+)\s*(?<operator>.*)\s*~', $key, $matches)) { 00379 $field = $matches['field']; 00380 $operator = $matches['operator']; 00381 unset($search_params[$key]); 00382 $search_params['field'] = $value; 00383 $pieces[] = "`{$field}`{$operator}:{$field}"; 00384 } 00385 else { 00386 $pieces[] = "`{$key}`=:{$key}"; 00387 } 00388 } 00389 00390 return " WHERE " . implode(' AND ', $pieces); 00391 } 00392 return ""; 00393 } 00394 00404 protected static function _generateOptionClause (array $options) { 00405 $query = ""; 00406 00407 if (!empty($options['group by'])) { 00408 $pieces = array(); 00409 00410 foreach((array)$options['group_by'] as $field) 00411 $pieces[] = "`{$field}`"; 00412 00413 $query .= " GROUP BY ".implode(',' ,$pieces); 00414 } 00415 00416 if (!empty($options['order by'])) { 00417 $pieces = array(); 00418 00419 foreach($options['order by'] as $field) 00420 $pieces[] = "`{$field}`"; 00421 00422 $query .= " ORDER BY ".implode(',' ,$pieces); 00423 00424 if (isset($options['order by type']) 00425 && in_array(strtoupper($options['order by type']), array('ASC', 'DESC'))) 00426 $query .= " " . strtoupper($options['order by type']); 00427 } 00428 00429 if (!empty($options['limit'])) { 00430 if (count($options['limit']) == 1) { 00431 $options['limit'] = (array)$options['limit']; 00432 $query .= " LIMIT {$options['limit'][0]}"; 00433 } 00434 00435 if (count($options['limit']) == 2) { 00436 $query .= " LIMIT {$options['limit'][0]},{$options['limit'][1]}"; 00437 } 00438 } 00439 00440 return $query; 00441 } 00442 }