PhpToolCase
Api Documentation Version 0.9.2
PtcMapper.php
Go to the documentation of this file.
1 <?php
2 
3  /**
4  * PHP TOOLCASE OBJECT RELATIONAL MAPPING CLASS
5  * PHP version 5.3
6  * @category Library
7  * @version 0.9.2
8  * @author Irony <carlo@salapc.com>
9  * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
10  * @link http://phptoolcase.com
11  */
12 
13  class PtcMapper
14  {
15  /**
16  * Retrives the query builder from the connection manager and table column names
17  */
18  public function __construct( ){ static::_initialize( ); }
19  /**
20  * Resets previously set values
21  */
22  public function reset( ) { $this->_fields = array( ); }
23  /**
24  * Removes values from fields property
25  * @param string $key the table column name
26  */
27  public function remove( $key ) { unset( $this->_fields[ $key ] ); }
28  /**
29  * Returns values as an associative array. See @ref convert_to_array
30  */
31  public function toArray( ){ return $this->_fields; }
32  /**
33  * Returns values as a json array. See @ref convert_to_json
34  */
35  public function toJson( ){ return json_encode( $this->_fields ); }
36  /**
37  * Sets values based on associative array. See @ref adding_record
38  * @param array $array an associative array with values
39  * @return the new created record
40  */
41  public static function create( $array )
42  {
43  $class = get_called_class( );
44  $record = new $class( );
45  foreach ( $array as $k => $v ){ $record->$k = $v; }
46  return $record;
47  }
48  /**
49  * Deletes record in table based on id. See @ref delete_record
50  * @return the number of affected rows
51  */
52  public function delete( )
53  {
54  $storage = static::$_storage[ get_called_class( ) ];
55  static::_fireEvent( 'deleting' , array(
56  &$this->_fields[ static::$_uniqueKey ] , &$this->_fields ) );
57  $result = static::_getQB( )->table( $storage[ 'table' ] )
58  ->delete( $this->_fields[ static::$_uniqueKey ] )
59  ->run( );
60  static::_fireEvent( 'deleted' ,
61  array( &$this->_fields[ static::$_uniqueKey ] , &$this->_fields , &$result ) );
62  //$this->reset( ); // reset fields
63  return $result;
64  }
65  /**
66  * Inserts a new record in table. See @ref adding_record and @ref update_record
67  * @return the numbr of affected rows
68  */
69  public function save( )
70  {
71  $storage = static::$_storage[ get_called_class( ) ];
72  if ( empty( $this->_fields ) )
73  {
74  trigger_error( 'Nothing to save in table' . static::$storage[ 'table' ] .
75  '!' , E_USER_WARNING );
76  return false;
77  }
78  static::_mapFields( );
79  $values = $this->_fields;
80  static::_fireEvent( 'saving' , array( &$values ) );
81  if ( array_key_exists( static::$_uniqueKey , $this->_fields ) ) // update record
82  {
83  static::_fireEvent( 'updating' , array( &$values ) );
84  unset( $values[ static::$_uniqueKey ] );
85  $result = static::_getQB( )->table( $storage[ 'table' ] )
86  ->update( $values , $this->_fields[ static::$_uniqueKey ] )
87  ->run( );
88  static::_fireEvent( 'updated' , array( &$values , $result ) );
89  }
90  else // insert new row
91  {
92  static::_fireEvent( 'inserting' , array( &$values ) );
93  $result = static::_getQB( )->table( $storage[ 'table' ] )
94  ->insert( $this->_fields )->run( );
95  static::_fireEvent( 'inserted' , array( &$values , $result ) );
96  }
97  static::_fireEvent( 'saved' , array( &$values , $result ) );
98  //$this->reset( ); // reset fields
99  return $result;
100  }
101  /**
102  * Retrieves single record from the table based on id. See @ref retrieve_record_by_id
103  * @param int $id the record id
104  * @return a new instance of this class.
105  */
106  public static function find( $id )
107  {
108  $class = static::_initialize( );
109  static::_getQB( )->setFetchMode( PDO::FETCH_CLASS |
110  PDO::FETCH_PROPS_LATE , $class );
111  return $result = static::_getQB( )->table( static::$_storage[ $class ][ 'table' ] )
112  ->where( 'id' , '=' , $id )
113  ->row( );
114  }
115  /**
116  * Gets all records. See @ref retrieve_records
117  * @return an array with multiple instances of this class as rows
118  */
119  public static function all( )
120  {
121  $class = static::_initialize( );
122  static::_getQB( )->setFetchMode( PDO::FETCH_CLASS |
123  PDO::FETCH_PROPS_LATE , $class );
124  return $result = static::_getQB( )->table( static::$_storage[ $class ][ 'table' ] )
125  ->run( );
126  }
127  /**
128  * Retrieves column names from table
129  @return an associative array with column names as keys
130  */
131  public static function getColumns( )
132  {
133  $class = static::_initialize( );
134  if ( array_key_exists( 'columns' , static::$_storage[ $class ] ) )
135  {
136  return static::$_storage[ $class ][ 'columns' ];
137  }
138  $cols = array( );
139  static::_getQB( )->setFetchMode( PDO::FETCH_ASSOC );
140  $columns = static::_getQB( )->run( 'SHOW COLUMNS FROM ' .
141  static::_getQB( )->sanitize( static::$_storage[ $class ][ 'table' ] ) );
142  foreach ( $columns as $name ){ $cols[ $name[ 'Field' ] ] = $name[ 'Field' ]; }
143  return static::$_storage[ $class ][ 'columns' ] = $cols;
144  }
145  /**
146  * Adds observers to the class to use event listeners with the queries. See @ref using_observers
147  * @param string $class the name of the class that will be used as observer
148  */
149  public static function observe( $class = null )
150  {
151  if ( !class_exists( $events_class = static::$_eventClass ) )
152  {
153  trigger_error( $events_class . ' NOT FOUND!' , E_USER_ERROR );
154  return false;
155  }
156  $class = ( $class ) ? $class : get_called_class( );
157  $methods = get_class_methods( $class );
158  foreach ( static::$_events as $event )
159  {
160  if ( in_array( $event , $methods ) )
161  {
162  $cls = strtolower( $class );
163  $events_class::listen( $cls . '.' . $event , $class . '::' . $event );
164  static::$_observers[ get_called_class( ) ][ $cls . '.' . $event ] = $event;
165  }
166  }
167  }
168  /**
169  * Sets values
170  * @param string $key the column name
171  * @param mixed $value the value
172  */
173  public function __set( $key , $value )
174  {
175  if ( !static::_checkColumn( $key ) ){ return false; }
176  return $this->_fields[ $key ] = $value;
177  }
178  /**
179  * Retrieves values
180  * @param string $key the column name
181  */
182  public function __get( $key )
183  {
184  if ( !static::_checkColumn( $key ) ){ return false; }
185  return $this->_fields[ $key ];
186  }
187  /**
188  * Calls shortcut methods for getting / setting single values, or the QueryBuilder methods directly.
189  * See @ref update_single_value , @ref retrieve_single_value and @ref using_query_builder
190  * @param string $method the method name
191  * @param array $args an array with arguments for the method
192  * @return the result of the query
193  */
194  public static function __callStatic( $method , $args )
195  {
196  $class = static::_initialize( );
197  if ( strpos( $method , 'get_' ) === 0 )
198  {
199  $meth = explode( 'get_' , $method );
200  if ( !static::_checkColumn( $meth[ 1 ] ) ){ return false; }
201  $column = ( !array_key_exists( 1 , $args ) ) ? static::$_uniqueKey : $args[ 0 ];
202  $value = ( !array_key_exists( 1 , $args ) ) ? $args[ 0 ] : $args[ 1 ];
203  return static::_getQB( )->table( static::$_storage[ $class ][ 'table' ] )
204  ->where( $column , '=' , $value )
205  ->row( $meth[ 1 ] );
206  }
207  else if ( strpos( $method , 'set_' ) === 0 )
208  {
209  $meth = explode( 'set_' , $method );
210  if ( !static::_checkColumn( $meth[ 1 ] ) ){ return false; }
211  static::_fireEvent( array( 'saving' , 'updating' ) , array( &$meth , &$args ) );
212  $result = static::_getQB( )->table( static::$_storage[ $class ][ 'table' ] )
213  ->where( static::$_uniqueKey , '=' , $args[ 1 ] )
214  ->update( array( $meth[ 1 ] => $args[ 0 ] ) )
215  ->run( );
216  static::_fireEvent( array( 'updated' , 'saved' ) , array( &$meth , &$args , &$result ) );
217  return $result;
218  }
219  $qb = static::_getQB( )->table( static::$_storage[ $class ][ 'table' ] );
220  $qb->setFetchMode( PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE , $class );
221  return call_user_func_array( array( $qb , $method ), $args );
222  }
223  /**
224  * Database table property
225  */
226  protected static $_table = null;
227  /**
228  * Unique row identifier column name
229  */
230  protected static $_uniqueKey = 'id';
231  /**
232  * Maps column names to fields, if "as" is used. See @ref mapping_fields
233  */
234  protected static $_map = array( );
235  /**
236  * Event class name property. See @ref specifyEventClass
237  */
238  protected static $_eventClass = '\PtcEvent';
239  /**
240  * Connection Manager class name property. See @ref specifyConnectionManagerClass
241  */
242  protected static $_connectionManager = 'PtcDb';
243  /**
244  * Connection name to be used property. See @ref change_connection
245  */
246  protected static $_connectionName ='default';
247  /**
248  * Possible observer events array. See @ref using_observers
249  */
250  protected static $_events = array
251  (
252  'inserting' , 'inserted' , 'updating' , 'updated' ,
253  'deleting' , 'deleted' , 'saving' , 'saved'
254  );
255  /**
256  * Property that holds the observer classes
257  */
258  protected static $_observers = array( );
259  /**
260  * Column and table names property
261  */
262  protected static $_storage = array( );
263  /**
264  * Array of created values property
265  */
266  protected $_fields = array( );
267  /**
268  * Checks if a given column name exists in table
269  * @param string $column the value to check
270  * @return true if column exists, false otherwise
271  */
272  protected static function _checkColumn( $column )
273  {
274  $storage = static::$_storage[ get_called_class( ) ];
275  if ( !array_key_exists( $column , $storage[ 'columns' ] ) &&
276  !in_array( $column , static::$_map ) )
277  {
278  trigger_error( 'Column ' . $column . ' does not exists in table ' .
279  $storage[ 'table' ] . '!' , E_USER_ERROR );
280  return false;
281  }
282  return true;
283  }
284  /**
285  * Fires events if methods are present in observers classes. See @ref using_observers
286  * @param string $event the event name stored in the $_observers property
287  * @param array $data in array with the data to pass to the listeners
288  */
289  protected static function _fireEvent( $event , $data )
290  {
291  $event = ( is_array( $event ) ) ? $event : array( $event );
292  $event_class = static::$_eventClass;
293  if ( array_key_exists( $class = get_called_class( ) , static::$_observers ) )
294  {
295  foreach ( static::$_observers[ $class ] as $k => $v )
296  {
297  foreach ( $event as $ev )
298  {
299  if ( $v === $ev ){ $event_class::fire( $k , $data ); }
300  }
301  }
302  }
303  }
304  /**
305  * Retrieve the query builder object if present
306  */
307  protected static function _getQB( )
308  {
309  $manager = static::$_connectionManager;
310  return call_user_func( $manager . '::getQB' , static::$_connectionName );
311  }
312  /**
313  * Initializes the class, adding columns and table name to the PtcMapper::$_storage property.
314  * See @ref using_boot
315  * @return the name of called class as string
316  */
317  protected static function _initialize( )
318  {
319  $db = static::_getQB( );
320  if ( !array_key_exists( $class = get_called_class( ) , static::$_storage ) )
321  {
322  static::$_storage[ $class ] = array( );
323  if ( static::$_table ){ static::$_storage[ $class ][ 'table' ] = static::$_table; }
324  else
325  {
326  static::$_storage[ $class ][ 'table' ] = strpos( $class , '\\' ) ?
327  strtolower( end( explode( '\\' . $class ) ) ) : strtolower( $class );
328  }
329  $db->run( 'SHOW TABLES LIKE ?' , array( static::$_storage[ $class ][ 'table' ] ) );
330  if ( !$db->countRows( ) )
331  {
332  trigger_error( 'Table ' . static::$_storage[ $class ][ 'table' ] .
333  ' does not exists, quitting now!' , E_USER_ERROR );
334  return false;
335  }
336  static::$_storage[ $class ][ 'columns' ] = static::getColumns( );
337  if ( method_exists( $class , 'boot' ) ){ static::boot( ); }
338  }
339  return $class;
340  }
341  /**
342  * Replaces column names with values in the PtcMapper::$_map property. See @ref mapping_fields
343  */
344  protected function _mapFields( )
345  {
346  if ( !empty( static::$_map ) )
347  {
348  foreach ( static::$_map as $k => $v )
349  {
350  if ( array_key_exists( $v , $this->_fields ) )
351  {
352  $this->_fields[ $k ] = $this->_fields[ $v ];
353  unset( $this->_fields[ $v ] );
354  }
355  }
356  }
357  }
358  /**
359  * Retrieves last inserted id
360  */
361  public static function lastId( )
362  {
363  static::_initialize( );
364  return static::_getQB( )->lastId( );
365  }
366  }
save()
Inserts a new record in table.
Definition: PtcMapper.php:69
static $_uniqueKey
Unique row identifier column name.
Definition: PtcMapper.php:230
_mapFields()
Replaces column names with values in the PtcMapper::$_map property.
Definition: PtcMapper.php:344
static _initialize()
Initializes the class, adding columns and table name to the PtcMapper::$_storage property.
Definition: PtcMapper.php:317
__set($key, $value)
Sets values.
Definition: PtcMapper.php:173
__construct()
Retrives the query builder from the connection manager and table column names.
Definition: PtcMapper.php:18
static __callStatic($method, $args)
Calls shortcut methods for getting / setting single values, or the QueryBuilder methods directly...
Definition: PtcMapper.php:194
static getColumns()
Retrieves column names from table.
Definition: PtcMapper.php:131
static $_storage
Column and table names property.
Definition: PtcMapper.php:262
toJson()
Returns values as a json array.
Definition: PtcMapper.php:35
toArray()
Returns values as an associative array.
Definition: PtcMapper.php:31
static find($id)
Retrieves single record from the table based on id.
Definition: PtcMapper.php:106
static $_eventClass
Event class name property.
Definition: PtcMapper.php:238
__get($key)
Retrieves values.
Definition: PtcMapper.php:182
static _fireEvent($event, $data)
Fires events if methods are present in observers classes.
Definition: PtcMapper.php:289
$_fields
Array of created values property.
Definition: PtcMapper.php:266
static $_events
Possible observer events array.
Definition: PtcMapper.php:250
static $_table
Database table property.
Definition: PtcMapper.php:226
static $_connectionName
Connection name to be used property.
Definition: PtcMapper.php:246
reset()
Resets previously set values.
Definition: PtcMapper.php:22
static _getQB()
Retrieve the query builder object if present.
Definition: PtcMapper.php:307
static $_observers
Property that holds the observer classes.
Definition: PtcMapper.php:258
static $_map
Maps column names to fields, if &quot;as&quot; is used.
Definition: PtcMapper.php:234
static $_connectionManager
Connection Manager class name property.
Definition: PtcMapper.php:242
static create($array)
Sets values based on associative array.
Definition: PtcMapper.php:41
static all()
Gets all records.
Definition: PtcMapper.php:119
static _checkColumn($column)
Checks if a given column name exists in table.
Definition: PtcMapper.php:272
static observe($class=null)
Adds observers to the class to use event listeners with the queries.
Definition: PtcMapper.php:149
static lastId()
Retrieves last inserted id.
Definition: PtcMapper.php:361