Rev 52 | Rev 58 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 27 | PointedEar | 1 | <?php | 
        
| 2 | |||
| 51 | PointedEar | 3 | namespace PointedEars\PHPX\Db;  | 
        
| 4 | |||
| 5 | use \PointedEars\PHPX\Application;  | 
        ||
| 6 | |||
| 27 | PointedEar | 7 | /** | 
        
| 8 |  * Generic database table model class | 
        ||
| 9 |  * | 
        ||
| 10 |  * @author Thomas Lahn | 
        ||
| 50 | PointedEar | 11 |  * @property Database $database | 
        
| 27 | PointedEar | 12 |  * @property-read int $lastInsertId | 
        
| 13 |  *   ID of the last inserted row, or the last value from | 
        ||
| 14 |      a sequence object, depending on the underlying driver. | 
        ||
| 15 |  */ | 
        ||
| 51 | PointedEar | 16 | class Table extends \PointedEars\PHPX\AbstractModel  | 
        
| 27 | PointedEar | 17 | { | 
        
| 18 |   /** | 
        ||
| 19 |    * Name of the table | 
        ||
| 56 | PointedEar | 20 |    * @var string | 
        
| 27 | PointedEar | 21 |    */ | 
        
| 56 | PointedEar | 22 | protected static $_name = '';  | 
        
| 50 | PointedEar | 23 | |
| 27 | PointedEar | 24 |   /** | 
        
| 25 |    * Database of the table | 
        ||
| 50 | PointedEar | 26 |    * @var Database|string | 
        
| 27 | PointedEar | 27 |    */ | 
        
| 56 | PointedEar | 28 | protected static $_database;  | 
        
| 50 | PointedEar | 29 | |
| 56 | PointedEar | 30 |   /** | 
        
| 31 |    * Name of the primary key column of the table | 
        ||
| 32 |    * @var string | 
        ||
| 33 |    */ | 
        ||
| 34 | protected static $_id = 'id';  | 
        ||
| 50 | PointedEar | 35 | |
| 34 | PointedEar | 36 |   /** | 
        
| 37 |    * Creates a new <code>Table</code> instance. | 
        ||
| 38 |    * | 
        ||
| 39 |    * Each of the parameters is optional and can also be given | 
        ||
| 40 |    * by a protected property where the parameter name is preceded | 
        ||
| 41 |    * by <code>_</code>.  Parameter values overwrite the default | 
        ||
| 42 |    * property values.  It is recommended to use default property | 
        ||
| 43 |    * values of inheriting classes except for small applications | 
        ||
| 44 |    * and testing purposes. | 
        ||
| 45 |    * | 
        ||
| 46 |    * @param Database $database | 
        ||
| 47 |    *   Database of the table (required in order to use a fitting | 
        ||
| 48 |    *   query language) | 
        ||
| 49 |    * @param string $name | 
        ||
| 50 |    *   Table name | 
        ||
| 51 |    * @param string $id | 
        ||
| 52 |    *   Name of the primary key column | 
        ||
| 53 |    * @throws InvalidArgumentException | 
        ||
| 54 |    */ | 
        ||
| 56 | PointedEar | 55 | public function __construct ($database = null, $name = '', $id = '')  | 
        
| 27 | PointedEar | 56 |   { | 
        
| 34 | PointedEar | 57 | if ($database === null)  | 
        
| 58 |     { | 
        ||
| 50 | PointedEar | 59 |                 /* Call getter to convert to Database if possible */ | 
        
| 60 | if ($this->database === null)  | 
        ||
| 61 |         { | 
        ||
| 56 | PointedEar | 62 | $this->database = Application::getInstance()->getDefaultDatabase();  | 
        
| 50 | PointedEar | 63 |         } | 
        
| 34 | PointedEar | 64 |     } | 
        
| 65 |     else | 
        ||
| 66 |     { | 
        ||
| 56 | PointedEar | 67 | $this->database = $database;  | 
        
| 34 | PointedEar | 68 |     } | 
        
| 50 | PointedEar | 69 | |
| 34 | PointedEar | 70 | if ($name !== '')  | 
        
| 71 |     { | 
        ||
| 56 | PointedEar | 72 | $this->name = $name;  | 
        
| 34 | PointedEar | 73 |     } | 
        
| 50 | PointedEar | 74 | |
| 56 | PointedEar | 75 | $name = $this->name;  | 
        
| 76 | if (!\is_string($name))  | 
        ||
| 34 | PointedEar | 77 |     { | 
        
| 50 | PointedEar | 78 | throw new \InvalidArgumentException(  | 
        
| 79 |         'Expected string for table name, saw ' | 
        ||
| 56 | PointedEar | 80 | . (\is_object($name) ? \get_class($name) : \gettype($name)));  | 
        
| 34 | PointedEar | 81 |     } | 
        
| 82 | |||
| 83 | if ($id !== '')  | 
        ||
| 84 |     { | 
        ||
| 56 | PointedEar | 85 | $this->id = $id;  | 
        
| 34 | PointedEar | 86 |     } | 
        
| 27 | PointedEar | 87 |   } | 
        
| 50 | PointedEar | 88 | |
| 27 | PointedEar | 89 |   /** | 
        
| 56 | PointedEar | 90 |    * @param string $value | 
        
| 91 |    */ | 
        ||
| 92 | public function setName ($value)  | 
        ||
| 93 |   { | 
        ||
| 94 | $class = \get_class($this);  | 
        ||
| 95 | $class::$_name = (string) $value;  | 
        ||
| 96 |   } | 
        ||
| 97 | |||
| 98 |   /** | 
        ||
| 99 |    * @return string | 
        ||
| 100 |    */ | 
        ||
| 101 | public function getName ()  | 
        ||
| 102 |   { | 
        ||
| 103 | $class = \get_class($this);  | 
        ||
| 104 | return $class::$_name;  | 
        ||
| 105 |   } | 
        ||
| 106 | |||
| 107 |   /** | 
        ||
| 27 | PointedEar | 108 |    * Returns the database for the table | 
        
| 109 |    * @return Database | 
        ||
| 110 |    */ | 
        ||
| 111 | public function getDatabase()  | 
        ||
| 112 |   { | 
        ||
| 56 | PointedEar | 113 | $class = \get_class($this);  | 
        
| 114 | if (\is_string($class::$_database))  | 
        ||
| 50 | PointedEar | 115 |     { | 
        
| 116 |       /* Call setter to convert to Database */ | 
        ||
| 56 | PointedEar | 117 | $this->setDatabase($class::$_database);  | 
        
| 50 | PointedEar | 118 |     } | 
        
| 119 | |||
| 56 | PointedEar | 120 | return $class::$_database;  | 
        
| 27 | PointedEar | 121 |   } | 
        
| 50 | PointedEar | 122 | |
| 27 | PointedEar | 123 |   /** | 
        
| 50 | PointedEar | 124 |    * @param Database|string $value | 
        
| 125 |    * @throws InvalidArgumentException | 
        ||
| 126 |    */ | 
        ||
| 127 | public function setDatabase ($value)  | 
        ||
| 128 |   { | 
        ||
| 56 | PointedEar | 129 | $class = \get_class($this);  | 
        
| 50 | PointedEar | 130 | if ($value instanceof Database)  | 
        
| 131 |         { | 
        ||
| 56 | PointedEar | 132 | $class::$_database = $value;  | 
        
| 50 | PointedEar | 133 |         } | 
        
| 134 | else if ($value !== null)  | 
        ||
| 135 |         { | 
        ||
| 136 | $database = new $value();  | 
        ||
| 137 | if (!($database instanceof Database))  | 
        ||
| 138 |                 { | 
        ||
| 139 | throw new \InvalidArgumentException(  | 
        ||
| 140 |                                 'Expected Database instance or string for class name, saw ' | 
        ||
| 56 | PointedEar | 141 | . (\is_object($value) ? \get_class($value) : \gettype($value))  | 
        
| 50 | PointedEar | 142 | );  | 
        
| 143 |                 } | 
        ||
| 144 | |||
| 56 | PointedEar | 145 | $class::$_database = $database;  | 
        
| 50 | PointedEar | 146 |         } | 
        
| 147 |   } | 
        ||
| 148 | |||
| 149 |   /** | 
        ||
| 56 | PointedEar | 150 |    * @param string $value | 
        
| 151 |    */ | 
        ||
| 152 | public function setId ($value)  | 
        ||
| 153 |   { | 
        ||
| 154 | $class = \get_class($this);  | 
        ||
| 155 | $class::$_id = (string) $value;  | 
        ||
| 156 |   } | 
        ||
| 157 | |||
| 158 |   /** | 
        ||
| 159 |    * @return string | 
        ||
| 160 |    */ | 
        ||
| 161 | public function getId ()  | 
        ||
| 162 |   { | 
        ||
| 163 | $class = \get_class($this);  | 
        ||
| 164 | return $class::$_id;  | 
        ||
| 165 |   } | 
        ||
| 166 | |||
| 167 |   /** | 
        ||
| 27 | PointedEar | 168 |    * Initiates a transaction | 
        
| 169 |    * | 
        ||
| 170 |    * @return bool | 
        ||
| 171 |    * @see Database::beginTransaction() | 
        ||
| 172 |    */ | 
        ||
| 173 | public function beginTransaction()  | 
        ||
| 174 |   { | 
        ||
| 56 | PointedEar | 175 | return $this->database->beginTransaction();  | 
        
| 27 | PointedEar | 176 |   } | 
        
| 50 | PointedEar | 177 | |
| 27 | PointedEar | 178 |   /** | 
        
| 179 |    * Rolls back a transaction | 
        ||
| 180 |    * | 
        ||
| 181 |    * @return bool | 
        ||
| 182 |    * @see Database::rollBack() | 
        ||
| 183 |    */ | 
        ||
| 184 | public function rollBack()  | 
        ||
| 185 |   { | 
        ||
| 56 | PointedEar | 186 | return $this->database->rollBack();  | 
        
| 27 | PointedEar | 187 |   } | 
        
| 50 | PointedEar | 188 | |
| 27 | PointedEar | 189 |   /** | 
        
| 190 |    * Commits a transaction | 
        ||
| 191 |    * | 
        ||
| 192 |    * @return bool | 
        ||
| 193 |    * @see Database::commit() | 
        ||
| 194 |    */ | 
        ||
| 195 | public function commit()  | 
        ||
| 196 |   { | 
        ||
| 56 | PointedEar | 197 | return $this->database->commit();  | 
        
| 27 | PointedEar | 198 |   } | 
        
| 50 | PointedEar | 199 | |
| 27 | PointedEar | 200 |   /** | 
        
| 201 |    * Retrieves all rows from the table | 
        ||
| 202 |    * | 
        ||
| 203 |    * @return array | 
        ||
| 204 |    * @see Database::fetchAll() | 
        ||
| 205 |    */ | 
        ||
| 206 | public function fetchAll($fetch_style = null, $column_index = null, array $ctor_args = null)  | 
        ||
| 207 |   { | 
        ||
| 56 | PointedEar | 208 | return $this->database->fetchAll($this->name, $fetch_style, $column_index, $ctor_args);  | 
        
| 27 | PointedEar | 209 |   } | 
        
| 50 | PointedEar | 210 | |
| 27 | PointedEar | 211 |   /** | 
        
| 212 |    * Selects data from one or more tables | 
        ||
| 213 |    * | 
        ||
| 214 |    * @return array | 
        ||
| 215 |    * @see Database::select() | 
        ||
| 216 |    */ | 
        ||
| 217 | public function select($columns = null, $where = null, $order = null, $limit = null)  | 
        ||
| 218 |   { | 
        ||
| 56 | PointedEar | 219 | return $this->database->select($this->name, $columns, $where, $order, $limit);  | 
        
| 27 | PointedEar | 220 |   } | 
        
| 50 | PointedEar | 221 | |
| 27 | PointedEar | 222 |   /** | 
        
| 223 |    * Updates records in one or more tables | 
        ||
| 224 |    * | 
        ||
| 225 |    * @return bool | 
        ||
| 226 |    * @see Database::update() | 
        ||
| 227 |    */ | 
        ||
| 228 | public function update($data, $condition)  | 
        ||
| 229 |   { | 
        ||
| 56 | PointedEar | 230 | return $this->database->update($this->name, $data, $condition);  | 
        
| 27 | PointedEar | 231 |   } | 
        
| 50 | PointedEar | 232 | |
| 27 | PointedEar | 233 |   /** | 
        
| 234 |    * Inserts a record into the table | 
        ||
| 235 |    * | 
        ||
| 236 |    * @return bool | 
        ||
| 237 |    * @see Database::insert() | 
        ||
| 238 |    */ | 
        ||
| 239 | public function insert($data, $cols = null)  | 
        ||
| 240 |   { | 
        ||
| 56 | PointedEar | 241 | return $this->database->insert($this->name, $data, $cols);  | 
        
| 27 | PointedEar | 242 |   } | 
        
| 50 | PointedEar | 243 | |
| 27 | PointedEar | 244 |   /** | 
        
| 245 |    * Returns the ID of the last inserted row, or the last value from | 
        ||
| 246 |    * a sequence object, depending on the underlying driver. | 
        ||
| 247 |    * | 
        ||
| 248 |    * @return int | 
        ||
| 249 |    * @see Database::getLastInsertId() | 
        ||
| 250 |    */ | 
        ||
| 251 | public function getLastInsertId()  | 
        ||
| 252 |   { | 
        ||
| 56 | PointedEar | 253 | return $this->database->lastInsertId;  | 
        
| 27 | PointedEar | 254 |   } | 
        
| 50 | PointedEar | 255 | |
| 27 | PointedEar | 256 |   /** | 
        
| 257 |    * Delete a record from the table | 
        ||
| 258 |    * | 
        ||
| 259 |    * @param int $id | 
        ||
| 260 |    *   ID of the record to delete.  May be <code>null</code>, | 
        ||
| 261 |    *   in which case <var>$condition</var> must specify | 
        ||
| 262 |    *   the records to be deleted. | 
        ||
| 263 |    * @param array[optional] $condition | 
        ||
| 264 |    *   Conditions that must be met for a record to be deleted. | 
        ||
| 265 |    *   Ignored if <var>$id</var> is not <code>null</code>. | 
        ||
| 266 |    * @return bool | 
        ||
| 267 |    * @throws InvalidArgumentException if both <var>$id</var> and | 
        ||
| 268 |    *     <var>$condition</var> are <code>null</code>. | 
        ||
| 269 |    * @see Database::delete() | 
        ||
| 270 |    */ | 
        ||
| 50 | PointedEar | 271 | public function delete ($id, array $condition = null)  | 
        
| 27 | PointedEar | 272 |   { | 
        
| 50 | PointedEar | 273 | if ($id !== null)  | 
        
| 27 | PointedEar | 274 |     { | 
        
| 56 | PointedEar | 275 | $condition = array($this->id => $id);  | 
        
| 27 | PointedEar | 276 |     } | 
        
| 50 | PointedEar | 277 | else if ($condition === null)  | 
        
| 27 | PointedEar | 278 |     { | 
        
| 279 | throw new InvalidArgumentException(  | 
        ||
| 280 | '$id and $condition cannot both be null');  | 
        ||
| 281 |     } | 
        ||
| 50 | PointedEar | 282 | |
| 56 | PointedEar | 283 | return $this->database->delete($this->name, $condition);  | 
        
| 27 | PointedEar | 284 |   } | 
        
| 50 | PointedEar | 285 | |
| 27 | PointedEar | 286 |  /** | 
        
| 287 |   * Inserts a row into the table or updates an existing one | 
        ||
| 288 |   * | 
        ||
| 289 |   * @param array $data | 
        ||
| 290 |   *   Associative array of column-value pairs to be updated/inserted | 
        ||
| 291 |   * @param string|array $condition | 
        ||
| 292 |   *   If there are no records matching this condition, a row will be inserted; | 
        ||
| 293 |   *   otherwise matching records are updated | 
        ||
| 294 |   * @return bool | 
        ||
| 295 |   * @see Table::update() | 
        ||
| 296 |   * @see Table::insert() | 
        ||
| 297 |   */ | 
        ||
| 298 | public function updateOrInsert($data, array $condition = null)  | 
        ||
| 299 |   { | 
        ||
| 56 | PointedEar | 300 | if ($this->select($this->id, $condition))  | 
        
| 27 | PointedEar | 301 |     { | 
        
| 302 | return $this->update($data, $condition);  | 
        ||
| 303 |     } | 
        ||
| 304 | |||
| 50 | PointedEar | 305 | return $this->insert($data);  | 
        
| 27 | PointedEar | 306 |   } | 
        
| 307 | |||
| 308 |   /** | 
        ||
| 309 |    * Finds a record by ID | 
        ||
| 310 |    * | 
        ||
| 311 |    * @param mixed $id | 
        ||
| 35 | PointedEar | 312 |    * @return array | 
        
| 27 | PointedEar | 313 |    */ | 
        
| 50 | PointedEar | 314 | public function find ($id)  | 
        
| 27 | PointedEar | 315 |   { | 
        
| 316 |     /* DEBUG */ | 
        ||
| 317 | if (defined('DEBUG') && DEBUG > 0)  | 
        ||
| 318 |     { | 
        ||
| 319 | debug($id);  | 
        ||
| 320 |     } | 
        ||
| 50 | PointedEar | 321 | |
| 56 | PointedEar | 322 | $result = $this->select(null, array($this->id => $id));  | 
        
| 50 | PointedEar | 323 | |
| 35 | PointedEar | 324 | if ($result)  | 
        
| 325 |     { | 
        ||
| 326 | $result = $result[0];  | 
        ||
| 327 |     } | 
        ||
| 50 | PointedEar | 328 | |
| 35 | PointedEar | 329 | return $result;  | 
        
| 27 | PointedEar | 330 |   } | 
        
| 331 | } |