Skip to content

Commit

Permalink
allow to relate a table with itself
Browse files Browse the repository at this point in the history
  • Loading branch information
oscarotero committed Aug 29, 2016
1 parent b2e08c0 commit 1d7365f
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 25 deletions.
10 changes: 4 additions & 6 deletions src/AbstractRow.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,10 @@ public function __call($name, $arguments)
$relation = $table->getScheme()['relations'][$name];
$related = $table->getDatabase()->$name;

switch ($relation[0]) {
case Scheme::HAS_ONE:
return $related->select()->one()->relatedWith($this);

default:
return $related->select()->relatedWith($this);
if ($relation[0] === Scheme::HAS_ONE) {
return $related->select()->one()->relatedWith($this);
}

return $related->select()->relatedWith($this);
}
}
4 changes: 4 additions & 0 deletions src/Queries/Mysql/ExtendedSelectionTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ public function relatedWith(AbstractRow $row)
return $this->by($relation[1], $row->id);

case Scheme::HAS_MANY:
if ($table->name === $this->table->name) {
return $this->by($relation[1], $row->id);
}

return $this->byId($row->{$relation[1]});

case Scheme::HAS_MANY_TO_MANY:
Expand Down
36 changes: 20 additions & 16 deletions src/Row.php
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,11 @@ public function relate(Row $row)
$this->relations[$relationTable->name][] = $row;
}

$cache = $row->getCache();
$cache[$table->name] = $this;
$row->setCache($cache);
if ($table->name !== $relationTable->name) {
$cache = $row->getCache();
$cache[$table->name] = $this;
$row->setCache($cache);
}

return $this;
}
Expand Down Expand Up @@ -321,24 +323,26 @@ public function unrelate(Row $row)
$relation = $relations[$relationTable->name];

if ($relation[0] === Scheme::HAS_ONE) {
if ($this->{$relation[1]} === $row->id) {
$this->{$relation[1]} = null;
}

$this->relations[$relationTable->name] = new NullValue();
$row->unrelate($this);

$cache = $row->getCache();
return $this;
}

if (isset($cache[$table->name])) {
unset($cache[$table->name][$this->id]);
$row->setCache($cache);
if ($relation[0] === Scheme::HAS_MANY) {
if ($row->{$relation[1]} === $this->id) {
$row->{$relation[1]} = null;
$row->save();
}

return $this->save();
}
if (isset($this->relations[$relationTable->name])) {
unset($this->relations[$relationTable->name][$row->id]);
}

if ($relation[0] === Scheme::HAS_MANY) {
$row->unrelate($this);
if ($table->name !== $relationTable->name) {
$cache = $row->getCache();
$cache[$table->name] = new NullValue();
$row->setCache($cache);
}

return $this;
}
Expand Down
7 changes: 6 additions & 1 deletion src/Scheme/Scheme.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ public function __invoke()
foreach ($scheme as $relTable => &$relInfo) {
if (isset($relInfo['fields'][$foreingKey])) {
$info['relations'][$relTable] = [self::HAS_MANY, $foreingKey];
$relInfo['relations'][$table] = [self::HAS_ONE, $foreingKey];

if ($table === $relTable) {
$relInfo['relations'][$table] = [self::HAS_MANY, $foreingKey];
} else {
$relInfo['relations'][$table] = [self::HAS_ONE, $foreingKey];
}
continue;
}

Expand Down
32 changes: 30 additions & 2 deletions tests/RelationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public function setUp()
<<<EOT
CREATE TABLE "category" (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`name` TEXT
`name` TEXT,
`category_id` INTEGER
);
EOT
);
Expand Down Expand Up @@ -60,7 +61,7 @@ public function testRelatedQuery()
$comment = $db->comment->create(['id' => 1])->save();

$this->assertEquals(
'SELECT `category`.`id`, `category`.`name`, `category_post`.`post_id` FROM `category`, `category_post`, `post` WHERE (`category_post`.`category_id` = `category`.`id`) AND (`category_post`.`post_id` = `post`.`id`) AND (`post`.`id` IN (:post_id))',
'SELECT `category`.`id`, `category`.`name`, `category`.`category_id`, `category_post`.`post_id` FROM `category`, `category_post`, `post` WHERE (`category_post`.`category_id` = `category`.`id`) AND (`category_post`.`post_id` = `post`.`id`) AND (`post`.`id` IN (:post_id))',
(string) $post->category()
);

Expand Down Expand Up @@ -150,6 +151,33 @@ public function testDirectRelatedData()
$this->assertEquals($json, (string) $comments);
}

public function testRelatedWithItself()
{
$db = $this->db;

$a = $db->category->create(['name' => 'A'])->save();
$b = $db->category->create(['name' => 'B'])->save();
$a1 = $db->category->create(['name' => 'A1'])->save();
$a2 = $db->category->create(['name' => 'A2'])->save();
$a11 = $db->category->create(['name' => 'A11'])->save();
$a21 = $db->category->create(['name' => 'A21'])->save();

$a->relate($a1);
$a->relate($a2);
$a1->relate($a11);
$a2->relate($a21);

$this->assertEquals([3 => 'A1', 4 => 'A2'], $a->category->name);
$this->assertEquals([5 => 'A11'], $a1->category->name);
$this->assertEquals([6 => 'A21'], $a2->category->name);

$a1->unrelate($a11);
$this->assertEmpty($a1->category->name);

$a->unrelate($a2);
$this->assertEquals([3 => 'A1'], $a->category->name);
}

public function testManyToManyData()
{
$db = $this->db;
Expand Down

0 comments on commit 1d7365f

Please sign in to comment.