Source for file TRepository.php
Documentation is available at TRepository.php
namespace
Adianti \
Database ;
* Implements the Repository Pattern to deal with collections of Active Records
* @author Pablo Dall'Oglio
* @copyright Copyright (c) 2006 Adianti Solutions Ltd. (http://www.adianti.com.br)
* @license http://www.adianti.com.br/framework-license
protected $class ; // Active Record class to be manipulated
protected $criteria ; // buffered criteria to use with fluent interfaces
* @param $class = Active Record class name
public function __construct ( $class , $withTrashed =
FALSE )
throw
new Exception ( AdiantiCoreTranslator :: translate ( 'The class ^1 was not accepted as argument. The class informed as parameter must be subclass of ^2.' , $class , 'TRecord' )) ;
throw
new Exception ( AdiantiCoreTranslator :: translate ( 'The class ^1 was not found. Check the class name or the file name. They must match' , '"' .
$class .
'"' )) ;
* Set withTrashed using fluent interfaces
* Returns the name of database entity
* @return A String containing the name of the entity
* Get attribute list from entity
$object =
new $this -> class ;
return $object -> getAttributeList ( ) ;
public function select ( $columns )
* Add a run time criteria using fluent interfaces
* @param $variable = variable
* @param $operator = comparison operator (>,<,=)
* @param $value = value to be compared
* @param $logicOperator = logical operator (TExpression::AND_OPERATOR, TExpression::OR_OPERATOR)
* @return A TRepository object
public function where ( $variable , $operator , $value , $logicOperator =
TExpression :: AND_OPERATOR )
$this -> criteria -> add ( new TFilter ( $variable , $operator , $value ) , $logicOperator ) ;
* Assign values to the database columns
* @param $column = column name
* @param $value = column value
* @return A TRepository object
public function set ( $column , $value )
* Add a run time OR criteria using fluent interfaces
* @param $variable = variable
* @param $operator = comparison operator (>,<,=)
* @param $value = value to be compared
* @return A TRepository object
public function orWhere ( $variable , $operator , $value )
* Define the ordering for criteria using fluent interfaces
* @param $order = Order column
* @param $direction = Order direction (asc, desc)
* @return A TRepository object
public function orderBy ( $order , $direction =
'asc' )
$this -> criteria -> setProperty ( 'order' , $order ) ;
$this -> criteria -> setProperty ( 'direction' , $direction ) ;
* Define the group for criteria using fluent interfaces
* @param $group Group column
* @return A TRepository object
$this -> criteria -> setProperty ( 'group' , $group ) ;
* Define the LIMIT criteria using fluent interfaces
* @return A TRepository object
public function take ( $limit )
$this -> criteria -> setProperty ( 'limit' , $limit ) ;
* Define the OFFSET criteria using fluent interfaces
* @param $offset = Offset
* @return A TRepository object
public function skip ( $offset )
$this -> criteria -> setProperty ( 'offset' , $offset ) ;
* Load a collection of objects from database using a criteria
* @param $criteria An TCriteria object, specifiyng the filters
* @param $callObjectLoad If load() method from Active Records must be called to load object parts
* @return An array containing the Active Records
public function load ( TCriteria $criteria =
NULL , $callObjectLoad =
TRUE )
$deletedat =
$this -> class :: getDeletedAtColumn ( ) ;
$criteria -> add ( new TFilter ( $deletedat , 'IS' , NULL )) ;
// creates a SELECT statement
// assign the criteria to the SELECT statement
$sql -> setCriteria ( $criteria ) ;
// get the connection of the active transaction
// register the operation in the LOG file
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$result =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$result -> execute ( $criteria -> getPreparedVars ( ) ) ;
$result =
$conn -> query ( $sql -> getInstruction ( )) ;
$callback =
array ( $class , 'load' ) ; // bypass compiler
// Discover if load() is overloaded
$rm =
new ReflectionMethod ( $class , $callback [ 1 ] ) ;
// iterate the results as objects
while ( $raw =
$result -> fetchObject ( ))
$object =
new $this -> class ;
$object -> onAfterLoadCollection ( $raw ) ;
$object -> fromArray ( (array)
$raw ) ;
// reload the object because its load() method may be overloaded
if ( $rm -> getDeclaringClass ( ) -> getName ( ) !==
'Adianti\Database\TRecord' )
if ( ( $cache =
$object -> getCacheControl ( )) &&
empty ( $this -> columns ))
$pk =
$object -> getPrimaryKey ( ) ;
$record_key =
$class .
'[' .
$object -> $pk .
']' ;
if ( $cache :: setValue ( $record_key , $object -> toArray ( ) ))
// store the object in the $results array
// if there's no active transaction opened
* Load with no aggregates
return $this -> load ( null , false ) ;
public function getIndexedArray ( $indexColumn , $valueColumn =
NULL , $criteria =
NULL )
$valueColumn =
$indexColumn ;
$criteria =
( empty ( $criteria )) ?
$this -> criteria :
$criteria ;
$objects =
$this -> load ( $criteria , FALSE ) ;
foreach ( $objects as $object )
$key =
( isset
( $object -> $indexColumn )) ?
$object -> $indexColumn :
$object -> render ( $indexColumn ) ;
$val =
( isset
( $object -> $valueColumn )) ?
$object -> $valueColumn :
$object -> render ( $valueColumn ) ;
$indexedArray [ $key ] =
$val ;
if ( empty ( $criteria ) or ( $criteria instanceof
TCriteria and empty ( $criteria -> getProperty ( 'order' )) ))
* Update values in the repository
public function update ( $setValues =
NULL , TCriteria $criteria =
NULL )
$deletedat =
$this -> class :: getDeletedAtColumn ( ) ;
$criteria -> add ( new TFilter ( $deletedat , 'IS' , NULL )) ;
$setValues = isset
( $setValues ) ?
$setValues :
$this -> setValues ;
// get the connection of the active transaction
// creates a UPDATE statement
foreach ( $setValues as $column =>
$value )
$sql -> setRowData ( $column , $value ) ;
// assign the criteria to the UPDATE statement
$sql -> setCriteria ( $criteria ) ;
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$statement =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$result =
$statement -> execute ( $sql -> getPreparedVars ( ) ) ;
// execute the UPDATE statement
$result =
$conn -> exec ( $sql -> getInstruction ( )) ;
// register the operation in the LOG file
if ( $cache =
$record -> getCacheControl ( ) )
$pk =
$record -> getPrimaryKey ( ) ;
// creates a SELECT statement
// assign the criteria to the SELECT statement
$sql -> setCriteria ( $criteria ) ;
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$subresult =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$subresult -> execute ( $criteria -> getPreparedVars ( ) ) ;
$subresult =
$conn -> query ( $sql -> getInstruction ( )) ;
// iterate the results as objects
while ( $raw =
$subresult -> fetchObject ( ))
$object =
new $this -> class ;
$object -> fromArray ( (array)
$raw ) ;
$record_key =
$class .
'[' .
$raw -> $pk .
']' ;
if ( $cache :: setValue ( $record_key , $object -> toArray ( ) ))
// if there's no active transaction opened
* Delete a collection of Active Records from database
* @param $criteria An TCriteria object, specifiyng the filters
* @return The affected rows
public function delete ( TCriteria $criteria =
NULL , $callObjectLoad =
FALSE )
$deletedat =
$this -> class :: getDeletedAtColumn ( ) ;
$criteria -> add ( new TFilter ( $deletedat , 'IS' , NULL )) ;
// get the connection of the active transaction
if ( ( $cache =
$record -> getCacheControl ( )) OR $callObjectLoad )
$pk =
$record -> getPrimaryKey ( ) ;
// creates a SELECT statement
// assign the criteria to the SELECT statement
$sql -> setCriteria ( $criteria ) ;
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$result =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$result -> execute ( $criteria -> getPreparedVars ( ) ) ;
$result =
$conn -> query ( $sql -> getInstruction ( )) ;
// iterate the results as objects
while ( $row =
$result -> fetchObject ( ))
$record_key =
$class .
'[' .
$row -> $pk .
']' ;
if ( $cache :: delValue ( $record_key ))
$object =
new $this -> class ;
$object -> fromArray ( (array)
$row ) ;
// creates a Update instruction
$date_mask =
( in_array ( $info [ 'type' ] , [ 'sqlsrv' , 'dblib' , 'mssql' ] )) ?
'Ymd H:i:s' :
'Y-m-d H:i:s' ;
$sql -> setRowData ( $deletedat , date ( $date_mask )) ;
// creates a DELETE statement
// assign the criteria to the DELETE statement
$sql -> setCriteria ( $criteria ) ;
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$result =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$result -> execute ( $sql -> getPreparedVars ( )) ;
$result -> execute ( $criteria -> getPreparedVars ( )) ;
// execute the DELETE statement
$result =
$conn -> exec ( $sql -> getInstruction ( )) ;
// register the operation in the LOG file
// if there's no active transaction opened
* Return the amount of objects that satisfy a given criteria
* @param $criteria An TCriteria object, specifiyng the filters
* @return An Integer containing the amount of objects that satisfy the criteria
public function count ( TCriteria $criteria =
NULL )
$deletedat =
$this -> class :: getDeletedAtColumn ( ) ;
$criteria -> add ( new TFilter ( $deletedat , 'IS' , NULL )) ;
// creates a SELECT statement
$sql -> addColumn ( 'count(*)' ) ;
// assign the criteria to the SELECT statement
$sql -> setCriteria ( $criteria ) ;
// get the connection of the active transaction
// register the operation in the LOG file
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$result =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$result -> execute ( $criteria -> getPreparedVars ( ) ) ;
// executes the SELECT statement
$result =
$conn -> query ( $sql -> getInstruction ( )) ;
// if there's no active transaction opened
* Count distinct aggregate
* @param $column Column to be aggregated
* @return An array of objects or the total value (if does not have group by)
$alias =
is_null ( $alias ) ?
$column :
$alias ;
return $this -> aggregate ( 'count' , 'distinct ' .
$column , $alias ) ;
* @param $column Column to be aggregated
* @param $alias Column alias
* @return An array of objects or the total value (if does not have group by)
public function countBy ( $column , $alias =
null )
return $this -> aggregate ( 'count' , $column , $alias ) ;
* Count aggregate and do another aggregate after
* @param $column Column to be aggregated
* @param $alias Column alias
public function countByAnd ( $column , $alias =
null )
$this -> aggregates [ ] =
" count({$column } ) as \"{$alias } \" " ;
* @param $column Column to be aggregated
* @param $alias Column alias
* @return An array of objects or the total value (if does not have group by)
public function sumBy ( $column , $alias =
null )
return $this -> aggregate ( 'sum' , $column , $alias ) ;
* Sum aggregate and do another aggregate after
* @param $column Column to be aggregated
* @param $alias Column alias
public function sumByAnd ( $column , $alias =
null )
$this -> aggregates [ ] =
" sum({$column } ) as \"{$alias } \" " ;
* @param $column Column to be aggregated
* @param $alias Column alias
* @return An array of objects or the total value (if does not have group by)
public function avgBy ( $column , $alias =
null )
return $this -> aggregate ( 'avg' , $column , $alias ) ;
* Average aggregate and do another aggregate after
* @param $column Column to be aggregated
* @param $alias Column alias
public function avgByAnd ( $column , $alias =
null )
$this -> aggregates [ ] =
" avg({$column } ) as \"{$alias } \" " ;
* @param $column Column to be aggregated
* @param $alias Column alias
* @return An array of objects or the total value (if does not have group by)
public function minBy ( $column , $alias =
null )
return $this -> aggregate ( 'min' , $column , $alias ) ;
* Min aggregate and do another aggregate after
* @param $column Column to be aggregated
* @param $alias Column alias
public function minByAnd ( $column , $alias =
null )
$this -> aggregates [ ] =
" min({$column } ) as \"{$alias } \" " ;
* @param $column Column to be aggregated
* @param $alias Column alias
* @return An array of objects or the total value (if does not have group by)
public function maxBy ( $column , $alias =
null )
return $this -> aggregate ( 'max' , $column , $alias ) ;
* Max aggregate and do another aggregate after
* @param $column Column to be aggregated
* @param $alias Column alias
public function maxByAnd ( $column , $alias =
null )
$this -> aggregates [ ] =
" max({$column } ) as \"{$alias } \" " ;
* @param $function Aggregate function (count, sum, min, max, avg)
* @return An array of objects or the total value (if does not have group by)
protected function aggregate ( $function , $column , $alias =
null )
$alias =
$alias ?
$alias :
$column ;
// creates a SELECT statement
if ( ! empty ( $this -> criteria -> getProperty ( 'group' ) ))
$sql -> addColumn ( $this -> criteria -> getProperty ( 'group' ) ) ;
$sql -> addColumn ( $aggregate ) ;
$sql -> addColumn ( " $function ({$column } ) as \"{$alias } \"" ) ;
// assign the criteria to the SELECT statement
$sql -> setCriteria ( $criteria ) ;
// get the connection of the active transaction
// register the operation in the LOG file
if ( isset
( $dbinfo [ 'prep' ] ) AND $dbinfo [ 'prep' ] ==
'1' ) // prepared ON
$result =
$conn -> prepare ( $sql -> getInstruction ( TRUE ) , array ( PDO :: ATTR_CURSOR =>
PDO :: CURSOR_FWDONLY )) ;
$result -> execute ( $criteria -> getPreparedVars ( ) ) ;
// executes the SELECT statement
$result =
$conn -> query ( $sql -> getInstruction ( )) ;
// iterate the results as objects
while ( $raw =
$result -> fetchObject ( ))
if ( ( count ( $results ) >
1 ) ||
! empty ( $this -> criteria -> getProperty ( 'group' )))
return $results [ 0 ] -> $alias ;
// if there's no active transaction opened
public function get ( TCriteria $criteria =
NULL , $callObjectLoad =
TRUE )
return $this -> load ( $criteria , $callObjectLoad ) ;
* Returns the first collection item
public function first ( $callObjectLoad =
TRUE )
$collection =
$this -> take ( 1 ) -> load ( null , $callObjectLoad ) ;
if ( isset
( $collection [ 0 ] ))
* Returns the last collection item
public function last ( $callObjectLoad =
TRUE )
$pk =
( new $class ) -> getPrimaryKey ( ) ;
$collection =
$this -> orderBy ( $pk , 'desc' ) -> take ( 1 ) -> load ( null , $callObjectLoad ) ;
if ( isset
( $collection [ 0 ] ))
* Returns transformed collection
public function transform ( Callable
$callback , $callObjectLoad =
TRUE )
$collection =
$this -> load ( null , $callObjectLoad ) ;
foreach ( $collection as $object )
* Returns filtered collection
public function filter ( Callable
$callback , $callObjectLoad =
TRUE )
$collection =
$this -> load ( null , $callObjectLoad ) ;
foreach ( $collection as $object )
$newcollection [ ] =
$object ;
public function dump ( $prepared =
FALSE )
$deletedat =
$this -> class :: getDeletedAtColumn ( ) ;
$criteria -> add ( new TFilter ( $deletedat , 'IS' , NULL )) ;
return $criteria -> dump ( $prepared ) ;