Skip to content

Commit

Permalink
Merge pull request #106 from Icinga/add-belongs-to-one-relation
Browse files Browse the repository at this point in the history
Introduce `BelongsToOne` relation
  • Loading branch information
nilmerg authored Apr 28, 2023
2 parents 3b7dca6 + a291abc commit 921cd94
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 15 deletions.
23 changes: 14 additions & 9 deletions src/Relation/BelongsToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
*/
class BelongsToMany extends Relation
{
/** @var string Relation class */
protected const RELATION_CLASS = HasMany::class;

protected $isOne = false;

/** @var string Name of the join table or junction model class */
Expand All @@ -31,9 +34,9 @@ class BelongsToMany extends Relation
/**
* Get the name of the join table or junction model class
*
* @return string
* @return ?string
*/
public function getThroughClass()
public function getThroughClass(): ?string
{
return $this->throughClass;
}
Expand All @@ -45,7 +48,7 @@ public function getThroughClass()
*
* @return $this
*/
public function through($through)
public function through(string $through): self
{
$this->throughClass = $through;

Expand All @@ -57,7 +60,7 @@ public function through($through)
*
* @return Model|Junction
*/
public function getThrough()
public function getThrough(): Model
{
if ($this->through === null) {
$throughClass = $this->getThroughClass();
Expand Down Expand Up @@ -86,7 +89,7 @@ public function getThrough()
*
* @return $this
*/
public function setThrough($through)
public function setThrough(Model $through): self
{
$this->through = $through;

Expand All @@ -110,7 +113,7 @@ public function getTargetForeignKey()
*
* @return $this
*/
public function setTargetForeignKey($targetForeignKey)
public function setTargetForeignKey($targetForeignKey): self
{
$this->targetForeignKey = $targetForeignKey;

Expand All @@ -134,7 +137,7 @@ public function getTargetCandidateKey()
*
* @return $this
*/
public function setTargetCandidateKey($targetCandidateKey)
public function setTargetCandidateKey($targetCandidateKey): self
{
$this->targetCandidateKey = $targetCandidateKey;

Expand Down Expand Up @@ -174,14 +177,16 @@ public function resolve()
}
}

$toJunction = (new HasMany())
$junctionClass = static::RELATION_CLASS;
$toJunction = (new $junctionClass())
->setName($junction->getTableAlias())
->setSource($source)
->setTarget($junction)
->setCandidateKey($this->extractKey($possibleCandidateKey))
->setForeignKey($this->extractKey($possibleForeignKey));

$toTarget = (new HasMany())
$targetClass = static::RELATION_CLASS;
$toTarget = (new $targetClass())
->setName($this->getName())
->setSource($junction)
->setTarget($target)
Expand Down
13 changes: 13 additions & 0 deletions src/Relation/BelongsToOne.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace ipl\Orm\Relation;

/**
* One-to-one relationship with a junction table
*/
class BelongsToOne extends BelongsToMany
{
protected const RELATION_CLASS = HasOne::class;

protected $isOne = true;
}
20 changes: 19 additions & 1 deletion src/Relations.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use ipl\Orm\Exception\InvalidRelationException;
use ipl\Orm\Relation\BelongsTo;
use ipl\Orm\Relation\BelongsToMany;
use ipl\Orm\Relation\BelongsToOne;
use ipl\Orm\Relation\HasMany;
use ipl\Orm\Relation\HasOne;
use IteratorAggregate;
Expand Down Expand Up @@ -76,7 +77,7 @@ public function add(Relation $relation)
* @param string $name Name of the relation
* @param string $targetClass Target model class
*
* @return BelongsTo|BelongsToMany|HasMany|HasOne|Relation
* @return BelongsTo|BelongsToOne|BelongsToMany|HasMany|HasOne|Relation
*
* @throws \InvalidArgumentException If the target model class is not of type string
*/
Expand Down Expand Up @@ -164,6 +165,23 @@ public function belongsTo($name, $targetClass)
return $relation;
}

/**
* Define a one-to-one relationship with a junction table
*
* @param string $name Name of the relation
* @param string $targetClass Target model class
*
* @return BelongsToOne
*/
public function belongsToOne(string $name, string $targetClass): BelongsToOne
{
$relation = $this->create(BelongsToOne::class, $name, $targetClass);

$this->add($relation);

return $relation;
}

/**
* Define a many-to-many relationship
*
Expand Down
3 changes: 2 additions & 1 deletion src/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use ipl\Orm\Exception\InvalidColumnException;
use ipl\Orm\Exception\InvalidRelationException;
use ipl\Orm\Relation\BelongsToMany;
use ipl\Orm\Relation\BelongsToOne;
use ipl\Sql\ExpressionInterface;
use LogicException;
use OutOfBoundsException;
Expand Down Expand Up @@ -564,7 +565,7 @@ public function resolveRelations($path, Model $subject = null)

$resolvedRelations[$relationPath] = $relation;

if ($relation instanceof BelongsToMany) {
if ($relation instanceof BelongsToMany || $relation instanceof BelongsToOne) {
$through = $relation->getThrough();
$this->setAlias($through, join('_', array_merge(
array_slice($segments, 0, -1),
Expand Down
12 changes: 8 additions & 4 deletions tests/RelationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use ipl\Orm\Exception\InvalidRelationException;
use ipl\Orm\Relation\BelongsTo;
use ipl\Orm\Relation\BelongsToMany;
use ipl\Orm\Relation\BelongsToOne;
use ipl\Orm\Relation\HasMany;
use ipl\Orm\Relation\HasOne;
use ipl\Orm\Relations;
Expand Down Expand Up @@ -77,31 +78,34 @@ public function testHasOneReturnsOneToOneRelationship()
{
$relation = (new Relations())->hasOne('test', TestModel::class);

/** @noinspection PhpParamsInspection */
$this->assertInstanceOf(HasOne::class, $relation);
}

public function testHasManyReturnsOneToManyRelationship()
{
$relation = (new Relations())->hasMany('test', TestModel::class);

/** @noinspection PhpParamsInspection */
$this->assertInstanceOf(HasMany::class, $relation);
}

public function testBelongsToReturnsTheInverseRelationship()
{
$relation = (new Relations())->belongsTo('test', TestModel::class);

/** @noinspection PhpParamsInspection */
$this->assertInstanceOf(BelongsTo::class, $relation);
}

public function testBelongsToManyReturnsManyToManyRelationship()
{
$relation = (new Relations())->belongsToMany('test', TestModel::class);

/** @noinspection PhpParamsInspection */
$this->assertInstanceOf(BelongsToMany::class, $relation);
}

public function testBelongsToOneReturnsOneToOneRelationship()
{
$relation = (new Relations())->belongsToOne('test', TestModel::class);

$this->assertInstanceOf(BelongsToOne::class, $relation);
}
}

0 comments on commit 921cd94

Please sign in to comment.