sql = $sql; } /** * Tabellen-Präfix ermitteln * * Wrapper um $REX, um zu vermeiden, dass die Methoden des AddOns immer * wieder "global REX" schreiben müssen. * * @return string das Tabellen-Präfix von Redaxo */ public static function getPrefix() { global $REX; return $REX['TABLE_PREFIX']; } /** * Datenbank auswählen * * Ändert die ab sofort zu verwendende Datenbank. * * @param int $databaseID die ID der Datenbank (1 oder 2) */ public function selectDB($databaseID) { $this->sql->selectDB($databaseID); } /** * Hilfsmethode für genau eine Zeile * * Diese Methode dient dazu, genau eine Zeile zu holen. Sie gibt im * Erfolgsfall kein true, sondern die geholte Zeile zurück, wodurch ein * Aufruf von row() entfällt. Sollte das Ergebnis nur eine Spalte haben, so * wird direkt dieser Wert zurückgeliefert (und kein Array mit einem * Element). * * @param string $what Spalten, die geholt werden sollen * @param string $from Tabelle, aus der gelesen werden soll * @param string $where WHERE-Kriterium * @param int $mode der Modus, in dem die Zeilen dann zurückgegeben werden sollen * @param bool $includeRexPrefix wenn true, wird $REX['TABLE_PREFIX'] vor den Tabellennamen gesetzt * @return mixed false im Falle eines Fehlers, sonst mixed oder ein Array (je nach Spaltenanzahl) */ public function fetch($what, $from, $where = '1', $mode = self::ASSOC, $includeRexPrefix = true) { $query = sprintf('SELECT %s FROM %s%s WHERE %s LIMIT 1', $what, $includeRexPrefix ? self::getPrefix() : '', $from, $where); if ( ($result = $this->query($query, '', $mode, true)) === false ) { return false; } $row = array(); switch ( $mode ) { case self::BOTH : $row = mysql_fetch_array($result); break; case self::NUM : $row = mysql_fetch_row($result); break; case self::ASSOC: default : $row = mysql_fetch_assoc($result); } mysql_free_result($result); if ( $row === false ) { return false; } if ( count($row) == 1 ) { $ret = array_values($row); return $ret[0]; } else { return $row; } } /** * Abfrage für den Iterator ausführen * * Diese Methode arbeitet exakt so wie auch query(), mit dem Unterschied, * dass sie im Erfolgsfall nicht true, sondern eine Referenz auf das Objekt * zurückgibt, über das direkt iteriert werden kann. So kann man bei kurzen * Abfragen nochmal eine Zeile Code einsparen. * * @param string $query die auszuführende Abfrage * @param string $replaceRexPrefix wenn nichtleer, wird in dem Query jedes Vorkommen durch TABLE_PREFIX ersetzt * @param int $mode der Modus, in dem die Zeilen dann zurückgegeben werden sollen * @return mixed ein leeres Array, wenn etwas schief lief, oder eine Referenz auf sich selbst im Erfolgsfall */ public function iquery($query, $replaceRexPrefix = '', $mode = self::ASSOC) { if ( !empty($replaceRexPrefix) ) { $query = str_replace($replaceRexPrefix, self::getPrefix(), $query); } $this->lastQuery = $query; if ( gettype($this->result[$this->depth]) == 'resource' ) { mysql_free_result($this->result[$this->depth]); } $this->result[$this->depth] = mysql_query($query, $this->sql->identifier); $this->currentRow[$this->depth] = null; $this->iteratorMode[$this->depth] = $mode; if ( $this->result[$this->depth] === false ) { $this->numRows[$this->depth] = 0; $this->numCols[$this->depth] = 0; return array(); } if ( is_resource($this->result[$this->depth]) ) { $this->numRows[$this->depth] = mysql_num_rows($this->result[$this->depth]); $this->numCols[$this->depth] = mysql_num_fields($this->result[$this->depth]); } else { $this->numRows[$this->depth] = 0; $this->numCols[$this->depth] = 0; } return $this; } /** * Abfrage ausführen * * Diese Methode führt genau eine Abfrage aus und liefert im Erfolgsfall * true, sonst false zurück. Wird der Parameter $temp auf true gesetzt, so * belegt die Abfrage nicht das aktuelle, interne Resultset, sondern legt * eine neue Variable an und gibt auch diese nach erfolgter Abfrage zurück. * fetch() nutzt diesen Mechanismus, um vom internen Resultset unabhängig zu * sein. * * @param string $query die auszuführende Abfrage * @param string $replaceRexPrefix wenn nichtleer, wird in dem Query jedes Vorkommen durch TABLE_PREFIX ersetzt * @param int $mode der Modus, in dem die Zeilen dann zurückgegeben werden sollen * @param bool $temp true, wenn die Abfrage nicht das interne Resultset belegen soll * @return mixed false bei einem Fehler, true wenn alles i.O. */ public function query($query, $replaceRexPrefix = '', $mode = self::ASSOC, $temp = false) { if ( !empty($replaceRexPrefix) ) { $query = str_replace($replaceRexPrefix, self::getPrefix(), $query); } $this->lastQuery = $query; if ( $temp ) { $result = mysql_query($query, $this->sql->identifier); return $result ? $result : false; } if ( gettype($this->result[$this->depth]) == 'resource' ) { mysql_free_result($this->result[$this->depth]); } $this->result[$this->depth] = mysql_query($query, $this->sql->identifier); $this->currentRow[$this->depth] = null; $this->iteratorMode[$this->depth] = $mode; if ( $this->result[$this->depth] === false ) { $this->numRows[$this->depth] = 0; $this->numCols[$this->depth] = 0; return false; } if ( is_resource($this->result[$this->depth]) ) { $this->numRows[$this->depth] = mysql_num_rows($this->result[$this->depth]); $this->numCols[$this->depth] = mysql_num_fields($this->result[$this->depth]); } else { $this->numRows[$this->depth] = 0; $this->numCols[$this->depth] = 0; } return true; } /** * Liefert ein Array zurück * * Diese Methode läuft über ein Resultset und gibt ein * normales Array mit dem Wert zurück. Es darf dazu nur * ein einzelnes Feld selektiert werden. Werden zwei * Felder selektiert, so ist das erste der Schlüssel und * der zweite der Wert des Ergebnisarrays. * * @param string $query die auszuführende Abfrage * @param string $replaceRexPrefix wenn nichtleer, wird in dem Query jedes Vorkommen durch TABLE_PREFIX ersetzt * @return array ein Array mit den Werten */ public function getArray($query, $replaceRexPrefix = '') { if ( !$this->query($query, $replaceRexPrefix, self::ASSOC) ) return array(); if ( $this->cols() == 0 ) return array(); $result = array(); foreach ( $this as $row ) { if ( $this->cols() == 1 ) $result[] = reset($row); elseif ( $this->cols() == 2 ) $result[reset($row)] = next($row); else { $columns = array_slice(array_keys($row),1); foreach ( $columns as $col ) { $result[reset($row)][$col] = $row[$col]; } } } return $result; } /** * Zeilen zählen * * Diese Methode liefert die Anzahl der Zeilen in einer Tabelle, die auf ein * bestimmtes Kriterium passen. * * Intern wird fetch("COUNT(*) AS count", $table, $where) aufgerufen. * * @param string $table die zu untersuchende Tabelle * @param string $where WHERE-Kriterium * @param bool $includeRexPrefix wenn true, wird $REX['TABLE_PREFIX'] vor den Tabellennamen gesetzt * @return mixed false im Falle eines Fehlers, sonst int */ public function count($table, $where = '1', $includeRexPrefix = true) { $ret = $this->fetch('COUNT(*) AS count', $table, $where, $includeRexPrefix); return $ret ? intval($ret['count']) : false; } /** * Liefert eine Zeile * * Diese Methode liefert genaue eine Zeile aus dem Resultset, wird aber * durch die Iterator-Fähigkeit eher selten benötigt. * * @param string $mode der Modus, in dem die Zeilen dann zurückgegeben werden sollen * @return mixed ein lerres Array im Falle eines Fehlers, sonst ein gefülltes Array */ public function row($mode = self::ASSOC) { if ( $this->result[$this->depth] === null ) { return array(); } switch ( $mode ) { case self::BOTH : $row = mysql_fetch_array($this->result[$this->depth]); break; case self::NUM : $row = mysql_fetch_row($this->result[$this->depth]); break; case self::ASSOC: default : $row = mysql_fetch_assoc($this->result[$this->depth]); } return $row; } /** * die letzte ID * * Gibt die zuletzt durch AUTO_INCREMENT eingefügte ID zurück. * * @return int die letzte ID */ public function lastID() { return mysql_insert_id($this->sql->identifier); } /** * die betroffenen Zeilen * * Gibt die Anzahl der von der letzten Abfrage betroffenen Zeilen zurück. * * @return int die betroffenen Zeilen */ public function affectedRows() { return mysql_affected_rows($this->sql->identifier); } /** * Neues Resultset anlegen * * Um verschachtelte Abfragen zu ermöglichen, kann mit dieser Methode ein * neues, leeres Resultset auf den Stack gelegt werden, das danach für alle * weiteren Abfragen herhalten wird. */ public function in() { ++$this->depth; $this->result[$this->depth] = null; $this->currentRow[$this->depth] = null; $this->iteratorMode[$this->depth] = self::ASSOC; $this->numRows[$this->depth] = 0; $this->numCols[$this->depth] = 0; } /** * Vorheriges Resultset nutzen * * Entfernt das oberste Resultset und setzt den Zeiger auf das vorherige. * Entspricht einer POP-Operation bei Stacks. Jeder in()-Aufruf sollte * irgendwann von einem out()-Aufruf gefolgt werden. */ public function out() { if ( is_resource($this->result[$this->depth]) ) { mysql_free_result($this->result[$this->depth]); } --$this->depth; if ( $this->depth < 0 ) { $this->depth = 0; } } /** * die letzte Abfrage * * Gibt die zuletzt ausgeführte Afrage zurück * * @return string die letzte Abfrage */ public function getLastQuery() { return $this->lastQuery; } /** * Anzahl der Zeilen * * Diese Methode gibt die Anzahl der mit der letzten Abfrage geholten Zeilen * zurück. Dieser Wert ist nicht immer definiert (z.B. nicht für * UPDATE-Queries). * * @return int die Anzahl der Zeilen */ public function rows() { return $this->numRows[$this->depth]; } /** * Anzahl der Spalten * * Diese Methode gibt die Anzahl der mit der letzten Abfrage geholten * Spalten zurück. Dieser Wert ist nicht immer definiert (z.B. nicht für * UPDATE-Queries). * * @return int die Anzahl der Spalten */ public function cols() { return $this->numCols[$this->depth]; } /** * Gibt den letzten Fehlercode zurück. * * @return int den letzten Fehlercode */ public function getErrno() { return mysql_errno($this->sql->identifier); } /** * Gibt die letzte Fehlermeldung zurück. * * @return string die letzte Fehlermeldung */ public function getError() { return mysql_error($this->sql->identifier); } // ========================================================================= // ITERATOR-METHODEN // ========================================================================= ///@cond INCLUDE_ITERATOR_METHODS public function current() { return $this->currentRow[$this->depth]; } public function next() { $this->currentRow[$this->depth] = $this->row($this->iteratorMode[$this->depth]); } public function key() { return null; } public function valid() { if ( $this->result[$this->depth] === false ) { return false; } // Wurde noch gar keine Zeile geholt? Dann holen wir das hier nach. if ( $this->currentRow[$this->depth] === null ) { $this->currentRow[$this->depth] = $this->row($this->iteratorMode[$this->depth]); } return is_array($this->currentRow[$this->depth]); } public function rewind() { if ( mysql_num_rows($this->result[$this->depth]) > 0 ) { mysql_data_seek($this->result[$this->depth], 0); $this->currentRow[$this->depth] = null; } } ///@endcond } ?>