Subversion Repositories PHPX

Rev

Rev 56 | 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
  /**
58 PointedEar 25
   * Columns definition
26
   * @var array
27
         * @see Table::create()
28
   */
29
  protected static $_columns;
30
 
31
  /**
32
   * Indexes definition
33
   * @var array
34
         * @see Table::create()
35
   */
36
  protected static $_indexes;
37
 
38
  /**
39
   * Constraints definition
40
   * @var array
41
         * @see Table::create()
42
   */
43
  protected static $_constraints;
44
 
45
  /**
27 PointedEar 46
   * Database of the table
50 PointedEar 47
   * @var Database|string
58 PointedEar 48
         * @see Table::create()
27 PointedEar 49
   */
56 PointedEar 50
  protected static $_database;
50 PointedEar 51
 
56 PointedEar 52
  /**
53
   * Name of the primary key column of the table
54
   * @var string
55
   */
56
  protected static $_id = 'id';
50 PointedEar 57
 
34 PointedEar 58
  /**
59
   * Creates a new <code>Table</code> instance.
60
   *
61
   * Each of the parameters is optional and can also be given
62
   * by a protected property where the parameter name is preceded
63
   * by <code>_</code>.  Parameter values overwrite the default
64
   * property values.  It is recommended to use default property
65
   * values of inheriting classes except for small applications
66
   * and testing purposes.
67
   *
68
   * @param Database $database
69
   *   Database of the table (required in order to use a fitting
70
   *   query language)
71
   * @param string $name
72
   *   Table name
73
   * @param string $id
74
   *   Name of the primary key column
75
   * @throws InvalidArgumentException
76
   */
56 PointedEar 77
  public function __construct ($database = null, $name = '', $id = '')
27 PointedEar 78
  {
34 PointedEar 79
    if ($database === null)
80
    {
50 PointedEar 81
                /* Call getter to convert to Database if possible */
82
        if ($this->database === null)
83
        {
56 PointedEar 84
                $this->database = Application::getInstance()->getDefaultDatabase();
50 PointedEar 85
        }
34 PointedEar 86
    }
87
    else
88
    {
56 PointedEar 89
      $this->database = $database;
34 PointedEar 90
    }
50 PointedEar 91
 
34 PointedEar 92
    if ($name !== '')
93
    {
56 PointedEar 94
      $this->name = $name;
34 PointedEar 95
    }
50 PointedEar 96
 
56 PointedEar 97
    $name = $this->name;
98
    if (!\is_string($name))
34 PointedEar 99
    {
50 PointedEar 100
      throw new \InvalidArgumentException(
101
        'Expected string for table name, saw '
56 PointedEar 102
                                . (\is_object($name) ? \get_class($name) : \gettype($name)));
34 PointedEar 103
    }
104
 
105
    if ($id !== '')
106
    {
56 PointedEar 107
      $this->id = $id;
34 PointedEar 108
    }
27 PointedEar 109
  }
50 PointedEar 110
 
27 PointedEar 111
  /**
56 PointedEar 112
   * @param string $value
113
   */
114
  public function setName ($value)
115
  {
116
        $class = \get_class($this);
117
        $class::$_name = (string) $value;
118
  }
119
 
120
  /**
121
   * @return string
122
   */
123
  public function getName ()
124
  {
125
        $class = \get_class($this);
126
        return $class::$_name;
127
  }
128
 
129
  /**
27 PointedEar 130
   * Returns the database for the table
131
   * @return Database
132
   */
133
  public function getDatabase()
134
  {
56 PointedEar 135
        $class = \get_class($this);
136
    if (\is_string($class::$_database))
50 PointedEar 137
    {
138
      /* Call setter to convert to Database */
56 PointedEar 139
      $this->setDatabase($class::$_database);
50 PointedEar 140
    }
141
 
56 PointedEar 142
    return $class::$_database;
27 PointedEar 143
  }
50 PointedEar 144
 
