Compare commits

...

1 Commits

Author SHA1 Message Date
sheychen 47c0be00fb WIP 2018-07-11 14:39:17 +02:00
24 changed files with 1804 additions and 1380 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
vendor

42
LICENSE
View File

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2017 sheychen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License
Copyright (c) 2017 sheychen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,18 +1,17 @@
{
"name": "krutush/database",
"license": "MIT",
"authors": [
{
"name": "sheychen",
"email": "contact@clementbois.fr"
}
],
"require": {
"krutush/krutush": "dev-develop"
},
"autoload": {
"psr-4": {
"Krutush\\Database\\": "src/"
}
}
}
{
"name": "krutush/database",
"license": "MIT",
"authors": [
{
"name": "sheychen",
"email": "contact@clementbois.fr"
}
],
"require": {},
"autoload": {
"psr-4": {
"Krutush\\Database\\": "src/",
"Krutush\\Database\\Exemple\\": "exemple/"
}
}
}

View File

@ -0,0 +1,25 @@
$migration->create(
Krutush\Database\Exemple\Model\UserModel:class,
Krutush\Database\ModelID:class,
[
'id' => [
'column' => 'user_id',
'type' => 'bigint'
],
'first_name' => [
'not_null' => true
],
'last_name' => [
'not_null' => true
],
'supervisor' => [
'foreign' => []
],
'supervised' => [
'virtual' => true,
'foreign' => [
'key' => 'supervisor',
'multiple' => true
]
]
]);

View File

@ -0,0 +1,10 @@
$migration->alter(
Krutush\Database\Exemple\Model\UserModel:class,
[
'first_name' => [
'unique' => 'full_name'
],
'last_name' => [
'unique' => 'full_name'
]
]);

View File

@ -0,0 +1,11 @@
$migration->create(
Krutush\Database\Exemple\Model\OfficeModel:class,
Krutush\Database\ModelID:class,
['name']
)->alter(
Krutush\Database\Exemple\Model\UserModel:class,
[
'office' => [
'foreign' => Krutush\Database\Exemple\Model\OfficeModel:class,
]
]);

View File

@ -0,0 +1,10 @@
<?php
namespace Krutush\Database\Exemple\Model;
use Krutush\Database\ModelID;
class OfficeModel extends ModelID{
public const FIELDS = [
'name'
];
}

View File

@ -0,0 +1,35 @@
<?php
namespace Krutush\Database\Exemple\Model;
use Krutush\Database\ModelID;
class UserModel extends ModelID{
public const FIELDS = [
'id' => [
'column' => 'user_id',
'type' => 'bigint'
],
'first_name' => [
'not_null' => true,
'unique' => 'full_name'
],
'last_name' => [
'not_null' => true,
'unique' => 'full_name'
],
'supervisor' => [
'foreign' => []
],
'supervised' => [
'virtual' => true,
'index' => true,
'foreign' => [
'key' => 'supervisor',
'multiple' => true
]
],
'office' => [
'foreign' => OfficeModel::class,
]
];
}

17
exemple/index.php Normal file
View File

@ -0,0 +1,17 @@
<?php
require_once('../vendor/autoload.php');
(new Krutush\Database\Connection('Databases.php'))->connect();
$UserModel = Krutush\Database\Exemple\Model\UserModel::class;
var_dump($UserModel::getTable());
//var_dump($UserModel::getFields());
var_dump((new $UserModel([
'id' => 42,
'first_name' => 'Pierre De La VIEDDDDDDD',
'last_name' => 'Caillou'
]))->insert());
//TODO: format src before commit

View File

