Subversion Repositories PHPX

Rev

Rev 65 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
27 PointedEar 1
<?php
2
 
52 PointedEar 3
namespace PointedEars\PHPX;
29 PointedEar 4
 
27 PointedEar 5
/**
51 PointedEar 6
* Abstract model class for Object-Relational Mapping
27 PointedEar 7
*
51 PointedEar 8
* Provides simple mapping of a model object to records of
9
* a table of a relational database.
27 PointedEar 10
*
62 PointedEar 11
* @property Db\Table $persistentTable
27 PointedEar 12
* @author Thomas Lahn
13
*/
52 PointedEar 14
abstract class Model extends \PointedEars\PHPX\AbstractModel
27 PointedEar 15
{
16
  /**
51 PointedEar 17
   * The <code>Table</code> for instances of this model
18
   *
19
   * @type Table|string
27 PointedEar 20
   */
54 PointedEar 21
        protected static $_persistentTable;
51 PointedEar 22
 
27 PointedEar 23
  /**
51 PointedEar 24
   * The name(s) of the property or properties whose value(s)
25
   * identify this object in the <code>Table</code>.  They are
26
   * used for comparing against the primary key column(s) of
27
   * the <code>Table</code>.
28
   *
29
   * @type string|array[string]
30
   */
55 PointedEar 31
        protected static $_persistentId = 'id';
51 PointedEar 32
 
33
  /**
34
   * The names of the properties that should be used in database
35
   * queries, and their mapping to the columns of
36
   * the <code>Table</code>, if specified (keys are property names,
37
   * values are column names, or both if the key is numeric).
38
   *
53 PointedEar 39
   * NOTE: It should not be necessary to include the
40
   * <code>persistentId</code> property value here.  If an object
41
   * is not in the database, it should be assigned an ID
42
   * automatically when saved; if it is in the database,
43
   * you already have its ID as you searched by it.
44
   *
51 PointedEar 45
   * @type array
46
   */
55 PointedEar 47
  protected static $_persistentProperties = array();
51 PointedEar 48
 
49
        /**
27 PointedEar 50
   * Creates a new model object
51
   *
51 PointedEar 52
   * @see AbstractModel::__construct()
27 PointedEar 53
   */
63 PointedEar 54
  public function __construct (
55
    array $data = null, array $mapping = null, $exclusiveMapping = false)
27 PointedEar 56
  {
63 PointedEar 57
    parent::__construct($data, $mapping, $exclusiveMapping);
27 PointedEar 58
  }
51 PointedEar 59
 
60
  public function getPersistentTable ()
61
  {
54 PointedEar 62
        $class = \get_class($this);
63
        if (\is_string($class::$_persistentTable))
51 PointedEar 64
        {
65
                /* Call setter to convert to Table */
54 PointedEar 66
                $this->setPersistentTable($class::$_persistentTable);
51 PointedEar 67
        }
68
 
54 PointedEar 69
        return $class::$_persistentTable;
51 PointedEar 70
  }
71
 
72
  public function setPersistentTable ($value)
73
  {
54 PointedEar 74
        $class = \get_class($this);
51 PointedEar 75
        if ($value instanceof Table)
76
        {
54 PointedEar 77
                $class::$_persistentTable = $value;
51 PointedEar 78
        }
79
        else
80
        {
81
                $table = new $value();
52 PointedEar 82
                if (!($table instanceof Db\Table))
51 PointedEar 83
                {
84
                        throw new \InvalidArgumentException(
52 PointedEar 85
                                'Parameter does not specify a subclass of \\PointedEars\\PHPX\\Table: '
86
                                . $value
51 PointedEar 87
                        );
88
                }
89
 
54 PointedEar 90
                $class::$_persistentTable = $table;
51 PointedEar 91
        }
92
  }
93
 
27 PointedEar 94
  /**
67 PointedEar 95
   * Returns an array containing the property-column mapping.
96
   *
97
   * @param array $propertyNames = null
98
   *   Names of the properties that should be included.
99
   *   The default is to include all persistent properties.
100
   * @return array
101
   */
102
  public static function getPersistentMapping (array $propertyNames = null)
103
  {
104
    $a = array();
105
 
106
        $persistent_properties = static::$_persistentProperties;
107
 
108
        if ($propertyNames === null)
109
        {
110
                $propertyNames = $persistent_properties;
111
        }
112
 
113
        foreach ($propertyNames as $property_name)
114
        {
115
          if (!array_key_exists($property_name, $persistent_properties))
116
          {
117
                        $column_name = $property_name;
118
          }
119
          else
120
          {
121
            $column_name = $persistent_properties[$property_name];
122
          }
123
 
124
                $a[$property_name] = $column_name;
125
        }
126
 
127
        return $a;
128
  }
129
 
130
  /**
51 PointedEar 131
   * Returns an array for database queries containing the
132
   * property values of this object, using the specified
133
   * property-to-column mapping.
134
   *
135
   * @param array $propertyNames = null
136
   *   Names of the properties that should be included.
137
   *   The default is to include all persistent properties.
138
   * @return array
27 PointedEar 139
   */
51 PointedEar 140
  public function getPropertyArray (array $propertyNames = null)
27 PointedEar 141
  {
51 PointedEar 142
        $a = array();
143
 
144
        if ($propertyNames === null)
145
        {
55 PointedEar 146
                $class = \get_class($this);
147
                $propertyNames = $class::$_persistentProperties;
51 PointedEar 148
        }
149
 
150
        foreach ($propertyNames as $propertyName => $columnName)
151
        {
152
                if (is_numeric($propertyName))
153
                {
154
                        $propertyName = $columnName;
155
                }
156
 
157
                $a[$columnName] = $this->$propertyName;
158
        }
159
 
160
        return $a;
27 PointedEar 161
  }
51 PointedEar 162
 
163
  /**
53 PointedEar 164
   * Finds the record for the model object in the table, fills
51 PointedEar 165
   * the object with missing data, and returns the result.
166
   *
62 PointedEar 167
   * @param mixed $id = null
168
   *   The ID of the object to find.  If <code>null</code> (default),
67 PointedEar 169
   *   the object is searched for by its current ID.
51 PointedEar 170
   * @return Model|null
171
   *   This object filled with missing data, or <code>null</code>
172
   *   if there is no data for this object
67 PointedEar 173
   * @see Table::find(int)
51 PointedEar 174
   */
62 PointedEar 175
  public function find ($id = null)
51 PointedEar 176
  {
54 PointedEar 177
        $class = \get_class($this);
65 PointedEar 178
        if ($id === null)
179
        {
180
          $id = $this->{$class::$_persistentId};
181
        }
182
 
183
    $result = $this->persistentTable->find($id);
62 PointedEar 184
    if ($id !== null)
185
    {
186
      $this->{$class::$_persistentId} = $id;
187
    }
188
 
55 PointedEar 189
    $result = $this->persistentTable->find($this->{$class::$_persistentId});
51 PointedEar 190
    if ($result)
191
    {
192
        return $this->map($result);
193
    }
194
 
195
    return null;
196
  }
197
 
198
  /**
67 PointedEar 199
   * Finds the records for model objects in the table by value,
200
   * and returns the result.
201
   *
202
   * @param string $name
203
   *   Name of the property to search for.
204
   * @param mixed $value = null
205
   *   The property value to find.  If <code>null</code>,
206
   *   the current value of the specified property is used.
207
   *   (To search for null, you need to make sure that the
208
   *   current property value is <code>null</code>, which is
209
   *   the PHP default.)
210
   * @return array[Model]|null
211
   *   Model objects, or <code>null</code> if there is no data
212
   *   for this property and value
213
   * @see Table::select(Model)
214
   */
215
  public function findByProperty ($name, $value = null)
216
  {
217
    $class = \get_class($this);
218
        $mapping = $class::getPersistentMapping(array($name));
219
 
220
        if ($value === null)
221
        {
222
          $value = $this->$name;
223
        }
224
 
225
    $results = $this->persistentTable->select(null,
226
      array($mapping[$name] => $value));
227
 
228
    if ($results)
229
    {
230
        return array_map(array($this, 'map'), $results);
231
    }
232
 
233
    return null;
234
  }
235
 
236
  /**
53 PointedEar 237
   * Saves the model object in the table
51 PointedEar 238
   *
239
   * @param array $propertyNames = null
240
   *   Names of the properties whose values should be saved
241
   *   in the database.  The default is to save the values
242
   *   of all persistent properties.
243
   * @return boolean
62 PointedEar 244
   *   The return value of
245
   *   <code>$this->persistentTable->updateOrInsert()</code>.
51 PointedEar 246
   * @see Model::getPropertyArray()
247
   * @see Table::updateOrInsert()
248
   */
249
  public function save (array $propertyNames = null)
250
  {
53 PointedEar 251
        $table = $this->persistentTable;
55 PointedEar 252
        $class = \get_class($this);
253
        $idPropertyName = $class::$_persistentId;
53 PointedEar 254
 
255
        $result = $table->updateOrInsert(
256
                $this->getPropertyArray($propertyNames),
257
                array(
258
                        $table->id => $this->$idPropertyName
51 PointedEar 259
                )
260
        );
53 PointedEar 261
 
262
        if ($result && ($lastInsertId = $table->lastInsertId))
263
        {
264
                $this->$idPropertyName = $lastInsertId;
265
        }
266
 
267
        return $result;
51 PointedEar 268
  }
269
 
270
  /**
53 PointedEar 271
   * Inserts the model object into the table
272
   *
273
   * @param array $propertyNames = null
274
   *   Names of the properties whose values should be insert
275
   *   in the database.  The default is to insert the values
276
   *   of all persistent properties.
277
   * @return boolean
278
   * @see Model::getPropertyArray()
279
   * @see Table::insert()
280
   */
281
  public function insert (array $propertyNames = null)
282
  {
283
        $table = $this->persistentTable;
55 PointedEar 284
        $class = \get_class($this);
285
        $idPropertyName = $class::$_persistentId;
53 PointedEar 286
 
287
        $result = $table->insert($this->getPropertyArray($propertyNames));
288
 
289
        if ($result && ($lastInsertId = $table->lastInsertId))
290
        {
291
                $this->$idPropertyName = $lastInsertId;
292
        }
293
 
294
        return $result;
295
  }
296
 
297
  /**
51 PointedEar 298
   * Deletes a model object from the <code>Table</code>
299
   *
300
   * @return bool
301
   * @see Table::delete()
302
   */
303
  public function delete ()
304
  {
55 PointedEar 305
        $class = \get_class($this);
306
        return $this->persistentTable->delete($this->{$class::$_persistentId});
51 PointedEar 307
  }
27 PointedEar 308
}