27 PointedEar 145
  /**
50 PointedEar 146
   * @param Database|string $value
147
   * @throws InvalidArgumentException
148
   */
149
  public function setDatabase ($value)
150
  {
56 PointedEar 151
        $class = \get_class($this);
50 PointedEar 152
        if ($value instanceof Database)
153
        {
56 PointedEar 154
                $class::$_database = $value;
50 PointedEar 155
        }
156
        else if ($value !== null)
157
        {
158
                $database = new $value();
159
                if (!($database instanceof Database))
160
                {
161
                        throw new \InvalidArgumentException(
162
                                'Expected Database instance or string for class name, saw '
56 PointedEar 163
                                        . (\is_object($value) ? \get_class($value) : \gettype($value))
50 PointedEar 164
                        );
165
                }
166
 
56 PointedEar 167
                $class::$_database = $database;
50 PointedEar 168
        }
169
  }
170
 
171
  /**
56 PointedEar 172
   * @param string $value
173
   */
174
  public function setId ($value)
175
  {
176
        $class = \get_class($this);
177
        $class::$_id = (string) $value;
178
  }
179
 
180
  /**
181
   * @return string
182
   */
183
  public function getId ()
184
  {
185
        $class = \get_class($this);
186
        return $class::$_id;
187
  }
188
 
189
  /**
58 PointedEar 190
   * Returns the <var>options</var> array for {@link Database::createTable}
191
   *
192
   * Should be called and overridden by inheriting classes.
193
   *
194
   * @return array
195
   */
196
  protected function _createOptions ()
197
  {
198
        $options = array();
199
 
200
        foreach (array('indexes', 'constraints') as $option)
201
        {
202
                if ($class::${"_$option"})
203
                {
204
                        $options[$option] = $class::${"_$option"};
205
                }
206
        }
207
 
208
        return $options;
209
  }
210
 
211
  /**
212
   * Creates the table for this model
213
   *
214
   * @return bool
215
   */
216
  public function create ()
217
  {
218
        $class = \get_class($this);
219
                return $this->database->createTable(
220
                        $class::$_name, $class::$_columns, $this->_createOptions());
221
  }
222
 
223
  /**
27 PointedEar 224
   * Initiates a transaction
225
   *
226
   * @return bool
227
   * @see Database::beginTransaction()
228
   */
229
  public function beginTransaction()
230
  {
56 PointedEar 231
    return $this->database->beginTransaction();
27 PointedEar 232
  }
50 PointedEar 233
 
27 PointedEar 234
  /**
235
   * Rolls back a transaction
236
   *
237
   * @return bool
238
   * @see Database::rollBack()
239
   */
240
  public function rollBack()
241
  {
56 PointedEar 242
    return $this->database->rollBack();
27 PointedEar 243
  }
50 PointedEar 244
 
27 PointedEar 245
  /**
246
   * Commits a transaction
247
   *
248
   * @return bool
249
   * @see Database::commit()
250
   */
251
  public function commit()
252
  {
56 PointedEar 253
    return $this->database->commit();
27 PointedEar 254
  }
50 PointedEar 255
 
27 PointedEar 256
  /**
257
   * Retrieves all rows from the table
258
   *
259
   * @return array
260
   * @see Database::fetchAll()
261
   */
262
  public function fetchAll($fetch_style = null, $column_index = null, array $ctor_args = null)
263
  {
56 PointedEar 264
    return $this->database->fetchAll($this->name, $fetch_style, $column_index, $ctor_args);
27 PointedEar 265
  }
50 PointedEar 266
 
27 PointedEar 267
  /**
268
   * Selects data from one or more tables
269
   *
270
   * @return array
271
   * @see Database::select()
272
   */
273
  public function select($columns = null, $where = null, $order = null, $limit = null)
274
  {
56 PointedEar 275
    return $this->database->select($this->name, $columns, $where, $order, $limit);
27 PointedEar 276
  }
