Skip to content

Commit

Permalink
more natural way to have natural keys: can be stored in any field
Browse files Browse the repository at this point in the history
  • Loading branch information
Magomogo committed Sep 27, 2013
1 parent 3d30229 commit 6c48eca
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 38 deletions.
2 changes: 1 addition & 1 deletion lib/Magomogo/Persisted/AbstractProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function id($container)
$this->idInContainer[get_class($container)] : null;
}

public function naturalKey()
public function naturalKeyFieldName()
{
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Magomogo/Persisted/Container/CouchDb.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public function saveProperties($properties)
$doc = array_merge_recursive($doc, $existingDoc);
$this->client->putDocument($doc, $properties->id($this));
} else {
if (!is_null($properties->naturalKey())) {
$doc['_id'] = $properties->naturalKey();
if (!is_null($properties->naturalKeyFieldName())) {
$doc['_id'] = $properties->{$properties->naturalKeyFieldName()};
}
list($id, $rev) = $this->client->postDocument($doc);
$properties->persisted($id, $this);
Expand Down
7 changes: 6 additions & 1 deletion lib/Magomogo/Persisted/Container/Memory.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,13 @@ public function deleteProperties($properties)
*/
private function notifyOnPersistence($properties)
{
$id = $properties->id($this) ?: $properties->naturalKey() ?: self::$autoincrement++;
if (is_null($properties->naturalKeyFieldName())) {
$id = $properties->id($this) ?: self::$autoincrement++;
} else {
$id = $properties->{$properties->naturalKeyFieldName()};
}
$properties->persisted($id, $this);

return $properties;
}

Expand Down
16 changes: 14 additions & 2 deletions lib/Magomogo/Persisted/Container/SqlDb.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Magomogo\Persisted\PossessionInterface;
use Magomogo\Persisted\AbstractProperties;
use Magomogo\Persisted\Exception;
use Magomogo\Persisted\PropertiesInterface;

class SqlDb implements ContainerInterface
{
Expand Down Expand Up @@ -130,7 +131,7 @@ private function begin($properties)

$row = $this->db->fetchAssoc(
'SELECT * FROM ' . $this->db->quoteIdentifier($this->names->propertiesToName($properties))
. ' WHERE id=?',
. ' WHERE ' . $this->db->quoteIdentifier(($properties->naturalKeyFieldName() ?: 'id')) . '=?',
array($properties->id($this))
);

Expand All @@ -153,7 +154,7 @@ private function commit(array $row, $properties)

if (!$properties->id($this)) {
$this->db->insert($this->db->quoteIdentifier($tableName), $row);
$properties->persisted($properties->naturalKey() ?: $this->db->lastInsertId($tableName . '_id_seq'), $this);
$properties->persisted($this->defineNewId($properties, $tableName), $this);
} else {
$this->db->update($this->db->quoteIdentifier($tableName), $row, array('id' => $properties->id($this)));
}
Expand Down Expand Up @@ -265,4 +266,15 @@ private function foreignKeys($references)

return $keys;
}

/**
* @param PropertiesInterface $properties
* @param string $tableName
* @return string
*/
private function defineNewId($properties, $tableName)
{
return $properties->naturalKeyFieldName() ?
$properties->{$properties->naturalKeyFieldName()} : $this->db->lastInsertId($tableName . '_id_seq');
}
}
37 changes: 19 additions & 18 deletions lib/Magomogo/Persisted/Container/SqlDb/SchemaCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function($items) use ($properties, $collection, $creator) {

}

$properties->persisted($tableName, $this);
$properties->persisted($properties, $this);
return $properties;
}

