Subversion Repositories PHPX

Rev

Rev 56 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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