Skip to content

Commit

Permalink
CREATE TABLE query generation from models.
Browse files Browse the repository at this point in the history
  • Loading branch information
martywallace committed Nov 30, 2017
1 parent b99ada6 commit e55fe9e
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 47 deletions.
36 changes: 14 additions & 22 deletions src/Tempest/Database/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public static function json() {
*/
public static function enum(array $set) {
$field = new static(static::ENUM);
$field->setSet($set);
$field->setEnumerable($set);

return $field;
}
Expand All @@ -100,6 +100,7 @@ public static function enum(array $set) {
*/
protected function __construct($type) {
$this->setType($type);

parent::__construct($this->getName(), $this);
}

Expand All @@ -110,20 +111,17 @@ protected function __construct($type) {
*
* @return $this
*/
public function default($value) {
$this->setDefault($value);

return $this;
public function setDefault($value) {
return $this->setDefaultInternally($value);
}

/**
* Adds a primary key index to this field.
*
* @return $this
*/
public function primary() {
$this->addIndex(Index::PRIMARY);
return $this;
public function setPrimary() {
return $this->addIndexInternally(Index::PRIMARY)->setNotNullable();
}

/**
Expand All @@ -133,9 +131,8 @@ public function primary() {
*
* @return $this
*/
public function unique($name = null) {
$this->addIndex(Index::UNIQUE, $name);
return $this;
public function addUniqueKey($name = null) {
return $this->addIndexInternally(Index::UNIQUE, $name);
}

/**
Expand All @@ -145,31 +142,26 @@ public function unique($name = null) {
*
* @return $this
*/
public function index($name = null) {
$this->addIndex(Index::INDEX, $name);
return $this;
public function addIndex($name = null) {
return $this->addIndexInternally(Index::INDEX, $name);
}

/**
* Marks this field as auto-incrementing. This also adds a primary key index to this field.
*
* @return $this
*/
public function increments() {
$this->setAutoIncrement(true);
$this->addIndex(Index::PRIMARY);

return $this;
public function setAutoIncrements() {
return $this->setAutoIncrementsInternally()->setPrimary();
}

/**
* Marks this field as non-nullable.
*
* @return $this
*/
public function notNullable() {
$this->setNullable(false);
return $this;
public function setNotNullable() {
return $this->setNullableInternally(false);
}

/**
Expand Down
37 changes: 36 additions & 1 deletion src/Tempest/Database/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Tempest\App;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Doctrine\Common\Inflector\Inflector;
use Tempest\Events\ModelEvent;

/**
* A database model, derived from a {@link Row}.
Expand All @@ -26,6 +27,34 @@ public static function getTable() {
return static::table();
}

/**
* Gets a generated CREATE TABLE query for this model.
*
* @return string
*/
public static function getCreateTableQuery() {
$content = [];

foreach (static::getFields() as $field) {
$content[] = trim(implode(' ', [
'`' . $field->getName() . '`',
$field->getColumnType(),
$field->getNullable() ? 'DEFAULT NULL' : 'NOT NULL',
$field->getAutoIncrements() ? 'AUTO_INCREMENT' : ''
]));
}

if (!empty(static::getPrimaryFields())) {
$names = array_map(function(SealedField $field) {
return '`' . $field->getName() . '`';
}, static::getPrimaryFields());

$content[] = 'PRIMARY KEY(' . implode(', ', $names) . ')';
}

return 'CREATE TABLE `' . static::getTable() . '` (' . PHP_EOL . ' ' . implode(',' . PHP_EOL . ' ', $content) . PHP_EOL . ');';
}

/**
* Retrieve all declared fields for this model.
*
Expand Down Expand Up @@ -107,7 +136,7 @@ public static function getNonUniqueFields() {
*/
public static function getIncrementingField() {
foreach (static::getFields() as $field) {
if ($field->getAutoIncrement()) return $field;
if ($field->getAutoIncrements()) return $field;
}

return null;
Expand Down Expand Up @@ -307,6 +336,8 @@ public function reset() {
$this->setFieldValue($name, $field->getDefault());
}

$this->dispatch(ModelEvent::RESET, new ModelEvent($this));

return $this;
}

Expand Down Expand Up @@ -431,6 +462,8 @@ public function getPrimaryKey() {
* @param bool $updateOnDuplicate Whether or not to update a matching duplicate record if one was found.
*/
public function save($updateOnDuplicate = true) {
$this->dispatch(ModelEvent::BEFORE_SAVE, new ModelEvent($this));

$query = static::insert($this->_data);

if ($updateOnDuplicate) {
Expand All @@ -448,6 +481,8 @@ public function save($updateOnDuplicate = true) {
$this->setFieldValue($incrementing->getName(), App::get()->db->getLastInsertId());
}
}

$this->dispatch(ModelEvent::AFTER_SAVE, new ModelEvent($this));
}

public function jsonSerialize() {
Expand Down
8 changes: 4 additions & 4 deletions src/Tempest/Database/Models/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ class Session extends Model {

protected static function fields() {
return [
'id' => Field::string()->primary(),
'created' => Field::dateTime()->default('now'),
'updated' => Field::dateTime()->default('now'),
'id' => Field::string()->setAutoIncrements(),
'created' => Field::dateTime()->setDefault('now'),
'updated' => Field::dateTime()->setDefault('now'),
'ip' => Field::string(),
'data' => Field::text()
'data' => Field::text()->setNotNullable()
];
}

Expand Down
87 changes: 67 additions & 20 deletions src/Tempest/Database/SealedField.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SealedField {
private $_type;

/** @var bool */
private $_autoIncrement = false;
private $_autoIncrements = false;

/** @var mixed */
private $_default = null;
Expand All @@ -27,16 +27,16 @@ class SealedField {
private $_indexes = [];

/** @var string[] */
private $_set = null;
private $_enumerable = null;

protected function __construct($name, Field $field) {
$this->_name = $name;
$this->_type = $field->getType();
$this->_autoIncrement = $field->getAutoIncrement();
$this->_autoIncrements = $field->getAutoIncrements();
$this->_default = $field->getDefault();
$this->_nullable = $field->getNullable();
$this->_indexes = $field->getIndexes();
$this->_set = $field->getSet();
$this->_enumerable = $field->getEnumerable();
}

/**
Expand All @@ -54,7 +54,7 @@ public function toRaw($value) {
break;

case Field::ENUM:
if (in_array($value, $this->getSet())) return strval($value);
if (in_array($value, $this->getEnumerable())) return strval($value);
return null;
break;

Expand Down Expand Up @@ -112,7 +112,7 @@ public function toRefined($value) {
break;

case Field::ENUM:
if (in_array($value, $this->getSet())) return strval($value);
if (in_array($value, $this->getEnumerable())) return strval($value);
return null;
break;

Expand Down Expand Up @@ -206,9 +206,12 @@ public function getType() {
* Set the field type.
*
* @param string $value The type.
*
* @return $this
*/
protected function setType($value) {
$this->_type = $value;
return $this;
}

/**
Expand All @@ -224,27 +227,31 @@ public function getDefault() {
* Sets the default value for this field.
*
* @param mixed $value The value.
*
* @return $this
*/
protected function setDefault($value) {
protected function setDefaultInternally($value) {
$this->_default = $value;
return $this;
}

/**
* Whether or not this field auto-increments.
*
* @return bool
*/
public function getAutoIncrement() {
return $this->_autoIncrement;
public function getAutoIncrements() {
return $this->_autoIncrements;
}

/**
* Sets whether this field auto-increments or not.
* Sets this field to be auto-incrementing.
*
* @param bool $value The value.
* @return $this
*/
protected function setAutoIncrement($value) {
$this->_autoIncrement = $value;
protected function setAutoIncrementsInternally() {
$this->_autoIncrements = true;
return $this;
}

/**
Expand All @@ -260,9 +267,12 @@ public function getNullable() {
* Sets whether or not this field is nullable.
*
* @param bool $value The value.
*
* @return $this
*/
protected function setNullable($value) {
protected function setNullableInternally($value) {
$this->_nullable = $value;
return $this;
}

/**
Expand All @@ -279,41 +289,51 @@ public function getIndexes() {
*
* @param string $type The index type.
* @param string $name The index name.
*
* @return $this
*/
protected function addIndex($type, $name = null) {
protected function addIndexInternally($type, $name = null) {
if ($type === Index::PRIMARY && $this->hasPrimaryIndex()) {
// Only one primary key.
return;
return $this;
}

$this->_indexes[] = new Index($type, $name);

return $this;
}

/**
* Sets the indexes added to this field.
*
* @param array $indexes The indexes to set.
*
* @return $this
*/
protected function setIndexes(array $indexes) {
$this->_indexes = $indexes;
return $this;
}

/**
* Gets the enum set for this field if it is an enum.
*
* @return string[]
*/
public function getSet() {
return $this->_set;
public function getEnumerable() {
return $this->_enumerable;
}

/**
* Sets the enum set.
*
* @param string[] $set The enum set.
*
* @return $this
*/
protected function setSet(array $set) {
$this->_set = $set;
protected function setEnumerable(array $set) {
$this->_enumerable = $set;
return $this;
}

/**
Expand Down Expand Up @@ -353,4 +373,31 @@ public function hasIndex() {
return count($this->_indexes) > 0;
}

/**
* Get the MySQL column type related to this field.
*
* @return string
*/
public function getColumnType() {
switch ($this->getType()) {
default: return 'VARCHAR(255)'; break;

case Field::INT: return 'INT(10) UNSIGNED'; break;
case Field::STRING: return 'VARCHAR(255)'; break;
case Field::DATETIME: return 'DATETIME'; break;
case Field::BOOL: return 'TINYINT(1)'; break;
case Field::TEXT: return 'TEXT'; break;
case Field::DECIMAL: return 'DECIMAL(10, 2)'; break;
case Field::JSON: return 'TEXT'; break;

case Field::ENUM:
$enumerable = array_map(function($enum) {
return "'$enum'";
}, $this->getEnumerable());

return 'ENUM(' . implode(', ', $enumerable) . ')';
break;
}
}

}
Loading

0 comments on commit e55fe9e

Please sign in to comment.