Subversion Repositories PHPX

Rev

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

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