Expand All @@ -99,10 +99,12 @@ public function many2manySchema($collection, $leftProperties, array $manyPropert
$rightProperties = reset($manyProperties);
$table = new Table($this->quoteIdentifier($referenceName));
$this->addForeignReferenceColumn(
$table, $this->names->propertiesToName($leftProperties), $leftProperties
$table, $this->names->propertiesToName($leftProperties), $leftProperties,
array('onUpdate' => 'CASCADE', 'onDelete' => 'CASCADE')
);
$this->addForeignReferenceColumn(
$table, $this->names->propertiesToName($rightProperties), $rightProperties
$table, $this->names->propertiesToName($rightProperties), $rightProperties,
array('onUpdate' => 'CASCADE', 'onDelete' => 'CASCADE')
);
$this->manager->createTable($table);
}
Expand All @@ -126,12 +128,10 @@ private function defineSchemaForField($table, $fieldName, $fieldValue) {
if (is_string($fieldValue)) {
$table->addColumn($this->quoteIdentifier($fieldName), 'text', array('notNull' => false));
} elseif ($fieldValue instanceof ModelInterface) {
$table->addColumn($this->quoteIdentifier($fieldName), 'integer', array('unsigned' => true, 'notNull' => false));
$relatedTable = $fieldValue->save($this);
$table->addForeignKeyConstraint(
$this->quoteIdentifier($relatedTable),
array($this->quoteIdentifier($fieldName)),
array('id'),
$this->addForeignReferenceColumn(
$table,
$fieldName,
$fieldValue->save($this),
array('onUpdate' => 'RESTRICT', 'onDelete' => 'SET NULL')
);
} elseif ($fieldValue instanceof \DateTime) {
Expand All @@ -150,23 +150,24 @@ private function newTableObject($properties, $tableName)
{
$table = new Table($this->quoteIdentifier($tableName));

if (!isset($properties->id)) {
if (is_null($properties->naturalKeyFieldName())) {
$table->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => true));
}

foreach ($properties as $name => $value) {
if (($name === 'id') && is_string($value)) {
$table->addColumn('id', 'string', array('length' => 255, 'notnull' => true));
if ($properties->naturalKeyFieldName() === $name) {
$table->addColumn($name, 'string', array('length' => 255, 'notnull' => true));
} else {
$this->defineSchemaForField($table, $name, $value);
}
}

$table->setPrimaryKey(array('id'));
$table->setPrimaryKey(array($properties->naturalKeyFieldName() ?: 'id'));

if ($properties instanceof PossessionInterface) {
foreach ($properties->foreign() as $propertyName => $foreignProperties) {
$this->addForeignReferenceColumn($table, $propertyName, $foreignProperties);
$this->addForeignReferenceColumn($table, $propertyName, $foreignProperties,
array('onUpdate' => 'CASCADE', 'onDelete' => 'CASCADE'));
}
}

Expand All @@ -178,9 +179,9 @@ private function newTableObject($properties, $tableName)
* @param string $columnName
* @param AbstractProperties $leftProperties
*/
private function addForeignReferenceColumn($table, $columnName, $leftProperties)
private function addForeignReferenceColumn($table, $columnName, $leftProperties, $options)
{
if ($leftProperties->naturalKey() && is_string($leftProperties->naturalKey())) {
if ($leftProperties->naturalKeyFieldName()) {
$table->addColumn($this->quoteIdentifier($columnName), 'string', array('length' => 255, 'notnull' => false));
} else {
$table->addColumn(
Expand All @@ -192,8 +193,8 @@ private function addForeignReferenceColumn($table, $columnName, $leftProperties)
$table->addForeignKeyConstraint(
$this->quoteIdentifier($this->names->propertiesToName($leftProperties)),
array($this->quoteIdentifier($columnName)),
array('id'),
array('onUpdate' => 'CASCADE', 'onDelete' => 'CASCADE')
array($leftProperties->naturalKeyFieldName() ?: 'id'),
$options
);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/Magomogo/Persisted/PropertiesInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ interface PropertiesInterface
public function id($container);

/**
* Optionally defines natural key value
* null value forces container to set its artificial identifier
* Optionally defines natural key
* null value forces container to use its specific artificial identifier
*
* @return mixed
* @return string|null
*/
public function naturalKey();
public function naturalKeyFieldName();

/**
* The message. A container stored properties giving particular identifier
Expand Down
8 changes: 6 additions & 2 deletions test/Keymarker/PropertiesTest.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<?php
namespace Magomogo\Persisted\Test\Keymarker;

use Magomogo\Persisted\Container\Memory;

class PropertiesTest extends \PHPUnit_Framework_TestCase
{
public function testHasNaturalId()
{
$properties = new Properties(array('id' => 'Natural'));
$this->assertEquals('Natural', $properties->naturalKey());
$properties = new Properties(array('name' => 'Natural'));
$container = new Memory();
$container->saveProperties($properties);
$this->assertEquals('Natural', $properties->id($container));
}
}
2 changes: 1 addition & 1 deletion test/ModelsPersistencyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private static function employeeModel($container)
$company = ObjectMother\Company::xiag();
$company->save($container);

$keymarker = new Keymarker\Model(new Keymarker\Properties(array('id' => 'test')));
$keymarker = new Keymarker\Model(new Keymarker\Properties(array('name' => 'test')));
$keymarker->save($container);

return new Employee\Model(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public function propertiesOperation($function)
parent::propertiesOperation($function);

$indexedItems = array();
/** @var Properties $property */
foreach ($this->items as $property) {
$indexedItems[$property->id] = $property;
$indexedItems[$property->name] = $property;
}
$this->items = $indexedItems;
}
Expand Down
2 changes: 1 addition & 1 deletion test/_classes/Magomogo/Persisted/Test/Keymarker/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function __construct($properties)

public function __toString()
{
return $this->properties->id;
return $this->properties->name;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ class Properties extends AbstractProperties
protected function properties()
{
return array(
'id' => '',
'name' => '',
'created' => new \DateTime(date('c'))
);
}

public function naturalKey()
public function naturalKeyFieldName()
{
return $this->id;
return 'name';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ class Keymarker
public static function friend()
{
return new Model(
new Properties(array('id' => 'Friend', 'created' => new \DateTime('2012-12-08T10:16+07:00')))
new Properties(array('name' => 'Friend', 'created' => new \DateTime('2012-12-08T10:16+07:00')))
);
}

public static function IT()
{
return new Model(
new Properties(array('id' => 'IT', 'created' => new \DateTime('2012-12-08T10:36+07:00')))
new Properties(array('name' => 'IT', 'created' => new \DateTime('2012-12-08T10:36+07:00')))
);
}

Expand Down

0 comments on commit 6c48eca

Please sign in to comment.