HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Repository Pattern without an ORM

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
patternormwithoutrepository

Problem

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

  • 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.



  • 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?



  • 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?



  • Am I doing anything just completely wrong in general?



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

Product.php

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

```
db = $db;
}

/**
* @return array
*/
public function findAll()
{
$stmt = $this->db->query(
'SELECT
id

Solution

A quick answer regarding the setId method.

You should use the object's constructor instead like this:

class Product
{
    /** @var int $id */
    protected $id;

    /** @var string $name */
    protected $name;

    public function __construct($id = null)
    {
        $this->id = $id;
    }

    public function isNew()
    {
        return is_null($this->id)
    }
}


So if the entity is created for the fist time you have to call $product = new Product() and if you fetch it from the database: $product = new Product($result['id']);.

With this trick you can make a single save operation for your repository:

class ProductRepository implements ProductRepositoryInterface
{

    public function save(Product $product)
    {
        if($product->isNew())
            $this->create($product);
        else
            $this->update($product);
    }
}


For the id question, two options:

  • When you insert a new object, you'll make a new one with the id from the database



  • You'll handle the generation of the Id by yourself using an UUID for example (this lib is perfect for that: https://github.com/ramsey/uuid)



In this second case (you handle the generation of the ID), your class will look like this:

class Product
{
    /** @var int $id */
    protected $id;

    /** @var string $name */
    protected $name;

    protected $isNew = false;

    public function __construct($id = null)
    {
        if($id === null) {
            $this->id = Uuid::uuid4();
            $this->isNew = true;
        } else {
            $this->id = $id;
        }

    }
}


Hope it can help !

Code Snippets

class Product
{
    /** @var int $id */
    protected $id;

    /** @var string $name */
    protected $name;

    public function __construct($id = null)
    {
        $this->id = $id;
    }

    public function isNew()
    {
        return is_null($this->id)
    }
}
class ProductRepository implements ProductRepositoryInterface
{

    public function save(Product $product)
    {
        if($product->isNew())
            $this->create($product);
        else
            $this->update($product);
    }
}
class Product
{
    /** @var int $id */
    protected $id;

    /** @var string $name */
    protected $name;

    protected $isNew = false;

    public function __construct($id = null)
    {
        if($id === null) {
            $this->id = Uuid::uuid4();
            $this->isNew = true;
        } else {
            $this->id = $id;
        }

    }
}

Context

StackExchange Code Review Q#126050, answer score: 2

Revisions (0)

No revisions yet.