Skip to main content
Code Review

Return to Question

Tweeted twitter.com/StackCodeReview/status/722263730227146757
edited tags; edited title
Link
Mathieu Guindon
  • 75.5k
  • 18
  • 194
  • 467

RepositoryPattern Repository Pattern without an ORM

Post Migrated Here from stackoverflow.com (revisions)
Source Link
jpt
  • 101
  • 4

RepositoryPattern without an ORM

I'm trying to learn the Repository pattern, and I have some questions regarding my current understanding of it.

  1. All the examples I've been able to find of database repositories use ORMs, but for a number of reasons, I can't use an ORM in the project I am learning this for. So, when not using an ORM, where should the SQL queries go? My best guess was in the repository class itself, so that's what I did in the example below.
  2. How's my naming convention for the repository's methods? I stuck with the create/update/delete verbiage of SQL as a sort of placeholder, but is there a better way?
  3. Because I'm not using an ORM, I need a setId() method in my repository. I recognize the danger inherent in allowing id's to be changed after object creation. Right now I prevent that by throwing an exception in setId() if id is not null. Is that alright or is there a better way?
  4. Am I doing anything just completely wrong in general?

Here is my current implementation, as far as I understand the concepts.

Product.php

<?php
namespace Vendor\Package\Module\Entities;
class Product
{
 /** @var int $id */
 protected $id;
 /** @var string $name */
 protected $name;
 public function getId()
 {
 return $this->id;
 }
 public function setId($id)
 {
 if ($this->id !== null) {
 throw new Exception('id cannot be reset.');
 }
 $this->id = $id;
 return $this;
 }
 public function getName()
 {
 return $this->name;
 }
 public function setName($name)
 {
 $this->name = $name;
 return $this;
 }
}

ProductRepositoryInterface.php

<?php
namespace Vendor\Package\Module\Repositories;
use PDO;
use Vendor\Package\Module\Entities\Product;
interface ProductRepositoryInterface
{
 public function findAll();
 public function findById($id);
 public function create(Product $product);
 public function update(Product $product);
 public function delete(Product $product);
}

ProductRepository.php

<?php
namespace Vendor\Package\Module\Repositories;
use PDO;
use Vendor\Package\Module\Entities\Product;
class ProductRepository implements ProductRepositoryInterface
{
 /** @var PDO $db */
 protected $db;
 public function __construct(PDO $db)
 {
 $this->db = $db;
 }
 /**
 * @return array
 */
 public function findAll()
 {
 $stmt = $this->db->query(
 'SELECT
 id,
 name
 FROM products
 WHERE active = 1'
 );
 $products = [];
 while ($stmt->fetch(PDO::FETCH_ASSOC)) {
 $product = new Product();
 $product
 ->setId($result['id'])
 ->setName($result['name'])
 ;
 }
 return $products;
 }
 /**
 * @param int $id
 *
 * @return Product
 */
 public function findById($id)
 {
 $stmt = $this->db->prepare(
 'SELECT
 id,
 name
 FROM products
 WHERE id = :id
 AND active = 1
 LIMIT 1'
 );
 $stmt->bindValue(':id', $id, PDO::PARAM_INT);
 $stmt->execute();
 $result = $stmt->fetch(PDO::FETCH_ASSOC);
 $product = new Product();
 $product
 ->setId($result['id'])
 ->setName($result['name'])
 ;
 }
 /**
 * @param Product $product
 *
 * @return int
 */
 public function create(Product $product)
 {
 $stmt = $this->db->prepare(
 'INSERT INTO products (
 name
 ) VALUES (
 :name
 )'
 );
 $stmt->bindValue(':name', $product->getName(), PDO::PARAM_STR);
 $stmt->execute();
 
 $id = $this->db->lastInsertId();
 $product->setId($id);
 return $id;
 }
 /**
 * @param Product $product
 *
 * @return bool
 */
 public function update(Product $product)
 {
 $stmt = $this->db->prepare(
 'UPDATE products SET
 name = :name
 WHERE id = :id
 AND active = 1'
 );
 $stmt->bindValue(':name', $product->getName(), PDO::PARAM_STR);
 $stmt->bindValue(':id', $product->getId(), PDO::PARAM_INT);
 return $stmt->execute();
 }
 /**
 * @param Product $product
 *
 * @return bool
 */
 public function delete(Product $product)
 {
 $stmt = $this->db->prepare(
 'UPDATE products SET
 active = 0
 WHERE id = :id
 AND active = 1'
 );
 $stmt->bindValue(':id', $product->getId(), PDO::PARAM_INT);
 return $stmt->execute();
 }
}

demo.php

<?php
use Vendor\Package\Module\Entities\Product;
use Vendor\Package\Module\Repositories\ProductRepository;
$repository = new ProductRepository($db);
// Create
if (
 isset($_POST['create'])
 && isset($_POST['name'])
) {
 $product = new Product();
 $product
 ->setName($_POST['name'])
 ;
 $repository->create($product);
}
// Update
if (
 isset($_POST['update'])
 && isset($_POST['id'])
 && isset($_POST['name'])
) {
 $product = new Product();
 $product
 ->setId($_POST['id'])
 ->setName($_POST['name'])
 ;
 $repository->update($product);
}
// Delete
if (
 isset($_POST['delete'])
 && isset($_POST['id'])
) {
 $product = new Product();
 $product
 ->setId($_POST['id'])
 ;
 $repository->delete($product);
}
lang-php

AltStyle によって変換されたページ (->オリジナル) /