src/Persist/Model.php
public static function find($filters,$sort = null,$pagination = null, $where = null){

        self::$_lastFindQuery = null;
        $calledClassName = get_called_class();

        $classList = RelationalMappingUtil::getClassConfiguration($calledClassName);
        $resultList = array();
        try{
        
        	TransactionManager::startTransaction();
        	$connection = TransactionManager::getConnection();
        	
	        $readAccessWhereClause = self::checkAccess($calledClassName, "User don't have access to Read");
	        
	        foreach ($classList as $className=>$class){
	        	self::runTrigger($className, self::TRIGGER_EVENT_READ, self::TRIGGER_TYPE_PRE, array(array("filters"=>$filters,"sort"=>$sort,"pagination"=>$pagination, "where"=>$where)));
	        }
	
	        if($readAccessWhereClause instanceof Expression){
	        	if($where instanceof Expression){
	        		$where = new Expression(self::OPERATOR_AND, array($where,$readAccessWhereClause));
	        	}else {
	        		$where = $readAccessWhereClause;
	        	}
	        }
	        $Clauses = self::generateClauses($connection,$classList, $filters, $sort, $where);
	        
	        $selectClause  = $Clauses["selectClause"];
	        $fromClause    = $Clauses["fromClause"];
	        $whereClause   = $Clauses["whereClause"];
	        $groupByClause = $Clauses["groupByClause"];
	        $orderByClause = $Clauses["orderByClause"];
	        
	        $i = 0;
	        
	        $classCount = count($classList);
	        foreach($classList as $className=>$class){
	            //skip the last class
	            if($i < $classCount-1){
	                if($whereClause != ""){
	                    $whereClause .=" AND ";
	                }
	                $parentClass = $classList[get_parent_class($className)];
	                $whereClause .= $class['prefix'].".".$class['fields'][RelationalMappingUtil::getReferenceKey($class)]['columnName']." = ".
	                    $parentClass['prefix'].".".$parentClass['fields'][RelationalMappingUtil::getPrimaryKey($parentClass)]['columnName'];
	            }
	            $i++;
	        }

            if($whereClause != ""){
                $whereClause = "WHERE ".$whereClause;
            }

            $limit = "";
            if(is_array($pagination)){

                if(array_key_exists("start",$pagination) && array_key_exists("pageSize",$pagination)){
                    $limit = $pagination["start"].",".$pagination["pageSize"];
                }elseif(array_key_exists("pageNumber",$pagination) && array_key_exists("pageSize",$pagination)){
                    $limit = (($pagination["pageNumber"]-1)*$pagination["pageSize"]).",".$pagination["pageSize"];
                }elseif(array_key_exists("start",$pagination) && array_key_exists("end",$pagination)){
                    $limit = $pagination["start"].",".($pagination["end"]-$pagination["start"]);
                }

                if($limit != ""){
                	$limit = "LIMIT ".$connection->encodeForSQLInjection($limit);
                }

            }
            
            $query = "SELECT $selectClause FROM $fromClause $whereClause $groupByClause $orderByClause $limit";

            $result = $connection->query($query);

            if(!$result){
                throw new BadQueryException("Select Failed : "+$connection->lastError());
            }

            self::$_lastFindQuery = array("selectClause" =>$selectClause,
                "fromClause"=>$fromClause,
                "whereClause"=>$whereClause,
                "groupByClause"=>$groupByClause,
                "orderByClause"=>$orderByClause,
                "limit"=>$limit);

            $row = $result->fetch_assoc();

            while($row != null){
            	$resultObj = self::__newInstanceWithoutConstructor($calledClassName);
                foreach($classList as $className=>$class){
                	$fields = $class['fields'];
                    foreach($fields as $fieldName=>$field){
                        $fieldSelect = $field['fieldSelect'];
                        $value = $row[$fieldSelect];

                        if($field['group']){
                            $value = explode(" $$ ",$value);
                            $value = array_map(function($_v){
                                if($_v == "#NULL$"){
                                    return null;
                                }
                                return $_v;
                            },$value);
                        }

                        if(strtoupper($field['type']) === "BOOLEAN" ){
                            if($field['group']){
                                foreach($value as &$valueItem){
                                    if($valueItem == "1"){
                                        $valueItem = true;
                                    }else{
                                        $valueItem = false;
                                    }
                                }
                            }else{
                                if($value == "1"){
                                    $value = true;
                                }else{
                                    $value = false;
                                }
                            }
                        }
                        
                        Reflection::setValue($className, $fieldName, $resultObj, $value);
                    }
                }
                
                $resultList[] = $resultObj;
                $row = $result->fetch_assoc();
            }
            
            foreach($classList as $className=>$class){
            	self::runTrigger($className, self::TRIGGER_EVENT_READ, self::TRIGGER_TYPE_POST, array($resultList));
            }

            TransactionManager::commitTransaction();
        }catch (DataNotFoundException $e){
            TransactionManager::abortTransaction();
            // don't throw for data not found exception
        }catch (\Exception $e){
            TransactionManager::abortTransaction();
            throw $e;
        }
        return $resultList;
    }
