Skip to content

Instantly share code, notes, and snippets.

@mariovalney
Last active June 6, 2019 00:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mariovalney/bce5c39dbeb80614ce14eabf4f115dcb to your computer and use it in GitHub Desktop.
Save mariovalney/bce5c39dbeb80614ce14eabf4f115dcb to your computer and use it in GitHub Desktop.
A simple implementation of Active Record.
<?php
namespace App\Database;
interface Database
{
public static function getInstance();
public function create(string $table, array $columns);
public function select(string $table, array $where );
public function insert(string $table, array $values);
public function update(string $table, array $values, array $where);
public function delete(string $table, array $where = []);
}
<?php
namespace App\Support;
use App\Support\Facades\Database;
use App\Support\Doctrine\Inflector;
/**
* Inflector is from Doctrine. You can remove it and always give a table property on model.
* Facade is a simple implementation. You can use the object from Mysql:getInstance().
*/
class Model
{
/**
* The identifier column
*
* @var string
*/
protected static $identifier = 'ID';
/**
* Field of Model
*
* @var array
*/
protected $fillable = [];
/**
* Attributes of Model
*
* @var array
*/
protected $attributes = [];
/**
* Create a new Model
*/
public function __construct(array $attributes = [])
{
foreach ($attributes as $key => $value) {
if ($key === static::$identifier) {
$this->{static::$identifier} = $value;
continue;
}
if (! in_array($key, $this->fillable, true)) {
continue;
}
$this->attributes[ $key ] = $value;
}
}
/**
* Magic method to get attributes
*
* @param string $name
* @return mixed
*/
public function __get(string $name)
{
return $this->attributes[ $name ] ?? null;
}
/**
* Magic method to set attributes
*
* @param string $name
* @return mixed
*/
public function __set(string $name, $value)
{
if ($name === static::$identifier) {
$this->{static::$identifier} = $value;
return;
}
if (! in_array($name, $this->fillable)) {
return;
}
$this->attributes[ $name ] = $value;
}
/**
* Create or update a new registry on database
*/
public function save()
{
$identifier = $this->{static::$identifier};
if (empty($identifier)) {
return Database::insert(static::getTable(), $this->attributes);
}
$where = [static::$identifier => $identifier];
$result = Database::update(static::getTable(), $this->attributes, $where);
return ($result) ? $identifier : 0;
}
/**
* Remove a registry from database
*/
public function delete()
{
$identifier = $this->{static::$identifier};
$where = [static::$identifier => $identifier];
return Database::delete(static::getTable(), $where);
}
/**
* Retrieve a single registry from database
*
* @param string $identifier
*
* @return Model
*/
public static function find($identifier)
{
$where = [static::$identifier => $identifier];
$result = Database::select(static::getTable(), $where);
if (empty($result)) {
return false;
}
return new static($result[0]);
}
/**
* Retrieve all registries from database
*
* @return Model
*/
public static function all()
{
$results = Database::select(static::getTable());
foreach ($results as $key => $result) {
$results[ $key ] = new static($result);
}
return $results;
}
/**
* Get table name of model
*
* @return string
*/
private static function getTable()
{
if (! empty(static::$table)) {
return static::$table;
}
$table = static::class;
$table = explode('\\', $table);
$table = strtolower(array_pop($table));
$table = Inflector::pluralize($table);
return $table;
}
}
<?php
namespace App\Database;
use Exception;
use PDO;
use PDOException;
use App\Support\Logger;
class Mysql implements Database
{
/** @var Mysql */
private static $instance;
/** @var PDO */
private $conn;
/** @var string */
private $dns;
/** @var string */
private $db;
/** @var string */
private $host;
/** @var int */
private $port;
/** @var string */
private $user;
/** @var string */
private $pass;
/**
* Creating connection
*/
private function __construct()
{
if (! defined('DB_NAME') || ! defined('DB_HOST') || ! defined('DB_USER') || ! defined('DB_PASS') ) {
die('Check database info in config.php');
}
$this->db = DB_NAME;
$this->host = DB_HOST;
$this->port = DB_PORT;
$this->user = DB_USER;
$this->pass = DB_PASS;
$this->dns = 'mysql:host=' . $this->host . ':' . $this->port . ';dbname=' . $this->db;
try {
$args = [
PDO::MYSQL_ATTR_FOUND_ROWS => true,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF8",
];
$this->conn = new PDO($this->dns, $this->user, $this->pass, $args);
} catch (PDOException $ex) {
die("Error to connect with Database");
}
}
/**
* Avoid Cloning
*/
private function __clone() {}
/**
* Avoid Unserialize
*/
private function __wakeup() {}
/**
* Retrieve a instance
*
* @return
*/
public static function getInstance()
{
if (! self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Create a table if not exits
*
* @param string $table
* @param array $columns
*
* @return
*/
public function create(string $table, array $columns) {
$columns = implode(',', array_values($columns));
$query = "CREATE TABLE IF NOT EXISTS $table ($columns)";
$result = $this->conn->exec($query);
}
/**
* Perform a SELECT query
*
* @param string $table
* @param array $where
*
* @return array
*/
public function select(string $table, array $where = []) {
$where = $this->createWhereClause($where);
$query = "SELECT * FROM $table WHERE $where->clause";
$query = $this->conn->prepare($query);
$query->execute($where->values);
return $query->fetchAll();
}
/**
* Perform a INSERT INTO query
*
* @param string $table
* @param array $values
*
* @return integer
*/
public function insert(string $table, array $values) {
if (empty($values)) {
return 0;
}
$columns = array_keys($values);
$columns = '`' . implode('`,`', $columns) . '`';
$placeholders = array_fill(0, count($values), '?');
$placeholders = implode(',', $placeholders);
$query = "INSERT INTO $table ($columns) VALUES ($placeholders)";
$query = $this->conn->prepare($query);
try {
$query->execute(array_values($values));
} catch (Exception $e) {
Logger::error($e->getMessage());
return 0;
}
return $this->conn->lastInsertId();
}
/**
* Perform a UPDATE query
*
* @param string $table
* @param array $values
*
* @return integer
*/
public function update(string $table, array $values, array $where = []) {
$data = [];
foreach ($values as $key => $value) {
$values[ $key ] = "$key = ?";
$data[] = $value;
}
$values = implode(',', array_values($values));
$where = $this->createWhereClause($where);
$query = "UPDATE $table SET $values WHERE $where->clause";
$query = $this->conn->prepare($query);
try {
$query->execute(array_merge($data, $where->values));
} catch (Exception $e) {
Logger::error($e->getMessage());
return 0;
}
return $query->rowCount();
}
/**
* Perform a DELETE query
*
* @param string $table
* @param array $values
*
* @return integer
*/
public function delete(string $table, array $where = []) {
$where = $this->createWhereClause($where);
$query = "DELETE FROM $table WHERE $where->clause";
$query = $this->conn->prepare($query);
try {
$query->execute($where->values);
} catch (Exception $e) {
Logger::error($e->getMessage());
return 0;
}
return $query->rowCount();
}
/**
* Return a WHERE clause
*
* @param array $where
* @return object
*/
private function createWhereClause(array $where)
{
if (empty($where)) {
$where = ['1' => '1'];
}
$values = [];
foreach ($where as $key => $comparison) {
if (! is_array($comparison)) {
$comparison = ['=', $comparison];
}
if (count($comparison) !== 2) {
continue;
}
$where[ $key ] = "$key $comparison[0] ?";
$values[] = $comparison[1];
}
$where = implode(' AND ', array_values($where));
return (object) [
'clause' => $where,
'values' => $values,
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment