Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- define('DS', DIRECTORY_SEPARATOR);
- define('BASE_PATH', __DIR__);
- define('CLASS_PATH', BASE_PATH . DS . 'classes' );
- define('TEMPLATE_PATH', BASE_PATH . DS . 'templates');
- function writeln($s) {
- echo $s . '<br>';
- }
- function dump($v) {
- echo '<pre>' . print_r($v, 1) . '</pre>';
- }
- function array_get($array, $key, $default = null) {
- return array_key_exists($key, $array) ? $array[$key] : $default;
- }
- function registry($k, $v = null) {
- static $r = [];
- return func_num_args() > 1 ? $r[$k] = $v : array_get($r, $k);
- }
- function template($filename, $data = []) {
- extract($data);
- ob_start();
- require TEMPLATE_PATH . DS . $filename . '.php';
- return ob_end_clean();
- }
- class Set implements Countable, IteratorAggregate {
- protected $data = [];
- public function __construct($data = []) {
- $this->update($data);
- }
- public function has($v) {
- return in_array($v, $this->data, true);
- }
- public function add($v) {
- if (!$this->has($v)) {
- $this->data[] = $v;
- }
- }
- public function update(array $data) {
- foreach ($data as $v) {
- $this->add($v);
- }
- }
- public function remove($v) {
- $i = array_search($v, $this->data, true);
- if (false !== $i) {
- unset($this->data[$i]);
- // Можно закомментировать, если не нужны индексы, идущие по порядку
- $this->reindex();
- }
- }
- public function clear() {
- $this->data = [];
- }
- public function toArray() {
- return $this->data;
- }
- public function count() {
- return count($this->data);
- }
- public function getIterator() {
- $obj = new ArrayObject($this->data);
- return $obj->getIterator();
- }
- protected function reindex() {
- $this->data = array_values($this->data);
- }
- }
- // ...
- /* (s => {
- let m = s.match(/\$(\w+)/g)
- return m.reduce((a, b) => a + ' protected ' + b + ';\n', '')
- + m.reduce((a, b) => a + ' $this->' + b.slice(1) + ' = ' + b + ';\n', '')
- })(`$dbname, $user = 'root', $password = '',
- $host = 'localhost', $port = 3306, $charset = 'utf8'`) */
- // Column is collection of cells aligned vertically in a table.
- // Field is an element in which one piece of information is stored
- // Table = Relation
- // Row = Tuple
- // Column = Attribute
- // Domain = Data Type
- class DB {
- protected $connection;
- protected $dbname;
- protected $user;
- protected $password;
- protected $host;
- protected $port;
- protected $charset;
- public function __construct($dbname, $user = 'root', $password = '',
- $host = 'localhost', $port = 3306, $charset = 'utf8') {
- $this->dbname = $dbname;
- $this->user = $user;
- $this->password = $password;
- $this->host = $host;
- $this->port = $port;
- $this->charset = $charset;
- $this->connect();
- }
- public function connect() {
- if ($this->connection) {
- return;
- }
- $dsn = sprintf(
- 'mysql:dbname=%s;host=%s;port=%d;charset=%s',
- $this->dbname,
- $this->host,
- $this->port,
- $this->charset
- );
- $this->connection = new PDO($dsn, $this->user, $this->password, [
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
- ]);
- }
- public function disconnect() {
- $this->connection = null;
- }
- public function __destruct() {
- $this->disconnect();
- }
- public function query($sql, $bind = []) {
- $s = $this->connection->prepare($sql);
- $s->execute($bind);
- return $s;
- }
- public function exec($sql, $bind = []) {
- return $this->query($sql, $bind)->rowCount();
- }
- public function lastInsertId() {
- return $this->connection->lastInsertId();
- }
- function find(string $table, int $id, string $key = 'id') {
- $sql = sprintf(
- 'SELECT * FROM %s WHERE %s = ?;',
- $this->quoteIdent($table),
- $key
- );
- return $this->query($sql, [$id])->fetch();
- }
- function findAll(string $table) {
- $sql = sprintf(
- 'SELECT * FROM %s;',
- $this->quoteIdent($table),
- );
- return $this->query($sql)->fetchAll();
- }
- public function insert($table, array $data) {
- $sql = sprintf(
- 'INSERT INTO %s (%s) VALUES (%s);',
- $this->quoteIdent($table),
- implode(', ', array_map([$this, 'qouteIdent'], array_keys($data))),
- substr(str_repeat('?, ', count($data)), 0, -2)
- );
- $this->exec($sql, array_values($data));
- return $this->lastInsertId();
- }
- public function update(string $table, array $data, int $id, string $key = 'id') {
- $set = [];
- foreach (array_keys($data) as $column) {
- $set[] = $this->quoteIdent($column) . ' = ?';
- }
- $sql = sprintf(
- 'UPDATE %s SET %s WHERE %s = ?;',
- $this->quoteIdent($table),
- implode(', ', $set),
- $key
- );
- $bind = array_values($data);
- $bind[] = $id;
- return $this->exec($sql, $bind);
- }
- public function delete(string $table, int $int, string $key = 'id') {
- $sql = sprintf(
- 'DELETE FROM %s WHERE %s = ?;',
- $this->quoteIdent($table),
- $key
- );
- return $this->exec($sql, [$id]);
- }
- // Транзакции
- public function beginTransaction() {
- return $this->connection->beginTransaction();
- }
- public function commit() {
- return $this->connection->commit();
- }
- public function rollBack() {
- return $this->connection->rollBack();
- }
- public function quoteIdent($name) {
- return '`' . str_replace('`', '``', $name) . '`';
- }
- }
- // http://qiita.com/asaokamei/items/d0957a51e4b943006997
- // Ведет себя как объект и как массив.
- // http://ideone.com/2j2Dwi
- // $m->data возвращвет null
- abstract class AbstractModel implements ArrayAccess, Countable,
- IteratorAggregate {
- protected $data;
- public function __construct(array $data = []) {
- $this->data = $data;
- }
- public function toArray() {
- return $this->data;
- }
- public function set($key, $value) {
- $this->data[$key] = $value;
- }
- public function has($key) {
- return array_key_exists($key, $this->data);
- }
- public function get($key, $default = null) {
- return $this->has($key) ? $this->data[$key] : $default;
- }
- public function remove($key) {
- unset($this->data[$key]);
- }
- public function keys() {
- return array_keys($this->data);
- }
- public function values() {
- return array_values($this->data);
- }
- public function __set($property, $value) {
- $this->set($property, $value);
- }
- public function __get($property) {
- return $this->get($property);
- }
- public function __isset($property) {
- return $this->has($property);
- }
- public function __unset($property) {
- $this->remove($property);
- }
- public function offsetSet($key, $value) {
- // $obj[] = $value;
- if (!is_null($key)) {
- $this->set($key, $value);
- }
- }
- public function offsetExists($key) {
- return $this->has($key);
- }
- public function offsetUnset($key) {
- $this->remove($key);
- }
- public function offsetGet($key) {
- return $this->get($key);
- }
- public function count() {
- return count($this->data);
- }
- public function getIterator() {
- $obj = new ArrayObject($this->data);
- return $obj->getIterator();
- }
- }
- abstract class AbstractMapper {
- protected $adapter;
- protected $primaryKey;
- protected $fields = [];
- // Эти свойства переопределяются в классах наследниках
- protected $table;
- protected $modelClass;
- public function __construct($adapter) {
- $this->adapter = $adapter;
- $this->describe();
- }
- public function find($id) {
- $row = $this->adapter->find($this->table, $id, $this->primaryKey);
- return $row ? $this->createObject($row) : null;
- }
- public function findAll() {
- $rows = $this->adapter->findAll($this->table);
- return $this->createObjects($rows);
- }
- public function save(AbstractModel $o) {
- return $o->{$this->primaryKey} ? $this->update($o) : $this->insert($o);
- }
- public function update(AbstractModel $o) {
- $data = $this->getModelData($o);
- $affected_rows = $this->adapter->update(
- $this->table,
- $data,
- $o->{$this->primaryKey},
- $this->primaryKey
- );
- }
- public function insert(AbstractModel $o) {
- $data = $this->getModelData($o);
- $id = $this->adapter->insert($this->table, $data);
- return $o->{$this->primaryKey} = $id;
- }
- public function remove(AbstractModel $o) {
- $affected_rows = $this->adapter->delete(
- $this->table,
- $o->{$this->primaryKey},
- $this->primaryKey
- );
- if ($affected_rows) {
- $o->{$this->primaryKey} = null;
- return true;
- }
- return false;
- }
- protected function describe() {
- $rows = $this->adapter->describe($this->table);
- foreach ($rows as $row) {
- $this->fields[] = $row['Field'];
- if ($row['Key'] === 'PRI') {
- $this->primaryKey = $row['Field'];
- }
- }
- }
- protected function createObject($row) {
- return new $this->modelClass($row);
- }
- protected function createObjects($rows) {
- return array_map([$this, 'createObject'], $rows);
- }
- // TODO: придумать более подходящее имя
- protected function getModelData(AbstractModel $o) {
- $ret = [];
- // Выбираем только те ключи, которые совпадают с именами колонок таблицы
- $keys = array_intersect($this->fields, $o->keys());
- foreach ($keys as $k) {
- $ret[$k] = $o[$k];
- }
- return $ret;
- }
- }
- class User extends AbstractModel {
- // Add some methods
- }
- class UserMapper extends AbstractMapper {
- protected $table = 'users';
- protected $modelClass = 'User';
- }
- /*
- CREATE TABLE `users` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
- `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
- `password` varchar(20) NOT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `username` (`username`),
- UNIQUE KEY `email` (`email`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8
- */
- $db = new MySQLAdapter(['dbname' => 'test']);
- $userMapper = new UserMapper($db);
- $user = new User([
- 'username' => 'r00t',
- 'email' => 'root@localhost',
- 'password' => '1'
- ]);
- $userMapper->save($user);
- dump($user);
- $user->password = '123456';
- $userMapper->save($user);
- dump($user);
- $userMapper->remove($user);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement