1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Data\Model;
6:
7: use Atk4\Data\Exception;
8:
9: /**
10: * Provides native Model methods for join functionality.
11: */
12: trait JoinsTrait
13: {
14: /** @var array<mixed> The class used by join() method. */
15: protected $_defaultSeedJoin = [Join::class];
16:
17: /**
18: * Creates an objects that describes relationship between multiple tables (or collections).
19: *
20: * When object is loaded, then instead of pulling all the data from a single table,
21: * join will also query $foreignTable in order to find additional fields. When inserting
22: * the record will be also added inside $foreignTable and relationship will be maintained.
23: *
24: * @param array<string, mixed> $defaults
25: */
26: public function join(string $foreignTable, array $defaults = []): Join
27: {
28: $this->assertIsModel();
29:
30: $defaults[0] = $foreignTable;
31:
32: $join = Join::fromSeed($this->_defaultSeedJoin, $defaults);
33:
34: $name = $join->getDesiredName();
35: if ($this->hasElement($name)) {
36: throw (new Exception('Join with such name already exists'))
37: ->addMoreInfo('name', $name)
38: ->addMoreInfo('foreignTable', $foreignTable);
39: }
40:
41: $this->add($join);
42:
43: return $join;
44: }
45:
46: /**
47: * Add left/weak join.
48: *
49: * @param array<string, mixed> $defaults
50: */
51: public function leftJoin(string $foreignTable, array $defaults = []): Join
52: {
53: $defaults['weak'] = true;
54:
55: return $this->join($foreignTable, $defaults);
56: }
57:
58: public function hasJoin(string $link): bool
59: {
60: return $this->getModel(true)->hasElement('#join-' . $link);
61: }
62:
63: public function getJoin(string $link): Join
64: {
65: $this->assertIsModel();
66:
67: return $this->getElement('#join-' . $link);
68: }
69:
70: /**
71: * @return array<string, Join>
72: */
73: public function getJoins(): array
74: {
75: $this->assertIsModel();
76:
77: $res = [];
78: foreach ($this->elements as $k => $v) {
79: if (str_starts_with($k, '#join-')) {
80: $link = substr($k, strlen('#join-'));
81: $res[$link] = $this->getJoin($link);
82: } elseif ($v instanceof Join) {
83: throw new \Error('Unexpected Join index');
84: }
85: }
86:
87: return $res;
88: }
89: }
90: