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 registry($k, $v = null) {
- static $r = [];
- return func_num_args() > 1 ? $r[$k] = $v : $r[$k] ?? null;
- }
- function render($filename, $data = []) {
- extract($data);
- require TEMPLATE_PATH . DS . $filename . '.php';
- }
- function error(int $code, callable $callback = null) {
- static $callbacks = [];
- if ($callback) {
- return $callbacks[$code] = $callback;
- }
- http_response_code($code);
- if (isset($callbacks[$code])) {
- $callbacks[$code]();
- }
- }
- /*
- // Модифицированная версия https://gist.github.com/Xeoncross/5357205
- function route(string $path, string $method = $_SERVER['REQUEST_METHOD'], callable $callback = null) {
- static $routes = [];
- if ($callback) {
- // shortcuts
- $path = str_replace(
- ['(:any)', '(:id)', '(:year)', '(:month)', '(:day)'],
- ['([^/]+)', '(\d+)', '(\d{4})', '(0[1-9]|1[0-2])', '([0-2][1-9]|30|31)'],
- $path
- );
- // ...
- return $routes[$method]["#^{$path}$#"] = $callback;
- }
- if (isset($routes[$method])) {
- foreach ($routes[$method] as $regex => $callback) {
- if (preg_match($regex, $path, $matches)) {
- return $callback(...array_slice($matches, 1));
- }
- }
- }
- error(404);
- }
- route('/hello/(:any)', 'GET', function ($name) {
- echo "Hello {$name}!";
- });
- route('/hello/World');
- error(404, function () {
- echo 'Page Not Found';
- });
- route('/page-no-exists');
- */
- 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 count() {
- return count($this->data);
- }
- public function getIterator() {
- $obj = new ArrayObject($this->data);
- return $obj->getIterator();
- }
- public function toArray() {
- return $this->data;
- }
- protected function reindex() {
- $this->data = array_values($this->data);
- }
- }
- // ...
- /**
- * TODO: переписать.
- */
- class DB {
- protected $dbname;
- protected $user;
- protected $password;
- protected $host;
- protected $port;
- protected $charset;
- protected $connection;
- protected $statement;
- protected $queries = [];
- 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;
- }
- 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
- );
- try {
- $this->connection = new PDO($dsn, $this->user, $this->password, [
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
- ]);
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function disconnect() {
- $this->connection = null;
- }
- public function query($sql, $bind = []) {
- // Подключаемся при первом запросе
- $this->connect();
- try {
- $t = -microtime(1);
- $this->statement = $this->connection->prepare($sql);
- $this->statement->execute($bind);
- $t += microtime(1);
- $this->queries[$sql] = $t;
- return $this;
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- function select($table, $fields = '*', $conditions = [], $limit = 0,
- $offset = 0, $sort = []) {
- if (is_array($fields)) {
- $fields = array_map([$this, 'quoteIdentifier'], $fields);
- $fields = implode(', ', $fields);
- }
- $bind = array_values($conditions);
- $where = [];
- foreach (array_keys($conditions) as $column) {
- $where[] = $this->quoteIdentifier($column) . ' = ?';
- }
- $order_by = [];
- foreach ($sort as $column => $order) {
- $order = strtoupper(trim($order));
- $order = $order === 'ASC' ? $order : 'DESC';
- $order_by[] = sprintf('%s %s', $this->quoteIdentifier($column), $order);
- }
- $sql = sprintf('SELECT %s FROM %s', $fields, $this->quoteIdentifier($table))
- . ($where ? ' WHERE ' . implode(' AND ', $where) : '')
- . ($order_by ? ' ORDER BY ' . implode(', ', $order_by) : '')
- . ($limit
- ? sprintf(' LIMIT %d, %d', $offset, $limit)
- : $offset
- ? sprintf(' OFFSET %d', $offset)
- : '')
- . ';';
- $this->query($sql, $bind);
- return $this;
- }
- public function insert($table, $data) {
- $sql = sprintf(
- 'INSERT INTO %s (%s) VALUES (%s);',
- $this->quoteIdentifier($table),
- implode(', ', array_map([$this, 'quoteIdentifier'], array_keys($data))),
- substr(str_repeat('?, ', count($data)), 0, -2)
- );
- $this->query($sql, array_values($data));
- return $this->lastInsertId();
- }
- public function update($table, $data, $conditions = []) {
- $bind = array_values($data);
- $set = [];
- foreach (array_keys($data) as $column) {
- $set[] = $this->quoteIdentifier($column) . ' = ?';
- }
- $where = [];
- foreach ($conditions as $column => $value) {
- $where[] = $this->quoteIdentifier($column) . ' = ?';
- $bind[] = $value;
- }
- $sql = sprintf(
- 'UPDATE %s SET %s',
- $this->quoteIdentifier($table),
- implode(', ', $set)
- )
- . ($where ? ' WHERE ' . implode(' AND ', $where) : '')
- . ';';
- return $this->query($sql, $bind)->affectedRows();
- }
- public function delete($table, $conditions = []) {
- $bind = array_values($conditions);
- $where = [];
- foreach (array_keys($conditions) as $column) {
- $where[] = $this->quoteIdentifier($column) . ' = ?';
- }
- $sql = sprintf('DELETE FROM %s', $this->quoteIdentifier($table))
- . ($where ? ' WHERE ' . implode(' AND ', $where) : '')
- . ';';
- return $this->query($sql, $bind)->affectedRows();
- }
- public function fetch() {
- try {
- return $this->statement->fetch();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function fetchOne() {
- try {
- return $this->statement->fetchColumn();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function fetchAll() {
- try {
- return $this->statement->fetchAll();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function affectedRows() {
- try {
- return $this->statement->rowCount();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function lastInsertId() {
- try {
- return $this->connection->lastInsertId();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function beginTransaction() {
- try {
- return $this->connection->beginTransaction();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function commit() {
- try {
- return $this->connection->commit();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function rollBack() {
- try {
- return $this->connection->rollBack();
- } catch (PDOException $e) {
- throw new RuntimeException($e->getMessage());
- }
- }
- public function quoteIdentifier($name) {
- return '`' . str_replace('`', '``', $name) . '`';
- }
- public function getQueries() {
- return $this->queries;
- }
- public function __destruct() {
- $this->disconnect();
- }
- }
- abstract class Entity implements IteratorAggregate {
- protected $data;
- public function __construct(array $data = []) {
- $this->data = $data;
- }
- public function __set($property, $value) {
- $this->data[$property] = $value;
- }
- public function __get($property) {
- return $this->data[$property] ?? null;
- }
- public function __isset($property) {
- return isset($this->data[$property]);
- }
- public function __unset($property) {
- unset($this->data[$property]);
- }
- public function getIterator() {
- $obj = new ArrayObject($this->data);
- return $obj->getIterator();
- }
- public function toArray() {
- return $this->data;
- }
- }
- // Код ужасен
- abstract class EntityMapper {
- protected $db;
- protected $fields = [];
- protected $primaryKey;
- // Эти свойства переопределяются в классах наследниках
- protected $table;
- protected $entitylClass;
- public function __construct($db) {
- $this->db = $db;
- $this->describeFields();
- }
- public function find($id) {
- $row = $this->db->select(
- $this->table,
- '*',
- [$this->primaryKey => $id]
- )->fetch();
- return $row
- ? $this->createEntity($row)
- : null;
- }
- public function findAll(array $conditions = [], int $limit = 0,
- int $offset = 0, array $sort = []): array {
- $rows = $this->db->select(
- $this->table,
- '*',
- $conditions,
- $limit,
- $offset,
- $sort
- )->fetchAll();
- return $this->createEntities($rows);
- }
- public function save(Entity $entry): bool {
- $data = [];
- foreach ($this->fields as $field) {
- $data[$field] = $entry->$field;
- }
- if ($entry->{$this->primaryKey}) {
- unset($data[$this->primaryKey]);
- $affected = $this->db->update(
- $this->table,
- $data,
- [$this->primaryKey => $entry->{$this->primaryKey}]
- );
- return $affected === 1;
- }
- $id = $this->db->insert($this->table, $data);
- if ($id) {
- $entry->{$this->primaryKey} = $id;
- return true;
- }
- return false;
- }
- public function delete(Entity $entry): bool {
- $affected = $this->db->delete(
- $this->table,
- [$this->primaryKey => $entry->{$this->primaryKey}]
- );
- if ($affected) {
- $entry->{$this->primaryKey} = null;
- return true;
- }
- return false;
- }
- protected function describeFields() {
- $sql = sprintf('DESCRIBE %s;', $this->db->quoteIdentifier($this->table));
- $rows = $this->db->query($sql)->fetchAll();
- foreach ($rows as $row) {
- $this->fields[] = $row['Field'];
- if ($row['Key'] === 'PRI') {
- $this->primaryKey = $row['Field'];
- }
- }
- }
- protected function createEntity(array $row) {
- return new $this->entityClass($row);
- }
- protected function createEntities(array $rows) {
- return array_map([$this, 'createEntity'], $rows);
- }
- }
- class MapperRepository {
- protected $db;
- protected $mappers = [];
- public function __construct(DB $db) {
- $this->db = $db;
- }
- public function getDB() {
- return $this->db;
- }
- public function getMapper($name) {
- if (!isset($this->mappers[$name])) {
- $this->mappers[$name] = new $name($this->db);
- }
- return $this->mappers[$name];
- }
- }
- class User extends Entity {
- // Add some methods
- }
- class UserMapper extends EntityMapper {
- protected $table = 'users';
- protected $entityClass = '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
- */
- // dump($_SERVER);
- $db = new DB('test');
- $repo = new MapperRepository($db);
- $user = new User([
- 'username' => 'u' . uniqid(),
- 'email' => uniqid() . '@example.com',
- 'password' => substr(md5(uniqid()), 0, 6)
- ]);
- $map = $repo->getMapper('UserMapper');
- $map->save($user);
- $users = $map->findAll([], 10, 20, ['id' => 'asc']);
- dump($users);
- dump($db->getQueries());
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement