Skip to content

Instantly share code, notes, and snippets.

@chrisguitarguy
Last active September 10, 2015 14:31
Show Gist options
  • Select an option

  • Save chrisguitarguy/8c723d9512471dae610b to your computer and use it in GitHub Desktop.

Select an option

Save chrisguitarguy/8c723d9512471dae610b to your computer and use it in GitHub Desktop.
<?php
interface Article
{
public function getIdentifier();
public function getTitle();
public function setTitle($title);
public function getBody();
public function setBody($body);
public function getYear();
public function setYear($year);
}
<?php
interface ArticleRepository
{
public function find($id);
public function findAll();
public function findByYear($year);
public function add(Article $article);
public function remove($article);
}
<?php
use Doctrine\ORM\EntityRepository;
final class DoctrineArticleRepository extends EntityRepository implements ArticleRepository
{
// EntityRepository provides this method
// but we override it to get ordering
public function findAll()
{
return $this->findBy([], [
'year' => 'DESC',
'title' => 'ASC',
]);
}
public function add(Article $article)
{
$em = $this->getEntityManager();
$em->persist($article);
$em->flush(); // probably not a good idea in a larger app
return $article->getIdentifier();
}
}
<?php
use Illuminate\Database\Eloquent\Model;
class EloquentArticle extends Model implements Article
{
// configures some stuff for Eloquent
public $timestamps = false;
protected $table = 'articles';
}
<?php
final class EloquentArticleRepository implements ArticleRepository
{
public function findAll()
{
return EloquentArticle::query()
->orderBy('year', 'DESC')
->orderBy('title', 'ASC')
->get();
}
public function add(Article $article)
{
if (!$article instanceof EloquentArticle) {
throw new \InvalidArgumentException(sprintf(
'%s expects and instance of %s, got "%s"',
__METHOD__,
EloquentArticle::class,
get_class($article)
));
}
$article->save();
return $article->id;
}
}
<?php
final class PdoArticleRepository implements ArticleRepository
{
const TABLE = 'articles';
/**
* @var PDO
*/
private $conn;
public function __construct(\PDO $conn)
{
$this->conn = $conn;
}
public function findAll()
{
$stm = $this->conn->query(
$this->getSelect().' ORDER BY publish_year DESC, title ASC'
);
$out = $this->statementToObjects($stm);
$stm->closeCursor();
return $out;
}
public function add(Article $article)
{
$id = $article->getIdentifier();
$params = [
':title' => $article->getTitle(),
':body' => $article->getBody(),
':year' => $article->getYear(),
];
$bind = [
':year' => \PDO::PARAM_INT,
];
if ($id) {
$sql = 'UPDATE '.self::TABLE.' SET title = :title, body = :body, publish_year = :year WHERE id = :id';
$params[':id'] = $id;
$bind[':id'] = \PDO::PARAM_INT;
} else {
$sql = 'INSERT INTO '.self::TABLE.' (title, body, publish_year) VALUES (:title, :body, :year)';
}
$stm = $this->conn->prepare($sql);
foreach ($params as $name => $val) {
$stm->bindValue(
$name,
$val,
isset($bind[$name]) ? $bind[$name] : \PDO::PARAM_STR
);
}
$stm->execute();
return $id ? $id : intval($this->conn->lastInsertId());
}
// may make more sense to use a factory object here, but
// let's keep this somewhat simple.
private function toObject(array $row)
{
$article = new SimpleArticle($row['id']);
$article->setTitle($row['title']);
$article->setBody($row['body']);
$article->setYear($row['publish_year']);
return $article;
}
private function statementToObjects(\PDOStatement $stm)
{
// could very easily use an iterator or a generator here
// with big data sets, again, let's keep it simple.
$stm->setFetchMode(\PDO::FETCH_ASSOC);
return array_map([$this, 'toObject'], $stm->fetchAll());
}
private function getSelect()
{
return 'SELECT id, title, body, publish_year FROM '.self::TABLE;
}
}
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
<entity name="PMG\ThreeRepositories\SimpleArticle" table="articles" repository-class="PMG\ThreeRepositories\DoctrineArticleRepository">
<id name="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="title" type="text" />
<field name="body" type="text" />
<field name="year" column="publish_year" type="integer" />
</entity>
</doctrine-mapping>
<?php
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
protected $repo;
public function testArticlesCanBePersistedUpdatedFetchedAndRemoved()
{
$this->assertEmpty($this->repo->findAll());
$this->assertEmpty($this->repo->findByYear(2015));
$article = $this->createArticle();
$article->setTitle('Hello');
$article->setBody('World');
$article->setYear(2015);
$id = $this->repo->add($article);
$this->assertCount(1, $this->repo->findAll());
$this->assertEmpty($this->repo->findByYear(2014));
$this->assertCount(1, $this->repo->findByYear(2015));
$article = $this->repo->find($id);
$this->assertInstanceOf(Article::class, $article);
$article->setTitle('changed');
$this->repo->add($article);
$article = $this->repo->find($id);
$this->assertInstanceOf(Article::class, $article);
$this->assertEquals('changed', $article->getTitle());
$this->repo->remove($article);
$this->assertNull($this->repo->find($id));
}
abstract protected function createArticle();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment