Subversion Repositories PHPX

Rev

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

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