Subversion Repositories PHPX

Rev

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

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