Прямой порт описания паттерна из PoEAA на php. Небольшую вольность позволил себе только с ActiveRecord::load.
Да, именно это называется ActiveRecord.
Так что, давайте прекращать ссылаться на Фаулера в контексте RoR-подобных реализаций AR (yii, eloquent итд), окей?
PHP:
<?php
class ActiveRecord {
protected static $db;
public static function setDb(Pdo $db) {
self::$db = $db;
}
public static function load(array $resultset) {
$instance = new static;
foreach ($resultset as $key => $value) {
if (property_exists($instance, $key)) {
$instance->$key = $value;
}
}
return $instance;
}
}
class User extends ActiveRecord {
const FIND_BY_ID_STMT = "SELECT id, email, name FROM User WHERE id = :id";
const FIND_BY_EMAIL_STMT = "SELECT id, email, name FROM User WHERE email = :email";
const INSERT_STMT = "INSERT INTO User (name, email) VALUES (:name, :email)";
const UPDATE_STMT = "UPDATE User SET name = :name, email = :email WHERE id = :id";
const DELETE_STMT = "DELETE FROM User WHERE id = :id";
protected $id;
protected $name;
protected $email;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
public function getEmail() {
return $this->email;
}
public function setEmail($email) {
$this->email = $email;
}
public static function findById($id) {
$stmt = self::$db->prepare(self::FIND_BY_ID_STMT);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? self::load($row) : null;
}
public static function findByEmail($email) {
$stmt = self::$db->prepare(self::FIND_BY_EMAIL_STMT);
$stmt->bindParam(':email', $email, PDO::PARAM_STR);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? self::load($row) : null;
}
public function insert() {
$stmt = self::$db->prepare(self::INSERT_STMT);
$stmt->bindParam(':email', $this->email, PDO::PARAM_STR);
$stmt->bindParam(':name', $this->name, PDO::PARAM_STR);
$stmt->execute();
return $this->id = self::$db->lastInsertId();
}
public function update() {
if (!isset($this->id)) {
throw new LogicException("Cannot update(): id is not defined");
}
$stmt = self::$db->prepare(self::UPDATE_STMT);
$stmt->bindParam(':id', $this->id, PDO::PARAM_INT);
$stmt->bindParam(':email', $this->email, PDO::PARAM_STR);
$stmt->bindParam(':name', $this->name, PDO::PARAM_STR);
$stmt->execute();
}
public function delete() {
if (!isset($this->id)) {
throw new LogicException("Cannot delete(): id is not defined");
}
$stmt = self::$db->prepare(self::DELETE_STMT);
$stmt->bindParam(':id', $this->id, PDO::PARAM_INT);
$stmt->execute();
$this->id = null;
}
}
class ArUserTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$db = new \Pdo('mysql:host=localhost;dbname=test', 'test', 'test');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->query('DROP TABLE IF EXISTS User');
$db->query(
'CREATE TABLE User (
id integer not null auto_increment,
email varchar(255),
name varchar(255),
PRIMARY KEY (id),
UNIQUE (email)
)'
);
ActiveRecord::setDb($db);
}
public function test() {
$User = new User;
$User->setEmail('[email protected]');
$User->setName('test user');
$id = $User->insert();
$this->assertEquals(1, $id);
$User = User::findById(1);
$this->assertEquals(1, $User->getId());
$this->assertEquals('[email protected]', $User->getEmail());
$this->assertEquals('test user', $User->getName());
$User = User::findByEmail('[email protected]');
$this->assertEquals(1, $User->getId());
$this->assertEquals('[email protected]', $User->getEmail());
$this->assertEquals('test user', $User->getName());
$User->setEmail('[email protected]');
$User->setName('test2 user');
$User->update();
$User = User::findById(1);
$this->assertEquals(1, $User->getId());
$this->assertEquals('[email protected]', $User->getEmail());
$this->assertEquals('test2 user', $User->getName());
$User->delete();
$this->assertNull($User->findById(1));
}
}
Так что, давайте прекращать ссылаться на Фаулера в контексте RoR-подобных реализаций AR (yii, eloquent итд), окей?