public static function find($filters,$sort = null,$pagination = null, $where = null){

        self::$_lastFindQuery = null;
        $calledClassName = get_called_class();

        $classList = RelationalMappingUtil::getClassConfiguration($calledClassName);
        $resultList = array();
        try{
        
        	TransactionManager::startTransaction();
        	$connection = TransactionManager::getConnection();
        	
	        $readAccessWhereClause = self::checkAccess($calledClassName, "User don't have access to Read");
	        
	        foreach ($classList as $className=>$class){
	        	self::runTrigger($className, self::TRIGGER_EVENT_READ, self::TRIGGER_TYPE_PRE, array(array("filters"=>$filters,"sort"=>$sort,"pagination"=>$pagination, "where"=>$where)));
	        }
	
	        if($readAccessWhereClause instanceof Expression){
	        	if($where instanceof Expression){
	        		$where = new Expression(self::OPERATOR_AND, array($where,$readAccessWhereClause));
	        	}else {
	        		$where = $readAccessWhereClause;
	        	}
	        }
	        $Clauses = self::generateClauses($connection,$classList, $filters, $sort, $where);
	        
	        $selectClause  = $Clauses["selectClause"];
	        $fromClause    = $Clauses["fromClause"];
	        $whereClause   = $Clauses["whereClause"];
	        $groupByClause = $Clauses["groupByClause"];
	        $orderByClause = $Clauses["orderByClause"];
	        
	        $i = 0;
	        
	        $classCount = count($classList);
	        foreach($classList as $className=>$class){
	            //skip the last class
	            if($i < $classCount-1){
	                if($whereClause != ""){
	                    $whereClause .=" AND ";
	                }
	                $parentClass = $classList[get_parent_class($className)];
	                $whereClause .= $class['prefix'].".".$class['fields'][RelationalMappingUtil::getReferenceKey($class)]['columnName']." = ".
	                    $parentClass['prefix'].".".$parentClass['fields'][RelationalMappingUtil::getPrimaryKey($parentClass)]['columnName'];
	            }
	            $i++;
	        }

            if($whereClause != ""){
                $whereClause = "WHERE ".$whereClause;
            }

            $limit = "";
            if(is_array($pagination)){

                if(array_key_exists("start",$pagination) && array_key_exists("pageSize",$pagination)){
                    $limit = $pagination["start"].",".$pagination["pageSize"];
                }elseif(array_key_exists("pageNumber",$pagination) && array_key_exists("pageSize",$pagination)){
                    $limit = (($pagination["pageNumber"]-1)*$pagination["pageSize"]).",".$pagination["pageSize"];
                }elseif(array_key_exists("start",$pagination) && array_key_exists("end",$pagination)){
                    $limit = $pagination["start"].",".($pagination["end"]-$pagination["start"]);
                }

                if($limit != ""){
                	$limit = "LIMIT ".$connection->encodeForSQLInjection($limit);
                }

            }
            
            $query = "SELECT $selectClause FROM $fromClause $whereClause $groupByClause $orderByClause $limit";

            $result = $connection->query($query);

            if(!$result){
                throw new BadQueryException("Select Failed : "+$connection->lastError());
            }

            self::$_lastFindQuery = array("selectClause" =>$selectClause,
                "fromClause"=>$fromClause,
                "whereClause"=>$whereClause,
                "groupByClause"=>$groupByClause,
                "orderByClause"=>$orderByClause,
                "limit"=>$limit);

            $row = $result->fetch_assoc();

            while($row != null){
            	$resultObj = self::__newInstanceWithoutConstructor($calledClassName);
                foreach($classList as $className=>$class){
                	$fields = $class['fields'];
                    foreach($fields as $fieldName=>$field){
                        $fieldSelect = $field['fieldSelect'];
                        $value = $row[$fieldSelect];

                        if($field['group']){
                            $value = explode(" $$ ",$value);
                            $value = array_map(function($_v){
                                if($_v == "#NULL$"){
                                    return null;
                                }
                                return $_v;
                            },$value);
                        }

                        if(strtoupper($field['type']) === "BOOLEAN" ){
                            if($field['group']){
                                foreach($value as &$valueItem){
                                    if($valueItem == "1"){
                                        $valueItem = true;
                                    }else{
                                        $valueItem = false;
                                    }
                                }
                            }else{
                                if($value == "1"){
                                    $value = true;
                                }else{
                                    $value = false;
                                }
                            }
                        }
                        
                        Reflection::setValue($className, $fieldName, $resultObj, $value);
                    }
                }
                
                $resultList[] = $resultObj;
                $row = $result->fetch_assoc();
            }
            
            foreach($classList as $className=>$class){
            	self::runTrigger($className, self::TRIGGER_EVENT_READ, self::TRIGGER_TYPE_POST, array($resultList));
            }

            TransactionManager::commitTransaction();
        }catch (DataNotFoundException $e){
            TransactionManager::abortTransaction();
            // don't throw for data not found exception
        }catch (\Exception $e){
            TransactionManager::abortTransaction();
            throw $e;
        }
        return $resultList;
    }
This method finds the data from database and constructs appropriate php daos

@param $filters array of fields to match for
@param null $sort array for sorting
@param null $pagination array(pageNumber,pageSize)
@param null $where Expression - complex SQL where expression
@return array
@throws \Exception

@todo Add select option to select required values, in one loop, or a callback method to work with found objects