Skip to content

Commit

Permalink
accept model or an with/CTE alias for join
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Jan 16, 2022
1 parent 6c64608 commit 702da60
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ public function withId($id)
*/
public function addWith(self $model, string $alias, array $mapping = [], bool $recursive = false)
{
if (isset($this->with[$alias])) {
if ($alias === $this->table || $alias === $this->table_alias || isset($this->with[$alias])) {
throw (new Exception('With cursor already set with given alias'))
->addMoreInfo('alias', $alias);
}
Expand Down
37 changes: 27 additions & 10 deletions src/Model/Join.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ class Join
}

/**
* Name of the table (or collection) that can be used to retrieve data from.
* For SQL, This can also be an expression or sub-select.
* Foreign model or WITH/CTE alias when used with SQL persistence.
*
* @var string
* @var Model|string
*/
protected $foreign_table;

Expand Down Expand Up @@ -120,18 +119,32 @@ class Join
/** @var array<int, array<string, mixed>> Data indexed by spl_object_id(entity) which is populated here as the save/insert progresses. */
private $saveBufferByOid = [];

public function __construct(string $foreign_table = null)
/**
* @param Model|string $foreignTable
*/
public function __construct($foreignTable = null)
{
$this->foreign_table = $foreign_table;
$this->foreign_table = $foreignTable;

// handle foreign table containing a dot - that will be reverse join
if (strpos($this->foreign_table, '.') !== false) {
if (is_string($this->foreign_table) && strpos($this->foreign_table, '.') !== false) {
// split by LAST dot in foreign_table name
[$this->foreign_table, $this->foreign_field] = preg_split('~\.+(?=[^.]+$)~', $this->foreign_table);
$this->reverse = true;
}
}

public function getForeignModel(): Model
{
if (is_string($this->foreign_table)) {
return $this->getOwner()->with[$this->foreign_table]['model'];
}

$this->foreign_table->assertIsModel();

return $this->foreign_table;
}

/**
* @param Model $owner
*
Expand Down Expand Up @@ -203,6 +216,8 @@ protected function init(): void
{
$this->_init();

$this->getForeignModel(); // assert valid foreign_table

// owner model should have id_field set
$id_field = $this->getOwner()->id_field;
if (!$id_field) {
Expand Down Expand Up @@ -278,25 +293,27 @@ public function addFields(array $fields = [], array $defaults = [])
/**
* Another join will be attached to a current join.
*
* @param Model|string $foreignTable
* @param array<string, mixed> $defaults
*/
public function join(string $foreign_table, array $defaults = []): self
public function join($foreignTable, array $defaults = []): self
{
$defaults['joinName'] = $this->short_name;

return $this->getOwner()->join($foreign_table, $defaults);
return $this->getOwner()->join($foreignTable, $defaults);
}

/**
* Another leftJoin will be attached to a current join.
*
* @param Model|string $foreignTable
* @param array<string, mixed> $defaults
*/
public function leftJoin(string $foreign_table, array $defaults = []): self
public function leftJoin($foreignTable, array $defaults = []): self
{
$defaults['joinName'] = $this->short_name;

return $this->getOwner()->leftJoin($foreign_table, $defaults);
return $this->getOwner()->leftJoin($foreignTable, $defaults);
}

/**
Expand Down
7 changes: 5 additions & 2 deletions src/Model/JoinsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Atk4\Data\Model;

use Atk4\Data\Exception;
use Atk4\Data\Model;

/**
* Provides native Model methods for join functionality.
Expand All @@ -21,9 +22,10 @@ trait JoinsTrait
* join will also query $foreignTable in order to find additional fields. When inserting
* the record will be also added inside $foreignTable and relationship will be maintained.
*
* @param Model|string $foreignTable
* @param array<string, mixed> $defaults
*/
public function join(string $foreignTable, array $defaults = []): Join
public function join($foreignTable, array $defaults = []): Join
{
$this->assertIsModel();

Expand All @@ -47,9 +49,10 @@ public function join(string $foreignTable, array $defaults = []): Join
*
* @see join()
*
* @param Model|string $foreignTable
* @param array<string, mixed> $defaults
*/
public function leftJoin(string $foreignTable, array $defaults = []): Join
public function leftJoin($foreignTable, array $defaults = []): Join
{
$defaults['weak'] = true;

Expand Down

0 comments on commit 702da60

Please sign in to comment.