├── .gitignore ├── listing01.php ├── listing02.php ├── listing03.php ├── listing04.php ├── listing05.php ├── listing06.php ├── listing07.php ├── listing08.php ├── listing09.php ├── listing10.php ├── listing11.php ├── listing12.php ├── listing13.php ├── listing14.php ├── listing15.php └── listing16.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /listing01.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 9 | $rating = $this->request->getParam('rating'); 10 | 11 | // Building database connection 12 | $db = new Zend_Db_Adapter_Pdo_Mysql(array( 13 | 'host' => 'localhost', 14 | 'username' => 'idy', 15 | 'password' => '', 16 | 'dbname' => 'idy' 17 | )); 18 | 19 | // Finding the idea in the database 20 | $sql = 'SELECT * FROM ideas WHERE idea_id = ?'; 21 | $row = $db->fetchRow($sql, $ideaId); 22 | if (!$row) { 23 | throw new Exception('Idea does not exist'); 24 | } 25 | 26 | // Building the idea from the database 27 | $idea = new Idea(); 28 | $idea->setId($row['id']); 29 | $idea->setTitle($row['title']); 30 | $idea->setDescription($row['description']); 31 | $idea->setRating($row['rating']); 32 | $idea->setVotes($row['votes']); 33 | $idea->setAuthor($row['email']); 34 | 35 | // Add user rating 36 | $idea->addRating($rating); 37 | 38 | // Update the idea and save it to the database 39 | $data = array( 40 | 'votes' => $idea->getVotes(), 41 | 'rating' => $idea->getRating() 42 | ); 43 | $where['idea_id = ?'] = $ideaId; 44 | $db->update('ideas', $data, $where); 45 | 46 | // Redirect to view idea page 47 | $this->redirect('/idea/'.$ideaId); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /listing02.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $ideaRepository = new IdeaRepository(); 11 | $idea = $ideaRepository->find($ideaId); 12 | if (!$idea) { 13 | throw new Exception('Idea does not exist'); 14 | } 15 | 16 | $idea->addRating($rating); 17 | $ideaRepository->update($idea); 18 | 19 | $this->redirect('/idea/'.$ideaId); 20 | } 21 | } 22 | 23 | class IdeaRepository 24 | { 25 | /** 26 | * @var Zend_Db_Adapter_Pdo_Mysql 27 | */ 28 | private $client; 29 | 30 | public function __construct() 31 | { 32 | $this->client = new Zend_Db_Adapter_Pdo_Mysql(array( 33 | 'host' => 'localhost', 34 | 'username' => 'idy', 35 | 'password' => '', 36 | 'dbname' => 'idy' 37 | )); 38 | } 39 | 40 | /** 41 | * Finds an idea by id 42 | * 43 | * @param int $id 44 | * @return null|Idea 45 | */ 46 | public function find($id) 47 | { 48 | $sql = 'SELECT * FROM ideas WHERE idea_id = ?'; 49 | $row = $this->client->fetchRow($sql, $id); 50 | if (!$row) { 51 | return null; 52 | } 53 | 54 | $idea = new Idea(); 55 | $idea->setId($row['id']); 56 | $idea->setTitle($row['title']); 57 | $idea->setDescription($row['description']); 58 | $idea->setRating($row['rating']); 59 | $idea->setVotes($row['votes']); 60 | $idea->setAuthor($row['email']); 61 | 62 | return $idea; 63 | } 64 | 65 | public function update(Idea $idea) 66 | { 67 | $data = array( 68 | 'title' => $idea->getTitle(), 69 | 'description' => $idea->getDescription(), 70 | 'rating' => $idea->getRating(), 71 | 'votes' => $idea->getVotes(), 72 | 'email' => $idea->getAuthor(), 73 | ); 74 | 75 | $where = array('idea_id = ?' => $idea->getId()); 76 | $this->client->update('ideas', $data, $where); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /listing03.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $ideaRepository = new MySQLIdeaRepository(); 11 | $idea = $ideaRepository->find($ideaId); 12 | if (!$idea) { 13 | throw new Exception('Idea does not exist'); 14 | } 15 | 16 | $idea->addRating($rating); 17 | $ideaRepository->update($idea); 18 | 19 | $this->redirect('/idea/'.$ideaId); 20 | } 21 | } 22 | 23 | interface IdeaRepository 24 | { 25 | /** 26 | * Finds an idea by id 27 | * 28 | * @param int $id 29 | * @return null|Idea 30 | */ 31 | public function find($id); 32 | 33 | /** 34 | * Updates an idea 35 | * 36 | * @param Idea $idea 37 | */ 38 | public function update(Idea $idea); 39 | } 40 | 41 | class MySQLIdeaRepository implements IdeaRepository 42 | { 43 | // ... 44 | } 45 | -------------------------------------------------------------------------------- /listing04.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $ideaRepository = new RedisIdeaRepository(); 11 | $idea = $ideaRepository->find($ideaId); 12 | if (!$idea) { 13 | throw new Exception('Idea does not exist'); 14 | } 15 | 16 | $idea->addRating($rating); 17 | $ideaRepository->update($idea); 18 | 19 | $this->redirect('/idea/'.$ideaId); 20 | } 21 | } 22 | 23 | interface IdeaRepository 24 | { 25 | // ... 26 | } 27 | 28 | class RedisIdeaRepository implements IdeaRepository 29 | { 30 | /** 31 | * @var \Predis\Client 32 | */ 33 | private $client; 34 | 35 | public function __construct() 36 | { 37 | $this->client = new \Predis\Client(); 38 | } 39 | 40 | public function find($id) 41 | { 42 | $idea = $this->client->get($this->getKey($id)); 43 | if (!$idea) { 44 | return null; 45 | } 46 | 47 | return unserialize($idea); 48 | } 49 | 50 | public function update(Idea $idea) 51 | { 52 | $this->client->set( 53 | $this->getKey($idea->getId()), 54 | serialize($idea) 55 | ); 56 | } 57 | 58 | private function getKey($id) 59 | { 60 | return 'idea:'.$id; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /listing05.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $ideaRepository = new RedisIdeaRepository(); 11 | $useCase = new RateIdeaUseCase($ideaRepository); 12 | $response = $useCase->execute($ideaId, $rating); 13 | 14 | $this->redirect('/idea/'.$ideaId); 15 | } 16 | } 17 | 18 | interface IdeaRepository 19 | { 20 | // ... 21 | } 22 | 23 | class RateIdeaUseCase 24 | { 25 | /** 26 | * @var IdeaRepository 27 | */ 28 | private $ideaRepository; 29 | 30 | public function __construct(IdeaRepository $ideaRepository) 31 | { 32 | $this->ideaRepository = $ideaRepository; 33 | } 34 | 35 | /** 36 | * Executes this use case 37 | * 38 | * @param int $ideaId 39 | * @param int $rating 40 | * @throws RepositoryNotAvailableException 41 | * @throws IdeaDoesNotExistException 42 | */ 43 | public function execute($ideaId, $rating) 44 | { 45 | try { 46 | $idea = $this->ideaRepository->find($ideaId); 47 | } catch(Exception $e) { 48 | throw new RepositoryNotAvailableException(); 49 | } 50 | 51 | if (!$idea) { 52 | throw new IdeaDoesNotExistException(); 53 | } 54 | 55 | try { 56 | $idea->addRating($rating); 57 | $this->ideaRepository->update($idea); 58 | } catch(Exception $e) { 59 | throw new RepositoryNotAvailableException(); 60 | } 61 | 62 | return $idea; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /listing06.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $ideaRepository = new RedisIdeaRepository(); 11 | $useCase = new RateIdeaUseCase($ideaRepository); 12 | $response = $useCase->execute( 13 | new RateIdeaRequest($ideaId, $rating) 14 | ); 15 | 16 | $this->redirect('/idea/'.$response->idea->getId()); 17 | } 18 | } 19 | 20 | class RateIdeaRequest 21 | { 22 | /** 23 | * @var int 24 | */ 25 | public $ideaId; 26 | 27 | /** 28 | * @var int 29 | */ 30 | public $rating; 31 | 32 | public function __construct($ideaId, $rating) 33 | { 34 | $this->ideaId = $ideaId; 35 | $this->rating = $rating; 36 | } 37 | } 38 | 39 | class RateIdeaResponse 40 | { 41 | /** 42 | * @var Idea 43 | */ 44 | public $idea; 45 | 46 | public function __construct(Idea $idea) 47 | { 48 | $this->idea = $idea; 49 | } 50 | } 51 | 52 | class RateIdeaUseCase 53 | { 54 | // ... 55 | 56 | public function execute($request) 57 | { 58 | $ideaId = $request->ideaId; 59 | $rating = $request->rating; 60 | 61 | // ... 62 | 63 | return new RateIdeaResponse($idea); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /listing07.php: -------------------------------------------------------------------------------- 1 | get( 10 | '/api/rate/idea/{ideaId}/rating/{rating}', 11 | function($ideaId, $rating) use ($app) { 12 | $ideaRepository = new RedisIdeaRepository(); 13 | $useCase = new RateIdeaUseCase($ideaRepository); 14 | $response = $useCase->execute( 15 | new RateIdeaRequest($ideaId, $rating) 16 | ); 17 | 18 | return $app->json($response->idea); 19 | } 20 | ); 21 | 22 | $app->run(); 23 | -------------------------------------------------------------------------------- /listing08.php: -------------------------------------------------------------------------------- 1 | setName('idea:rate') 16 | ->setDescription('Rate an idea') 17 | ->addArgument('id', InputArgument::REQUIRED) 18 | ->addArgument('rating', InputArgument::REQUIRED) 19 | ; 20 | } 21 | 22 | protected function execute( 23 | InputInterface $input, 24 | OutputInterface $output 25 | ) 26 | { 27 | $ideaId = $input->getArgument('id'); 28 | $rating = $input->getArgument('rating'); 29 | 30 | $ideaRepository = new RedisIdeaRepository(); 31 | $useCase = new RateIdeaUseCase($ideaRepository); 32 | $response = $useCase->execute( 33 | new RateIdeaRequest($ideaId, $rating) 34 | ); 35 | 36 | $output->writeln('Done!'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /listing09.php: -------------------------------------------------------------------------------- 1 | setExpectedException('NotAvailableRepositoryException'); 11 | $ideaRepository = new NotAvailableRepository(); 12 | $useCase = new RateIdeaUseCase($ideaRepository); 13 | $useCase->execute( 14 | new RateIdeaRequest(1, 5) 15 | ); 16 | } 17 | } 18 | 19 | class NotAvailableRepository implements IdeaRepository 20 | { 21 | public function find($id) 22 | { 23 | throw NotAvailableException(); 24 | } 25 | 26 | public function update(Idea $idea) 27 | { 28 | throw NotAvailableException(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /listing10.php: -------------------------------------------------------------------------------- 1 | setExpectedException('IdeaDoesNotExistException'); 13 | $ideaRepository = new EmptyIdeaRepository(); 14 | $useCase = new RateIdeaUseCase($ideaRepository); 15 | $useCase->execute( 16 | new RateIdeaRequest(1, 5) 17 | ); 18 | } 19 | } 20 | 21 | class EmptyIdeaRepository implements IdeaRepository 22 | { 23 | public function find($id) 24 | { 25 | return null; 26 | } 27 | 28 | public function update(Idea $idea) 29 | { 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /listing11.php: -------------------------------------------------------------------------------- 1 | setExpectedException('NotAvailableRepositoryException'); 13 | $ideaRepository = new WriteNotAvailableRepository(); 14 | $useCase = new RateIdeaUseCase($ideaRepository); 15 | $response = $useCase->execute( 16 | new RateIdeaRequest(1, 5) 17 | ); 18 | } 19 | } 20 | 21 | class WriteNotAvailableRepository implements IdeaRepository 22 | { 23 | public function find($id) 24 | { 25 | $idea = new Idea(); 26 | $idea->setId(1); 27 | $idea->setTitle('Subscribe to php[architect]'); 28 | $idea->setDescription('Just buy it!'); 29 | $idea->setRating(5); 30 | $idea->setVotes(10); 31 | $idea->setAuthor('hi@carlos.io'); 32 | 33 | return $idea; 34 | } 35 | 36 | public function update(Idea $idea) 37 | { 38 | throw NotAvailableException(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /listing12.php: -------------------------------------------------------------------------------- 1 | execute( 15 | new RateIdeaRequest(1, 5) 16 | ); 17 | 18 | $this->assertSame(5, $response->idea->getRating()); 19 | $this->assertTrue($ideaRepository->updateCalled); 20 | } 21 | } 22 | 23 | class OneIdeaRepository implements IdeaRepository 24 | { 25 | public $updateCalled = false; 26 | 27 | public function find($id) 28 | { 29 | $idea = new Idea(); 30 | $idea->setId(1); 31 | $idea->setTitle('Subscribe to php[architect]'); 32 | $idea->setDescription('Just buy it!'); 33 | $idea->setRating(5); 34 | $idea->setVotes(10); 35 | $idea->setAuthor('hi@carlos.io'); 36 | 37 | return $idea; 38 | } 39 | 40 | public function update(Idea $idea) 41 | { 42 | $this->updateCalled = true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /listing13.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $useCase = new RateIdeaUseCase( 11 | new RedisIdeaRepository( 12 | new \Predis\Client() 13 | ) 14 | ); 15 | 16 | $response = $useCase->execute( 17 | new RateIdeaRequest($ideaId, $rating) 18 | ); 19 | 20 | $this->redirect('/idea/'.$response->idea->getId()); 21 | } 22 | } 23 | 24 | class RedisIdeaRepository implements IdeaRepository 25 | { 26 | private $client; 27 | 28 | public function __construct($client) 29 | { 30 | $this->client = $client; 31 | } 32 | 33 | // ... 34 | public function find($id) 35 | { 36 | $idea = $this->client->get($this->getKey($id)); 37 | if (!$idea) { 38 | return null; 39 | } 40 | 41 | return $idea; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /listing14.php: -------------------------------------------------------------------------------- 1 | request->getParam('id'); 8 | $rating = $this->request->getParam('rating'); 9 | 10 | $useCase = $this->get('rate_idea_use_case'); 11 | $response = $useCase->execute( 12 | new RateIdeaRequest($ideaId, $rating) 13 | ); 14 | 15 | $this->redirect('/idea/'.$response->idea->getId()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /listing15.php: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /listing16.php: -------------------------------------------------------------------------------- 1 | ideaRepository = $ideaRepository; 21 | $this->authorNotifier = $authorNotifier; 22 | } 23 | 24 | public function execute(RateIdeaRequest $request) 25 | { 26 | $ideaId = $request->ideaId; 27 | $rating = $request->rating; 28 | 29 | try { 30 | $idea = $this->ideaRepository->find($ideaId); 31 | } catch(Exception $e) { 32 | throw new RepositoryNotAvailableException(); 33 | } 34 | 35 | if (!$idea) { 36 | throw new IdeaDoesNotExistException(); 37 | } 38 | 39 | try { 40 | $idea->addRating($rating); 41 | $this->ideaRepository->update($idea); 42 | } catch(Exception $e) { 43 | throw new RepositoryNotAvailableException(); 44 | } 45 | 46 | try { 47 | $this->authorNotifier->notify( 48 | $idea->getAuthor() 49 | ); 50 | } catch(Exception $e) { 51 | throw new NotificationNotSentException(); 52 | } 53 | 54 | return $idea; 55 | } 56 | } 57 | --------------------------------------------------------------------------------