@ -1,74 +1,82 @@
<?php
namespace Krutush\Database;
class Connection{
protected static $databases = array();
protected $settings;
public function __construct(string $path = null){
if(isset($path))
$this->settings = include($path);
}
public function connect(string $dbname = null){
if(static::exists($dbname))
throw new DatabaseException("Allready connect");
$dbname = static::parseName($dbname);
if(!isset($this->settings[$dbname]))
throw new DatabaseException('Can\'t find '.$dbname.' in settings');
static::$databases[$dbname] = new Database($this->settings[$dbname]);
return static::$databases[$dbname];
}
public function tryConnect(string $dbname = null, bool $quiet = false) {
try {
return $this->connect($dbname);
} catch (DatabaseException $e) {
return $quiet ? false : $e;
}
}
public static function get(string $dbname = null){
$dbname = static::parseName($dbname);
if(!static::exists($dbname))
throw new DatabaseException('Can\'t find "'.$dbname.'"');
return static::$databases[$dbname];
}
public function getCreate(string $dbname = null){
if(!static::exists($dbname)){
$this->create($dbname);
}
return static::$databases[static::parseName($dbname)];
}
public static function tryGet(string $dbname = null, bool $quiet = false) {
try {
return static::get($dbname);
} catch (DatabaseException $e) {
return $quiet ? false : $e;
}
}
public function tryGetCreate(string $dbname = null, bool $quiet = false) {
try {
return $this->getCreate($dbname);
} catch (DatabaseException $e) {
return $quiet ? false : $e;
}
}
public static function exists(string $dbname = null){
$dbname = static::parseName($dbname);
return isset(static::$databases[$dbname]);
}
private static function parseName(string $dbname = null){
return $dbname ?: 'default'; //Edit me
}
<?php
namespace Krutush\Database;
/**
* Load a config file to provide a list of pdo instances (Database)
*/
class Connection{
/** @var array */
protected static $databases = array();
/** @var array */
protected $settings;
/** Load settings */
public function __construct(string $path = null){
if(isset($path))
$this->settings = include($path);
}
/** Setup Database */
public function connect(string $dbname = null): Database{
if(static::exists($dbname))
throw new \InvalidArgumentException("Allready connect");
$dbname = static::parseName($dbname);
if(!isset($this->settings[$dbname]))
throw new \InvalidArgumentException('Can\'t find '.$dbname.' in settings');
static::$databases[$dbname] = new Database($this->settings[$dbname]);
return static::$databases[$dbname];
}
/** If you dont remember how to make a try-catch */
public function tryConnect(string $dbname = null, bool $quiet = false) {
try {
return $this->connect($dbname);
} catch (\Exception $e) {
return $quiet ? false : $e;
}
}
public static function get(string $dbname = null){
$dbname = static::parseName($dbname);
if(!static::exists($dbname))
throw new \InvalidArgumentException('Can\'t find "'.$dbname.'"');
return static::$databases[$dbname];
}
public function getCreate(string $dbname = null){
if(!static::exists($dbname)){
$this->create($dbname);
}
return static::$databases[static::parseName($dbname)];
}
public static function tryGet(string $dbname = null, bool $quiet = false) {
try {
return static::get($dbname);
} catch (\Exception $e) {
return $quiet ? false : $e;
}
}
public function tryGetCreate(string $dbname = null, bool $quiet = false) {
try {
return $this->getCreate($dbname);
} catch (\Exception $e) {
return $quiet ? false : $e;
}
}
public static function exists(string $dbname = null){
$dbname = static::parseName($dbname);
return isset(static::$databases[$dbname]);
}
private static function parseName(string $dbname = null){
return $dbname ?: 'default'; //Edit me
}
}

View File

@ -2,11 +2,23 @@
namespace Krutush\Database;
/**
* Extention around PDO
*/
class Database{
/** @var \PDO */
private $pdo;
private $debug = false;
/**
* Requests history if debug == true
*
* @var array
*/
private $requests = [];
/** @var bool */
private $debug = false;
public function __construct(array $settings){
$dns = $settings['driver'] .
':host=' . $settings['host'] .
@ -23,22 +35,29 @@ class Database{
}
public function prepare(string $request){
if($this->debug)
$this->requests[] = $request;
return $this->pdo->prepare($request);
}
public function execute(string $request, array $values = null, $row = false){
if($this->debug)
$time_start = microtime(true);
$req = $this->prepare($request);
$req->execute($values);
if($row == false)
if(!$row)
return $req->fetchAll();
if($this->debug)
$this->requests[] = [
'request' => $request,
'values' => $values,
'fetch' => !$row,
'time' => round((microtime(true) - $time_start) * 1000)
];
return $req;
}
public function select(array $fields = null){
public function select(array $fields = null): Request\Select{
$select = new Request\Select($this);
if(isset($fields))
return $select->fields($fields);
@ -46,7 +65,7 @@ class Database{
return $select;
}
public function insert(array $fields = null){
public function insert(array $fields = null): Request\Insert{
$insert = new Request\Insert($this);
if(isset($fields))
return $insert->fields($fields);
@ -54,7 +73,7 @@ class Database{
return $insert;
}
public function update(array $fields = null){
public function update(array $fields = null): Request\Update{
$update = new Request\Update($this);
if(isset($fields))
return $update->fields($fields);
@ -62,7 +81,7 @@ class Database{
return $update;
}
public function create(string $table = null){
public function create(string $table = null): Request\Create{
$create = new Request\Create($this);
if(isset($table))
return $create->table($table);
@ -70,7 +89,7 @@ class Database{
return $create;
}
public function drop(string $table = null){
public function drop(string $table = null): Request\Drop{
$drop = new Request\Drop($this);
if(isset($table))
return $drop->table($table);
@ -78,7 +97,7 @@ class Database{
return $drop;
}
public function delete(){
public function delete(): Request\Delete{
return new Request\Delete($this);
}
@ -89,5 +108,4 @@ class Database{
public function getRequests(): array{
return $this->requests;
}
//TODO update, delete
}

View File

@ -1,7 +0,0 @@
<?php
namespace Krutush\Database;
use \Exception;
class DatabaseException extends Exception {}

12
src/Migration.php Normal file
View File

@ -0,0 +1,12 @@
<?php
require_once('../../autoload.php');
echo "TODO";
/*
- migrate <file>
- roolback <file>
- new <name>
- create <model>
- status
*/

File diff suppressed because it is too large Load Diff

115
src/ModelID.php Normal file
View File

@ -0,0 +1,115 @@
<?php
namespace Krutush\Database;
use Krutush\Database\Request\Request;
class ModelID extends Model {
/** @var string */
public const ID = null;
/** @var bool */
public const ID_INCLUDE_TABLE = false;
/**
* Get table id name for static::ID or default one
*
* @see static::ID_INCLUDE_TABLE
* @return string
*/
public static function getID(): string{
return static::ID ?? (static::ID_INCLUDE_TABLE ? static::getTable().static::WORD_SEPARATOR : '').'id';
}
public static function getFields(): array{
if(empty(static::FIELDS))
trigger_error('Any data fields');
$fields = static::FIELDS;
$id = static::getID();
$fields[$id] = static::getFieldRawOptions($id);
if(!isset(static::$complete_fields))
static::$complete_fields = static::completeFields($fields);
return static::$complete_fields;
}
/**
* static::FIELDS[$field] with some checks
*
* @param string $field
* @return array options
*/
protected static function getFieldRawOptions(string $field): array{
if($field == static::getID())
return array_merge(
[
'type' => 'int',
'primary' => true,
'not_null' => true,
'custom' => 'AUTO_INCREMENT' //TODO: be smart
],
static::FIELDS[$field] ?? []
);
return parent::getFieldRawOptions($field);
}
/**
* add values to static::getInsert and run it
*
* @param boolean $setID must update id value
*/
public function insert(bool $setID = true){
$res = parent::insert();
if($setID)
$this->{static::getID()} = Connection::get(static::getDatabase())->getLastInsertID();
return $res;
}
/**
* Use static:ID to get row
*
* @param mixed $id int is a good idea
* @param array $loads run static::load
* @return self|null
*/
public static function find($id, array $loads = []): ?self{
return static::first([$id], Request::toParam(static::getID()), $loads);
}
/**
* Same as find but throw exception on null
*
* @param mixed $id int is a good idea
* @param array $loads run static::load
* @return self
*/
public static function findOrFail($id, array $loads = []): self{
return static::firstOrFail([$id], Request::toParam(static::getID()), $loads);
}
/**
* Use static:ID to get rows
*
* @param array $ids array(int) is a good idea
* @param array $loads run static::loads
* @return array
*/
public static function finds(array $ids, array $loads = []): array{
return static::all($ids, Request::inParams(static::getID(), count($ids)), $loads);
}
/**
* Same as find but throw exception on empty
*
* @param array $ids array(int) is a good idea
* @param array $loads run static::loads
* @return array
*/
public static function findsOrFail(array $ids, array $loads = []): array{
return static::allOrFail($ids, Request::inParams(static::getID(), count($ids)), $loads);
}
}

View File

@ -1,97 +1,92 @@
<?php
namespace Krutush\Database\Request;
use Krutush\Database\Database;
use Krutush\Database\DatabaseException;
class Create extends Request{
protected $table;
protected $columns = [];
protected $primary = [];
protected $unique = [];
protected $index = [];
protected $foreign = [];
public function table(string $table): Create{
$this->table = $table;
return $this;
}
public function column(string $name, string $type, int $lenght = null, bool $not_null = false, string $more = null): Create{ //Really ?
$this->columns[] = '`'.$name.'` '.$type.($lenght ? '('.$lenght.')' : '').($not_null ? ' NOT NULL' : '').(isset($more) ? ' '.$more : '');
return $this;
}
public function primary(string $name): Create{
$this->primary[] = '`'.$name.'`';
return $this;
}
public function unique(string $name): Create{
$this->unique[$name] = ['`'.$name.'`'];
return $this;
}
public function uniques(string $name, array $columns): Create{
$this->unique[$name] = [$columns];
return $this;
}
public function index(string $name): Create{
$this->index[$name] = ['`'.$name.'`'];
return $this;
}
public function indexs(string $name, array $columns): Create{
$this->index[$name] = [$columns];
return $this;
}
public function foreign(string $name, string $table, string $column, string $on_delete = null, string $on_update = null): Create{ //TODO: complex foreign
$this->foreign[$name] = compact('name', 'table', 'column', 'on_delete', 'on_update');
return $this;
}
public function sql(){
if(!isset($this->table))
throw new DatabaseException('Any table set');
if(empty($this->columns))
throw new DatabaseException('Any columns set');
$uniques = [];
foreach ($this->unique as $name => $columns) {
$uniques[] = 'CONSTRAINT `UQ_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` UNIQUE ('.implode(', ', $columns).')';
}
$indexs = [];
foreach ($this->index as $name => $columns) {
$indexs[] = 'INDEX `ID_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` ('.implode(', ', $columns).')';
}
$foreigns = [];
foreach ($this->foreign as $name => $options) {
$foreigns[] = 'CONSTRAINT `FK_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` FOREIGN KEY (`'.$options['name'].'`) REFERENCES `'.$options['table'].'` (`'.$options['column'].'`)'.
(isset($options['on_delete']) ? 'ON DELETE '.$options['on_delete'] : '').
(isset($options['on_update']) ? 'ON UPDATE '.$options['on_update'] : '');
}
return 'CREATE TABLE `'.$this->table.'`('."\n".
$sql = implode(",\n",
array_merge(
$this->columns,
(empty($this->primary) ? [] : [
'CONSTRAINT `PK_'.ucfirst(strtolower(strtok($this->table, ' '))).'` PRIMARY KEY ('.implode(', ', $this->primary).')'
]),
$indexs,
$uniques,
$foreigns
)
)."\n)";
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
<?php
namespace Krutush\Database\Request;
use Krutush\Database\Database;
use Krutush\Database\DatabaseException;
class Create extends Request{
protected $table;
protected $columns = [];
protected $primary = [];
protected $unique = [];
protected $index = [];
protected $foreign = [];
public function table(string $table): Create{
$this->table = $table;
return $this;
}
public function column(string $name, string $type, int $lenght = null, bool $not_null = false, string $more = null): Create{
$this->columns[] = compact('name', 'type', 'lenght', 'not_null', 'more');
return $this;
}
public function primary(string $name): Create{
$this->primary[] = $name;
return $this;
}
public function unique(string $name, array $columns = null): Create{
$this->unique[$name] = $columns ?? [$name];
return $this;
}
public function index(string $name, array $columns = null): Create{
$this->index[$name] = $columns ?? [$name];
return $this;
}
public function foreign(string $name, string $table, string $column, string $on_delete = null, string $on_update = null): Create{ //TODO: complex foreign
$this->foreign[$name] = compact('name', 'table', 'column', 'on_delete', 'on_update');
return $this;
}
public function sql(){
if(!isset($this->table))
throw new \UnexpectedValueException('Any table set');
if(empty($this->columns))
throw new \UnexpectedValueException('Any columns set');
$columns = [];
foreach($this->columns as $column){
$columns[] = $column['name'].' '.$column['type'].($column['lenght'] ? '('.$column['lenght'].')' : '').($column['not_null'] ? ' NOT NULL' : '').(isset($column['more']) ? ' '.$column['more'] : '');
}
$uniques = [];
foreach ($this->unique as $name => $columns) {
$uniques[] = 'CONSTRAINT `UQ_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` UNIQUE ('.implode(', ', $columns).')';
}
$indexs = [];
foreach ($this->index as $name => $columns) {
$indexs[] = 'INDEX `ID_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` ('.implode(', ', $columns).')';
}
$foreigns = [];
foreach ($this->foreign as $name => $options) {
$foreigns[] = 'CONSTRAINT `FK_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` FOREIGN KEY (`'.$options['name'].'`) REFERENCES `'.$options['table'].'` (`'.$options['column'].'`)'.
(isset($options['on_delete']) ? 'ON DELETE '.$options['on_delete'] : '').
(isset($options['on_update']) ? 'ON UPDATE '.$options['on_update'] : '');
}
return 'CREATE TABLE '.$this->table.'('."\n".
implode(",\n",
array_merge(
$columns,
(empty($this->primary) ? [] : [
'CONSTRAINT `PK_'.ucfirst(strtolower(strtok($this->table, ' '))).'` PRIMARY KEY ('.implode(', ', $this->primary).')'
]),
$indexs,
$uniques,
$foreigns
)
)."\n)";
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
}

View File

@ -1,21 +1,21 @@
<?php
namespace Krutush\Database\Request;
class Data extends Request{
protected $values;
public function values(array $values, bool $add = false){
if($add){
$this->values = array_merge($this->values, $values);
}else{
$this->values = $values;
}
return $this;
}
public function execute(string $sql, array $values = null){
$values = $values ? ($this->values ? array_merge($this->values, $values) : $values) : $this->values;
return parent::execute($sql, $values);
}
<?php
namespace Krutush\Database\Request;
/** I'm the WHERE */
class Data extends Request{
/** @var array */
protected $values;
public function values(array $values, bool $add = false){
if($add)
$this->values = array_merge($this->values, $values);
else
$this->values = $values;
return $this;
}
public function execute(string $sql, array $values = null){
return parent::execute($sql, $values ? ($this->values ? array_merge($this->values, $values) : $values) : $this->values);
}
}

View File

@ -1,36 +1,42 @@
<?php
namespace Krutush\Database\Request;
//TODO: Split in traits
//TODO: Add INTO
//TODO: Add UNION
use Krutush\Database\DatabaseException;
class Delete extends Data{
protected $table;
protected $where;
public function from(string $table, bool $add = false): Delete{
$this->table = ($add && $this->table ? $this->table.', ' : '').$table;
return $this;
}
public function where(string $where, bool $add = false): Delete{
$this->where = $add && $this->where ? '('.$this->where.') AND ('.$where.')' : $where;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new DatabaseException('Any table set');
$sql = 'DELETE FROM '.$this->table.
($this->where ? ("\n".'WHERE '.$this->where) : '');
return $sql;
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
<?php
namespace Krutush\Database\Request;
//TODO: Split in traits
//TODO: Add INTO
//TODO: Add UNION
use Krutush\Database\DatabaseException;
class Delete extends Data{
protected $table;
protected $where;
public function from(string $table, bool $add = false): Delete{
$this->table = ($add && $this->table ? $this->table.', ' : '').$table;
return $this;
}
/**
* @param string|array $where
* @param boolean $add
* @return Delete
*/
public function where($where, bool $add = false): Delete{
$where = is_array($where) ? $where : [$where];
$this->where = $add && $this->where ? array_merge($this->where, $where) : $where;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new \UnexpectedValueException('Any table set');
$sql = 'DELETE FROM '.$this->table.
($this->where ? ("\n".'WHERE '.static::combineParams($this->where)) : '');
return $sql;
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
}

View File

@ -1,26 +1,26 @@
<?php
namespace Krutush\Database\Request;
use Krutush\Database\Database;
use Krutush\Database\DatabaseException;
class Drop extends Request{
protected $table;
public function table(string $table): Drop{
$this->table = $table;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new DatabaseException('Any table set');
return 'DROP TABLE `'.$this->table.'`';
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
<?php
namespace Krutush\Database\Request;
use Krutush\Database\Database;
use Krutush\Database\DatabaseException;
class Drop extends Request{
protected $table;
public function table(string $table): Drop{
$this->table = $table;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new \UnexpectedValueException('Any table set');
return 'DROP TABLE `'.$this->table.'`';
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
}

View File

@ -1,33 +1,33 @@
<?php
namespace Krutush\Database\Request;
use Krutush\Database\DatabaseException;
class Insert extends Data{
protected $fields;
protected $table;
public function fields(array $fields = null, bool $add = false): Insert{
$this->fields = $add ? array_merge($this->fields, $fields) : $fields;
return $this;
}
public function into(string $table): Insert{
$this->table = $table;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new DatabaseException('Any table set');
return 'INSERT INTO `'.$this->table."`\n".
'('.implode(', ', $this->fields).")\n".
'VALUES ('. str_repeat('?, ', count($this->fields)-1).(count($this->fields) > 0 ? '?' : '').')';
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
<?php
namespace Krutush\Database\Request;
use Krutush\Database\DatabaseException;
class Insert extends Data{
protected $fields;
protected $table;
public function fields(array $fields = null, bool $add = false): Insert{
$this->fields = $add ? array_merge($this->fields, $fields) : $fields;
return $this;
}
public function into(string $table): Insert{
$this->table = $table;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new \UnexpectedValueException('Any table set');
return 'INSERT INTO '.$this->table."\n".
'('.implode(', ', $this->fields).")\n".
'VALUES ('.static::paramList(count($this->fields)).')';
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
}

View File

@ -1,17 +1,42 @@
<?php
namespace Krutush\Database\Request;
use Krutush\Database\Database;
class Request{ //TODO: escape and slugify
protected $db;
public function __construct(Database $db){
$this->db = $db;
}
protected function execute(string $sql, array $values = null){
return $this->db->execute($sql, $values, true);
}
<?php
namespace Krutush\Database\Request;
use Krutush\Database\Database;
/** Base of any SQL request */
class Request{
/** @var Database */
protected $db;
/** Create it */
public function __construct(Database $db){
$this->db = $db;
}
/** Run it */
protected function execute(string $sql, array $values = null){
return $this->db->execute($sql, $values, true);
}
/*=== TOOLS ===*/
public static function toParam(string $name, string $operator = '='): string{
return $name.' '.$operator.' ?';
}
public static function toParams(array $names): string{
return implode(', ', array_map(function($name){ return static::toParam($name); }, $names));
}
public static function paramList(int $count): string{
return implode(',', array_fill(0, $count, '?'));
}
public static function inParams(string $name, $params): string{
return $name.' IN ('.static::paramList(is_int($params) ? $params : count($params)).')';
}
public static function combineParams(array $params, string $operator = ' AND '): string{
return implode($operator, $params);
}
}

View File

@ -1,95 +1,102 @@
<?php
namespace Krutush\Database\Request;
//TODO: Split in traits
//TODO: Add INTO
//TODO: Add UNION
use Krutush\Database\DatabaseException;
class Select extends Data{
protected $fields;
protected $table;
protected $where;
protected $group;
protected $order;
protected $limit;
protected $offset;
protected $joins;
public function fields(array $fields = null, bool $add = false): Select{
$this->fields = $add ? array_merge($this->fields, $fields) : $fields;
return $this;
}
public function from(string $table, bool $add = false): Select{
$this->table = ($add && $this->table ? $this->table.', ' : '').$table;
return $this;
}
public function join(string $joins, string $type = 'INNER', bool $add = false): Select{
if(!in_array($type, array('INNER', 'LEFT', 'RIGHT')))
throw new DatabaseException('Unknown JOIN type');
$this->joins = ($add && $this->joins ? $this->joins."\n" : '').$type.' JOIN '.$joins;
return $this;
}
public function where(string $where, bool $add = false): Select{
$this->where = $add && $this->where ? '('.$this->where.') AND ('.$where.')' : $where;
return $this;
}
public function groupby(string $group): Select{
$this->group = $group;
return $this;
}
public function orderby(string $order): Select{
$this->order = $order;
return $this;
}
public function limit(string $limit): Select{
$this->limit = $limit;
return $this;
}
public function offset(string $offset): Select{
$this->offset = $offset;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new DatabaseException('Any table set');
$fields = '*';
if(isset($this->fields)){
$numItems = count($this->fields);
$i = 0;
$fields = '';
foreach($this->fields as $key => $value){
$fields .= $value;
if(is_string($key))
$fields .= ' '.$key;
if(++$i !== $numItems) //Not last
$fields .= ', ';
}
}
$sql = 'SELECT '.$fields.
"\n".'FROM '.$this->table.
($this->joins ? ("\n".$this->joins) : '').
($this->where ? ("\n".'WHERE '.$this->where) : '').
($this->group ? ("\n".'GROUP BY '.$this->group) : '').
($this->order ? ("\n".'ORDER BY '.$this->order) : '').
($this->limit ? ("\n".'LIMIT '.$this->limit) : '').
($this->offset ? (($this->limit ? '' : "\n".'LIMIT 18446744073709551615').' OFFSET '.$this->offset) : '');
return $sql;
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
<?php
namespace Krutush\Database\Request;
//TODO: Split in traits
//TODO: Add INTO
//TODO: Add UNION
use Krutush\Database\DatabaseException;
class Select extends Data{
/** @var array */
protected $fields;
/** @var string */
protected $table;
/** @var array */
protected $where;
/** @var string */
protected $group;
protected $order;
protected $limit;
protected $offset;
protected $joins;
public function fields(array $fields = null, bool $add = false): Select{
$this->fields = $add ? array_merge($this->fields, $fields) : $fields;
return $this;
}
public function from(string $table, bool $add = false): Select{
$this->table = ($add && $this->table ? $this->table.', ' : '').$table;
return $this;
}
public function join(string $joins, string $type = 'INNER', bool $add = false): Select{
if(!in_array($type, array('INNER', 'LEFT', 'RIGHT')))
throw new \InvalidArgumentException('Unknown JOIN type');
$this->joins = ($add && $this->joins ? $this->joins."\n" : '').$type.' JOIN '.$joins;
return $this;
}
/**
* @param string|array $where
* @param boolean $add
* @return Select
*/
public function where($where, bool $add = false): Select{
$where = is_array($where) ? $where : [$where];
$this->where = $add && $this->where ? array_merge($this->where, $where) : $where;
return $this;
}
public function groupby(string $group): Select{
$this->group = $group;
return $this;
}
public function orderby(string $order): Select{
$this->order = $order;
return $this;
}
public function limit(string $limit): Select{
$this->limit = $limit;
return $this;
}
public function offset(string $offset): Select{
$this->offset = $offset;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new \UnexpectedValueException('Any table set');
$fields = '*';
if(isset($this->fields)){
$lines = [];
foreach($this->fields as $key => $value){
$lines[] = $value.(is_string($key) ? ' '.$key : '');
}
$fields = implode(', ', $lines);
}
$sql = 'SELECT '.$fields.
"\n".'FROM '.$this->table.
($this->joins ? ("\n".$this->joins) : '').
($this->where ? ("\n".'WHERE '.static::combineParams($this->where)) : '').
($this->group ? ("\n".'GROUP BY '.$this->group) : '').
($this->order ? ("\n".'ORDER BY '.$this->order) : '').
($this->limit ? ("\n".'LIMIT '.$this->limit) : '').
($this->offset ? (($this->limit ? '' : "\n".'LIMIT 18446744073709551615').' OFFSET '.$this->offset) : '');
return $sql;
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
}

View File

@ -1,39 +1,51 @@
<?php
namespace Krutush\Database\Request;
use Krutush\Database\DatabaseException;
class Update extends Data{
protected $fields;
protected $table;
protected $where;
public function fields(array $fields = null, bool $add = false): Update{
$this->fields = $add ? array_merge($this->fields, $fields) : $fields;
return $this;
}
public function table(string $table): Update{
$this->table = $table;
return $this;
}
public function where(string $where, bool $add = false): Update{
$this->where = $add && $this->where ? '('.$this->where.') AND ('.$where.')' : $where;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new DatabaseException('Any table set');
return 'UPDATE `'.$this->table."`\n".
'SET '.implode(', ', array_map(function($field){ return $field.' = ?'; }, $this->fields))."\n".
(isset($this->where) ? ('WHERE '.$this->where) : '');
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
<?php
namespace Krutush\Database\Request;
use Krutush\Database\DatabaseException;
/** UPDATE */
class Update extends Data{
/** @var array */
protected $fields;
/** @var string */
protected $table;
/** @var array */
protected $where;
public function fields(array $fields = null, bool $add = false): Update{
$this->fields = $add ? array_merge($this->fields, $fields) : $fields;
return $this;
}
public function table(string $table): Update{
$this->table = $table;
return $this;
}
/**
* @param string|array $where
* @param boolean $add
* @return Update
*/
public function where($where, bool $add = false): Update{
$where = is_array($where) ? $where : [$where];
$this->where = $add && $this->where ? array_merge($this->where, $where) : $where;
return $this;
}
public function sql(){
if(!isset($this->table))
throw new \UnexpectedValueException('Any table set');
return 'UPDATE '.$this->table."\n".
'SET '.static::toParams($this->fields)."\n".
($this->where ? 'WHERE '.static::combineParams($this->where) : '');
}
public function run(array $values = null){
return parent::execute($this->sql(), $values);
}
}

21
src/TypeHelper.php Normal file
View File

@ -0,0 +1,21 @@
<?php
namespace Krutush\Database;
class TypeHelper{
private static function dateTimeConverter(string $format, $value): string{
return (is_a($value, \DateTime::class) ? $value : new \DateTime(strval($value)))->format($format);
}
public static function dateConvert($value): string{
return static::dateTimeConverter('Y-m-d', $value);
}
public static function timeConvert($value): string{
return static::dateTimeConverter('H:i:s', $value);
}
public static function datetimeConvert($value): string{
return static::dateTimeConverter('Y-m-d H:i:s', $value);
}
}