Rework a bit
This commit is contained in:
parent
54fd0bd6ff
commit
acd024998b
|
@ -8,8 +8,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"krutush/krutush": "dev-develop",
|
"krutush/krutush": "dev-develop"
|
||||||
"sheychen/inutils": "^1.1"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
@ -39,5 +39,13 @@ class Database{
|
||||||
|
|
||||||
return $select;
|
return $select;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function create(string $table = null){
|
||||||
|
$create = new Request\Create($this);
|
||||||
|
if(isset($table))
|
||||||
|
return $create->table($table);
|
||||||
|
|
||||||
|
return $create;
|
||||||
|
}
|
||||||
//TODO insert, update, delete
|
//TODO insert, update, delete
|
||||||
}
|
}
|
336
src/Model.php
336
src/Model.php
|
@ -2,192 +2,256 @@
|
||||||
|
|
||||||
namespace Krutush\Database;
|
namespace Krutush\Database;
|
||||||
|
|
||||||
use Inutils\Storage\Container;
|
use Krutush\Database\DatabaseException;
|
||||||
|
|
||||||
//TODO extends
|
//TODO extends
|
||||||
//TODO protected to const php7
|
|
||||||
//TODO add model links
|
//TODO add model links
|
||||||
|
|
||||||
class Model extends Container{
|
class Model{
|
||||||
protected static $DATABASE = null;
|
/** @var string */
|
||||||
protected static $TABLE = null;
|
public const DATABASE = null;
|
||||||
protected static $FIELDS = null;
|
|
||||||
protected static $ID = null;
|
|
||||||
protected static $REF = null;
|
|
||||||
protected static $FILTER = null;
|
|
||||||
protected static $INNER = null;
|
|
||||||
protected static $ORDER = null;
|
|
||||||
|
|
||||||
protected $modify = false;
|
/** @var string */
|
||||||
|
public const TABLE = null;
|
||||||
|
|
||||||
public function __set(string $key, $value){
|
/** @var array
|
||||||
//TODO Check format
|
* @example ['id' => ['column' => 'idColumn', 'type' => 'int', 'not_null' => true, 'primary' => true, 'custom' => 'AUTO_INCREMENT']] */
|
||||||
$this->modify = true;
|
public const FIELDS = [];
|
||||||
parent::__set($key, $value);
|
|
||||||
|
/** @var array
|
||||||
|
* @example ['id' => ['value' => 1, 'modified' => false]] */
|
||||||
|
protected $fields = [];
|
||||||
|
|
||||||
|
public const FILTER = null;
|
||||||
|
public const INNER = null; //TODO: Manager OneToOne, OneToMany, ...
|
||||||
|
public const ORDER = null;
|
||||||
|
|
||||||
|
|
||||||
|
/*=== MAGIC ===*/
|
||||||
|
public function __construct(array $data = [], bool $useColumns = false){
|
||||||
|
foreach (static::getFields() as $field => $options) {
|
||||||
|
$column = $useColumns ? static::getColumn($field) : $field;
|
||||||
|
$value = static::convertField(isset($data[$column]) ? $data[$column] : null, $field);
|
||||||
|
$this->fields[$field] = [
|
||||||
|
'value' => $value,
|
||||||
|
'modified' => false
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*=== CREATE ===*/
|
//MAYBE: Save on destroy
|
||||||
|
|
||||||
public static function fromRow($row, $all = true, $exception = true){
|
public function __get(string $field){
|
||||||
|
if(array_key_exists($field, $this->fields))
|
||||||
|
return $this->fields[$field]['value'];
|
||||||
|
|
||||||
|
$trace = debug_backtrace();
|
||||||
|
trigger_error(
|
||||||
|
'Propriété non-définie via __get() : ' . $field .
|
||||||
|
' dans ' . $trace[0]['file'] .
|
||||||
|
' à la ligne ' . $trace[0]['line'],
|
||||||
|
E_USER_NOTICE);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __set(string $field, $value){
|
||||||
|
if(array_key_exists($field, static::FIELDS)){
|
||||||
|
$this->fields[$field] = [
|
||||||
|
'value' => static::convertField($value, $field),
|
||||||
|
'modified' => true
|
||||||
|
];
|
||||||
|
}else{
|
||||||
|
$trace = debug_backtrace();
|
||||||
|
trigger_error(
|
||||||
|
'Propriété non-définie via __set() : ' . $field .
|
||||||
|
' dans ' . $trace[0]['file'] .
|
||||||
|
' à la ligne ' . $trace[0]['line'],
|
||||||
|
E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*=== CREATE ===*/
|
||||||
|
public static function fromRow(\PDOStatement $row, bool $exception = true): ?self{
|
||||||
if($row->rowCount() < 1){
|
if($row->rowCount() < 1){
|
||||||
if($exception)
|
if($exception)
|
||||||
throw new \Exception('Create from Any Row');
|
throw new \Exception('Create from Any Row');
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($all){
|
$data = $row->fetch();
|
||||||
$res = array();
|
return new static($data, true);
|
||||||
while($data = $row->fetch()){
|
|
||||||
$res[] = new static($data);
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}else{
|
|
||||||
$data = $row->fetch();
|
|
||||||
return new static($data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fromData($data){
|
public static function fromRowAll(\PDOStatement $row, bool $exception = true): array{
|
||||||
|
if($row->rowCount() < 1){
|
||||||
|
if($exception)
|
||||||
|
throw new \Exception('Create from Any Row');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
$res = array();
|
$res = array();
|
||||||
foreach($data as $element){
|
while($data = $row->fetch()){
|
||||||
$res[] = new static($element);
|
$res[] = new static($data, true);
|
||||||
}
|
}
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function fromData($data, bool $useColumns = false): array{
|
||||||
|
$res = array();
|
||||||
|
foreach($data as $element){
|
||||||
|
$res[] = new static($element, $useColumns);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*=== CONST ===*/
|
/*=== CONST ===*/
|
||||||
|
public static function getFields(bool $exception = false): array{
|
||||||
public static function getFields($exception = false){
|
if(empty(static::$FIELDS) && $exception)
|
||||||
if(!isset(static::$FIELDS)){
|
throw new DatabaseException('FIELDS not set');
|
||||||
if($exception)
|
|
||||||
throw new \Exception('FIELDS not set');
|
return static::FIELDS;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static::$FIELDS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getField($alias){
|
public static function getOptions(string $field): array{
|
||||||
$fields = static::getFields();
|
$fields = static::getFields();
|
||||||
if(!isset($fields[$alias]))
|
if(!isset($fields[$field]))
|
||||||
throw new \Exception('Can\'t find alias : '.$alias);
|
throw new DatabaseException('Can\'t find field : '.$field);
|
||||||
|
|
||||||
return $fields[$alias];
|
return $fields[$field];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getID($real = true){
|
public static function getColumn(string $field): string{
|
||||||
if(static::$ID == null){
|
$options = static::getOptions($field);
|
||||||
if($real)
|
return isset($options['column']) ? $options['column'] : $field;
|
||||||
return static::getField('ID');
|
}
|
||||||
|
|
||||||
throw new \Exception('ID not set');
|
public static function getColumns(bool $sql = true): array{
|
||||||
|
$fields = static::getFields();
|
||||||
|
$columns = [];
|
||||||
|
foreach ($fields as $field => $options) {
|
||||||
|
$column = static::getColumn($field);
|
||||||
|
$columns[] = $sql ? '`'.static::TABLE.'`.`'.$column.'`' : $column;
|
||||||
|
}
|
||||||
|
return $columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function convertField($data, $field){
|
||||||
|
$options = static::getOptions($field);
|
||||||
|
if(isset($options['type'])){
|
||||||
|
switch(strtolower($options['type'])){
|
||||||
|
case 'int':
|
||||||
|
$data = intval($data); //MAYBE: E_NOTICE on strange types
|
||||||
|
break;
|
||||||
|
case 'char':
|
||||||
|
case 'varchar':
|
||||||
|
case 'text':
|
||||||
|
$data = strval($data); //MAYBE: E_NOTICE on strange types
|
||||||
|
if(isset($options['lenght']) && strlen($data) > $options['lenght'])
|
||||||
|
throw new DatabaseException('data is to long in field : '.$field);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new DatabaseException('unknown type in field : '.$field);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $real == true ? static::getField(static::$ID) : static::$ID;
|
if(is_null($data) && isset($options['not_null']) && $options['not_null'] == true)
|
||||||
|
throw new DatabaseException('Can\'t set null to NOT NULL field : '.$field);
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getREF($real = true){
|
|
||||||
if(static::$REF == null){
|
|
||||||
if($real)
|
|
||||||
return static::getField('REF');
|
|
||||||
|
|
||||||
throw new \Exception('REF not set');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $real == true ? static::getField(static::$REF) : static::$REF;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getDATABASE(){
|
|
||||||
return isset(static::$DATABASE) ? static::$DATABASE : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=== QUERIES ===*/
|
/*=== QUERIES ===*/
|
||||||
|
public static function select(): Request\Select{
|
||||||
|
$req = Connection::get(static::DATABASE)
|
||||||
|
->select(static::getColumns())
|
||||||
|
->from(static::TABLE);
|
||||||
|
|
||||||
public static function prepare(){
|
if(static::INNER != null)
|
||||||
$req = Connection::get(static::getDATABASE())
|
$req = $req->join(static::INNER);
|
||||||
->select(static::getFields())
|
|
||||||
->from(static::$TABLE);
|
|
||||||
|
|
||||||
if(isset(static::$INNER))
|
if(static::FILTER != null)
|
||||||
$req = $req->join(static::$INNER);
|
$req = $req->where(static::FILTER);
|
||||||
|
|
||||||
if(isset(static::$FILTER))
|
if(static::ORDER != null)
|
||||||
$req = $req->where(static::$FILTER);
|
$req = $req->orderby(static::ORDER);
|
||||||
|
|
||||||
if(isset(static::$ORDER))
|
return static::prepare($req);
|
||||||
$req = $req->orderby(static::$ORDER);
|
|
||||||
|
|
||||||
return static::postPrepare($req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function postPrepare($req){ return $req; }
|
public static function create(): Request\Create{
|
||||||
|
$req = Connection::get(static::DATABASE)
|
||||||
|
->create(static::TABLE);
|
||||||
|
|
||||||
public static function row(array $values = null, $filters = null){
|
foreach (static::getFields() as $field => $options) {
|
||||||
$req = static::prepare();
|
$req->column(
|
||||||
|
static::getColumn($field),
|
||||||
|
$options['type'],
|
||||||
|
isset($options['lenght']) ? $options['lenght'] : null,
|
||||||
|
isset($options['not_null']) && $options['not_null'],
|
||||||
|
isset($options['primary']) && $options['primary'],
|
||||||
|
isset($options['custom']) ? $options['custom'] : null);
|
||||||
|
}
|
||||||
|
|
||||||
if(isset($filters))
|
return $req;
|
||||||
$req = $req->where($filters, true);
|
}
|
||||||
|
|
||||||
|
/* Do advanced customuzation here */
|
||||||
|
protected static function prepare($req){ return $req; }
|
||||||
|
|
||||||
|
public static function runSelect(array $values = null, string $where = null){
|
||||||
|
$req = static::select();
|
||||||
|
|
||||||
|
if(isset($where))
|
||||||
|
$req = $req->where($where, true);
|
||||||
|
|
||||||
return $req->run($values);
|
return $req->run($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function first(array $values = null, string $where = null): ?self{
|
||||||
|
return static::fromRow(static::runSelect($values, $where), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function firstOrFail(array $values = null, string $where = null): ?self{
|
||||||
|
return static::fromRow(static::runSelect($values, $where));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function all(array $values = null, string $where = null): array{
|
||||||
|
return static::fromRowAll(static::runSelect($values, $where), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function allOrFail(array $values = null, string $where = null): array{
|
||||||
|
return static::fromRowAll(static::runSelect($values, $where));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function exists(array $values = null, string $where = null): bool{
|
||||||
|
return static::first($values, $where) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function count(array $values = null, string $where = null): int{
|
||||||
|
$req = static::select();
|
||||||
|
$req->fields(['COUNT(*) as count']);
|
||||||
|
|
||||||
|
if(isset($where))
|
||||||
|
$req = $req->where($where, true);
|
||||||
|
|
||||||
|
$data = $req->run($values)->fetch();
|
||||||
|
if(!isset($data['count']))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return $data['count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: Manager ids
|
||||||
public static function find($id) {
|
public static function find($id) {
|
||||||
return static::first(array($id), (static::getID().' = ?'));
|
return static::first(array($id), (static::getID().' = ?'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function findOrFail($id) {
|
public static function findOrFail($id) {
|
||||||
return static::firstOrFail(array($id), (static::getID().' = ?'));
|
return static::firstOrFail(array($id), (static::getID().' = ?'));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public static function first(array $values = null, $filters = null) {
|
|
||||||
return static::fromRow(static::row($values, $filters), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function firstOrFail(array $values = null, $filters = null) {
|
|
||||||
return static::fromRow(static::row($values, $filters), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function all(array $values = null, $filters = null) {
|
|
||||||
return static::fromRow(static::row($values, $filters), true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function allOrFail(array $values = null, $filters = null) {
|
|
||||||
return static::fromRow(static::row($values, $filters));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function byRef($ref){
|
|
||||||
return static::first(array($ref), (static::getREF().' = ?'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function byRefOrFail($ref){
|
|
||||||
return static::firstOrFail(array($ref), (static::getREF().' = ?'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function resolveID($ref, $exception = false) {
|
|
||||||
$res = static::fromRow(static::row(array($ref), (static::getREF().' = ?')), false, $exception);
|
|
||||||
if(!isset($res))
|
|
||||||
return;
|
|
||||||
|
|
||||||
$id = static::getID(false);
|
|
||||||
return $res->$id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function exists(array $values = null, $filters = null){
|
|
||||||
return static::first($values, $filters) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO clean
|
|
||||||
public static function count(array $values = null, $filters = null){
|
|
||||||
$req = static::prepare();
|
|
||||||
$req = $req->fields(array('COUNT(*)'));
|
|
||||||
|
|
||||||
if(isset($filters))
|
|
||||||
$req = $req->where($filters, true);
|
|
||||||
|
|
||||||
$data = $req->run($values)->fetch();
|
|
||||||
if(!isset($data['COUNT(*)']))
|
|
||||||
return;
|
|
||||||
|
|
||||||
return $data['COUNT(*)'];
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Krutush\Database\Request;
|
||||||
|
|
||||||
|
use Krutush\Database\Database;
|
||||||
|
use Krutush\Database\DatabaseException;
|
||||||
|
|
||||||
|
class Create extends Request{
|
||||||
|
protected $table;
|
||||||
|
protected $columns = [];
|
||||||
|
protected $primary = [];
|
||||||
|
|
||||||
|
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, bool $primary = false, string $more = null): Create{
|
||||||
|
$this->columns[] = '`'.$name.'` '.$type.($lenght ? '('.$lenght.')' : '').($not_null ? ' NOT NULL' : '').(isset($more) ? ' '.$more : '');
|
||||||
|
if($primary)
|
||||||
|
$this->primary[] = '`'.$name.'`';
|
||||||
|
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');
|
||||||
|
|
||||||
|
return 'CREATE `'.$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).')'
|
||||||
|
]))
|
||||||
|
)."\n)";
|
||||||
|
|
||||||
|
//TODO: foreign keys
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(array $values = null){
|
||||||
|
return parent::execute($this->sql(), $values);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue