From de45944c8b0a62092a91bb39724c4fce5488a3a9 Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Fri, 19 Sep 2014 17:07:02 +0800 Subject: [PATCH] More dataaccess stuff. --- Controllers/IndexController.php | 22 ++++-- DataAccess/DataMapper/DataMapper.php | 27 ++----- DataAccess/DataMapper/IDataMapper.php | 9 +-- DataAccess/IRepository.php | 2 - DataAccess/Queries/IQueryConstraints.php | 17 +++++ DataAccess/Queries/QueryConstraints.php | 85 ++++++++++++++++++++++ .../Queries/StepMania/ISimfileQueryConstraints.php | 13 ++++ .../Queries/StepMania/SimfileQueryConstraints.php | 30 ++++++++ DataAccess/StepMania/ISimfileRepository.php | 3 +- DataAccess/StepMania/SimfileRepository.php | 50 +++++++++++-- public_html/index.php | 2 +- 11 files changed, 217 insertions(+), 43 deletions(-) create mode 100644 DataAccess/Queries/IQueryConstraints.php create mode 100644 DataAccess/Queries/QueryConstraints.php create mode 100644 DataAccess/Queries/StepMania/ISimfileQueryConstraints.php create mode 100644 DataAccess/Queries/StepMania/SimfileQueryConstraints.php diff --git a/Controllers/IndexController.php b/Controllers/IndexController.php index 5f86846..8b4ba2a 100644 --- a/Controllers/IndexController.php +++ b/Controllers/IndexController.php @@ -5,12 +5,10 @@ namespace Controllers; use DataAccess\StepMania\ISimfileRepository; use Services\Http\IHttpResponse; use Services\Http\IHttpRequest; -use Controllers\AbstractBaseController; +use DataAccess\Queries\StepMania\SimfileQueryConstraints; class IndexController implements IDivineController { - - private $_content; private $_simfileRepository; private $_response; private $_request; @@ -26,9 +24,19 @@ class IndexController implements IDivineController $this->_simfileRepository = $repository; } - public function indexAction() { - $this->_response->setHeader('Content-Type', 'application/json') - ->setBody(json_encode(array('message' => 'nothing to see here'))) - ->sendResponse(); + public function indexAction() { + $queryConstraints = new SimfileQueryConstraints(); + $queryConstraints->stepsHaveRating(15); + + $simfiles = $this->_simfileRepository->findByTitle('a', $queryConstraints); + + foreach($simfiles as $simfile) + { + echo $simfile->getTitle(); + } + +// $this->_response->setHeader('Content-Type', 'application/json') +// ->setBody(json_encode(array('message' => 'nothing to see here'))) +// ->sendResponse(); } } diff --git a/DataAccess/DataMapper/DataMapper.php b/DataAccess/DataMapper/DataMapper.php index 1e49010..9d1611b 100644 --- a/DataAccess/DataMapper/DataMapper.php +++ b/DataAccess/DataMapper/DataMapper.php @@ -22,15 +22,14 @@ class DataMapper implements IDataMapper $options = array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); - $this->_db = new PDO($dsn, $username, $password, $options); + $this->_db = new PDO($dsn, $username, null, $options); $this->_maps = include $maps; } - public function find($entityName, $queryString) + public function map($entityName, $queryString = 'SELECT * FROM %s') { - $statement = $this->_db->prepare(sprintf('SELECT * from %s WHERE %s', - $this->_maps[$entityName]['table'], - $queryString + $statement = $this->_db->prepare(sprintf($queryString, + $this->_maps[$entityName]['table'] )); $statement->execute(); @@ -55,23 +54,9 @@ class DataMapper implements IDataMapper $entities[$row['id']] = $class; } - return count($entities) > 1 ? $entities : reset($entities); - - return $this->findRange($id, $entityName, 1); + return $entities; } - - public function findById($id, $entity) - { - $queryString = sprintf('id=%u', $id); - return $this->find($entity, $queryString); - } - - public function findRange($id, $entity, $limit) - { - $queryString = sprintf('id>=%u LIMIT %u', $id, $limit); - return $this->find($entity, $queryString); - } - + public function save(IDivineEntity $entity) { $queries = AbstractPopulationHelper::generateUpdateSaveQuery($this->_maps, $entity, $entity->getId(), $this->_db); diff --git a/DataAccess/DataMapper/IDataMapper.php b/DataAccess/DataMapper/IDataMapper.php index ee90de0..001db54 100644 --- a/DataAccess/DataMapper/IDataMapper.php +++ b/DataAccess/DataMapper/IDataMapper.php @@ -2,18 +2,15 @@ namespace DataAccess\DataMapper; +use DataAccess\Queries\IQueryConstraints; use Domain\Entities\IDivineEntity; interface IDataMapper { //TODO: Table is the wrong name. We actually give the implementation the entity name and it finds the table from the maps. - //find in table based on criteria in queryString - public function find($entityName, $queryString); - //find id in table and return it as an entity - public function findById($id, $entityName); - //find rows with id >= id and stop at limit - public function findRange($id, $entityName, $limit); + //find in table based on constraints and return it as entity + public function map($entityName, $queryString); //insert/update entity in table public function save(IDivineEntity $entity); //remove entity from table diff --git a/DataAccess/IRepository.php b/DataAccess/IRepository.php index 34765cb..af3a435 100644 --- a/DataAccess/IRepository.php +++ b/DataAccess/IRepository.php @@ -8,6 +8,4 @@ interface IRepository { public function findById($id); public function findRange($id, $limit); - public function save(IDivineEntity $entity); - public function remove(IDivineEntity $entity); } \ No newline at end of file diff --git a/DataAccess/Queries/IQueryConstraints.php b/DataAccess/Queries/IQueryConstraints.php new file mode 100644 index 0000000..38128d6 --- /dev/null +++ b/DataAccess/Queries/IQueryConstraints.php @@ -0,0 +1,17 @@ +_queryString = $queryString; + + $this->applyJoinClause() + ->applyWhereClauses() + ->applyLimitClause(); + + return $this->_queryString; + } + + public function where($columnName, $operator, $value) + { + $this->_whereClauses[$columnName] = array('operator' => $operator, 'value' => $value); + return $this; + } + + public function limit($start, $end = null) + { + if($end) + { + $this->_limitClause = sprintf(' LIMIT %u,%u', $start, $end); + return $this; + } + + $this->_limitClause = sprintf(' LIMIT %u', $start); + + return $this; + } + + public function join($type, $tableA, $columnA, $tableB, $columnB) + { + $this->_joinClause = sprintf(' %s JOIN %s ON %s.%s = %s.%s', $type, $tableB, $tableA, $columnA, $tableB, $columnB); + return $this; + } + + private function applyJoinClause() + { + $this->_queryString .= $this->_joinClause; + return $this; + } + + private function applyWhereClauses() + { + $this->_queryString .= ' WHERE '; + + foreach($this->_whereClauses as $columnName => $columnValue) + { + switch(gettype($columnValue['value'])) + { + case 'integer': + $this->_queryString .= sprintf("%s%s%u", $columnName, $columnValue['operator'], $columnValue['value']) . ' AND '; + break; + case 'string': + $this->_queryString .= sprintf("%s %s '%s'", $columnName, $columnValue['operator'], $columnValue['value']) . ' AND '; + break; + } + + } + + $this->_queryString = rtrim($this->_queryString, ' AND '); + return $this; + } + + private function applyLimitClause() + { + $this->_queryString .= $this->_limitClause; + return $this; + } + +} \ No newline at end of file diff --git a/DataAccess/Queries/StepMania/ISimfileQueryConstraints.php b/DataAccess/Queries/StepMania/ISimfileQueryConstraints.php new file mode 100644 index 0000000..3f59a87 --- /dev/null +++ b/DataAccess/Queries/StepMania/ISimfileQueryConstraints.php @@ -0,0 +1,13 @@ +where('fg_changes', '=', (int)$bool); + } + public function hasBgChanges($bool) + { + return $this->where('bg_changes', '=', (int)$bool); + } + + public function stepsHaveRating($rating) + { + return $this->join('INNER', 'simfiles', 'id', 'steps', 'simfile_id') + ->where('steps.rating', '=', $rating); + } + public function hasDifficulty($difficulty){} + + public function bpm($bpm) + { + return; + } +} diff --git a/DataAccess/StepMania/ISimfileRepository.php b/DataAccess/StepMania/ISimfileRepository.php index eea84c5..940bcc0 100644 --- a/DataAccess/StepMania/ISimfileRepository.php +++ b/DataAccess/StepMania/ISimfileRepository.php @@ -3,11 +3,12 @@ namespace DataAccess\StepMania; use DataAccess\IRepository; +use DataAccess\Queries\StepMania\ISimfileQueryConstraints; use Domain\Entities\StepMania\ISimfile; interface ISimfileRepository extends IRepository { - public function findByTitle($title); + public function findByTitle($title, ISimfileQueryConstraints $constraints); public function findByArtist($artist); public function findByBpm($high, $low); public function findByStepArtist($artistName); diff --git a/DataAccess/StepMania/SimfileRepository.php b/DataAccess/StepMania/SimfileRepository.php index 7e1a8fa..02d7c29 100644 --- a/DataAccess/StepMania/SimfileRepository.php +++ b/DataAccess/StepMania/SimfileRepository.php @@ -4,32 +4,72 @@ namespace DataAccess\StepMania; use DataAccess\StepMania\ISimfileRepository; use DataAccess\DataMapper\IDataMapper; +use DataAccess\Queries\StepMania\ISimfileQueryConstraints; use Domain\Entities\StepMania\ISimfile; //TODO: Implement some sort of caching. Probably OK for now not to worry. class SimfileRepository implements ISimfileRepository { - private $dataMapper; + private $_dataMapper; public function __construct(IDataMapper $dataMapper) { - $this->dataMapper = $dataMapper; + $this->_dataMapper = $dataMapper; } public function findById($id) { - return $this->dataMapper->findById($id, 'Simfile'); + return $this->_dataMapper->map( + 'Simfile', + 'SELECT * FROM %s WHERE id=' . $id + ); } public function findRange($id, $limit) { - return $this->dataMapper->findRange($id, 'Simfile', $limit); + return $this->_dataMapper->findRange( + 'Simfile', + 'SELECT * FROM %s WHERE id>=' . $id . ' LIMIT ' . $limit + ); } public function save(ISimfile $entity) { - $this->dataMapper->save($entity); + $this->_dataMapper->save($entity); } //TODO: Implement public function remove(ISimfile $entity) { ; } + + public function findByTitle($title, ISimfileQueryConstraints $constraints = NULL) + { + //TODO: Should I inject a factory, and then make $constraints if it isn't given? + if($constraints) + { + $queryString = $constraints->where('title', 'LIKE', "%%$title%%") //TODO: Should I make a like method that handles adding the %% ? + ->applyTo('SELECT * from %s'); + } else { + //It would avoid this, or rather I could put this in the constraints class + $queryString = "SELECT * FROM %s WHERE title LIKE '%$title%'"; + } + + //is it better to pass in constraints object? + //could have a default "select * from %s" in the constraints object which could be overwritten via a method. + //-no more need for applyTo, just go $constratints->getQuery + //maybe it should no longer be constraints but instead queryBuilder + + /** + * have this class contain a queryBuilderFactory and then have constraintsClass + * go in through methods which act on the query, adding in constraints. + */ + return $this->_dataMapper->map('Simfile', $queryString); + } + + public function findByArtist($artist){} + public function findByBpm($high, $low){} + public function findByStepArtist($artistName){} + public function findByLightMeter($feet){} + public function findByBeginnerMeter($feet){} + public function findByMediumMeter($feet){} + public function findByHardMeter($feet){} + public function findByExpertMeter($feet){} } diff --git a/public_html/index.php b/public_html/index.php index 1f6b8a1..0118b64 100644 --- a/public_html/index.php +++ b/public_html/index.php @@ -15,7 +15,7 @@ $controllerName= $router->getControllerName(); $controllerAction = $router->getActionName(); $controllerActionArgs = $router->getActionArgs(); -$controller = $container->get('Controllers\\' . $controllerName . 'Controller' ); +$controller = $container->get('Controllers\\' . ucfirst($controllerName) . 'Controller' ); // Last thing to do, call the action on the specified controller. call_user_func(array($controller, $controllerAction . 'Action'), $controllerActionArgs); -- 2.11.0