50 PointedEar 277
 
27 PointedEar 278
  /**
279
   * Updates records in one or more tables
280
   *
281
   * @return bool
282
   * @see Database::update()
283
   */
284
  public function update($data, $condition)
285
  {
56 PointedEar 286
    return $this->database->update($this->name, $data, $condition);
27 PointedEar 287
  }
50 PointedEar 288
 
27 PointedEar 289
  /**
290
   * Inserts a record into the table
291
   *
292
   * @return bool
293
   * @see Database::insert()
294
   */
295
  public function insert($data, $cols = null)
296
  {
56 PointedEar 297
    return $this->database->insert($this->name, $data, $cols);
27 PointedEar 298
  }
50 PointedEar 299
 
27 PointedEar 300
  /**
301
   * Returns the ID of the last inserted row, or the last value from
302
   * a sequence object, depending on the underlying driver.
303
   *
304
   * @return int
305
   * @see Database::getLastInsertId()
306
   */
307
  public function getLastInsertId()
308
  {
56 PointedEar 309
    return $this->database->lastInsertId;
27 PointedEar 310
  }
50 PointedEar 311
 
27 PointedEar 312
  /**
313
   * Delete a record from the table
314
   *
315
   * @param int $id
316
   *   ID of the record to delete.  May be <code>null</code>,
317
   *   in which case <var>$condition</var> must specify
318
   *   the records to be deleted.
319
   * @param array[optional] $condition
320
   *   Conditions that must be met for a record to be deleted.
321
   *   Ignored if <var>$id</var> is not <code>null</code>.
322
   * @return bool
323
   * @throws InvalidArgumentException if both <var>$id</var> and
324
   *     <var>$condition</var> are <code>null</code>.
325
   * @see Database::delete()
326
   */
50 PointedEar 327
  public function delete ($id, array $condition = null)
27 PointedEar 328
  {
50 PointedEar 329
    if ($id !== null)
27 PointedEar 330
    {
56 PointedEar 331
      $condition = array($this->id => $id);
27 PointedEar 332
    }
50 PointedEar 333
    else if ($condition === null)
27 PointedEar 334
    {
335
      throw new InvalidArgumentException(
336
        '$id and $condition cannot both be null');
337
    }
50 PointedEar 338
 
56 PointedEar 339
    return $this->database->delete($this->name, $condition);
27 PointedEar 340
  }
50 PointedEar 341
 
27 PointedEar 342
 /**
343
  * Inserts a row into the table or updates an existing one
344
  *
345
  * @param array $data
346
  *   Associative array of column-value pairs to be updated/inserted
347
  * @param string|array $condition
348
  *   If there are no records matching this condition, a row will be inserted;
349
  *   otherwise matching records are updated
350
  * @return bool
351
  * @see Table::update()
352
  * @see Table::insert()
353
  */
354
  public function updateOrInsert($data, array $condition = null)
355
  {
56 PointedEar 356
    if ($this->select($this->id, $condition))
27 PointedEar 357
    {
358
      return $this->update($data, $condition);
359
    }
360
 
50 PointedEar 361
        return $this->insert($data);
27 PointedEar 362
  }
363
 
364
  /**
365
   * Finds a record by ID
366
   *
367
   * @param mixed $id
35 PointedEar 368
   * @return array
27 PointedEar 369
   */
50 PointedEar 370
  public function find ($id)
27 PointedEar 371
  {
372
    /* DEBUG */
373
    if (defined('DEBUG') && DEBUG > 0)
374
    {
375
      debug($id);
376
    }
50 PointedEar 377
 
56 PointedEar 378
    $result = $this->select(null, array($this->id => $id));
50 PointedEar 379
 
35 PointedEar 380
    if ($result)
381
    {
382
      $result = $result[0];
383
    }
50 PointedEar 384
 
35 PointedEar 385
    return $result;
27 PointedEar 386
  }
387
}