1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php
namespace Laminas\Db\Sql;
use Countable;
use Iterator;
// phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse
use ReturnTypeWillChange;
use function array_shift;
use function count;
use function is_array;
use function is_string;
use function key;
use function sprintf;
/**
* Aggregate JOIN specifications.
*
* Each specification is an array with the following keys:
*
* - name: the JOIN name
* - on: the table on which the JOIN occurs
* - columns: the columns to include with the JOIN operation; defaults to
* `Select::SQL_STAR`.
* - type: the type of JOIN being performed; see the `JOIN_*` constants;
* defaults to `JOIN_INNER`
*/
class Join implements Iterator, Countable
{
public const JOIN_INNER = 'inner';
public const JOIN_OUTER = 'outer';
public const JOIN_FULL_OUTER = 'full outer';
public const JOIN_LEFT = 'left';
public const JOIN_RIGHT = 'right';
public const JOIN_RIGHT_OUTER = 'right outer';
public const JOIN_LEFT_OUTER = 'left outer';
/**
* Current iterator position.
*
* @var int
*/
private $position = 0;
/**
* JOIN specifications
*
* @var array
*/
protected $joins = [];
/**
* Initialize iterator position.
*/
public function __construct()
{
$this->position = 0;
}
/**
* Rewind iterator.
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->position = 0;
}
/**
* Return current join specification.
*
* @return array
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->joins[$this->position];
}
/**
* Return the current iterator index.
*
* @return int
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->position;
}
/**
* Advance to the next JOIN specification.
*/
#[ReturnTypeWillChange]
public function next()
{
++$this->position;
}
/**
* Is the iterator at a valid position?
*
* @return bool
*/
#[ReturnTypeWillChange]
public function valid()
{
return isset($this->joins[$this->position]);
}
/**
* @return array
*/
public function getJoins()
{
return $this->joins;
}
/**
* @param string|array|TableIdentifier $name A table name on which to join, or a single
* element associative array, of the form alias => table, or TableIdentifier instance
* @param string|Predicate\Expression $on A specification describing the fields to join on.
* @param string|string[]|int|int[] $columns A single column name, an array
* of column names, or (a) specification(s) such as SQL_STAR representing
* the columns to join.
* @param string $type The JOIN type to use; see the JOIN_* constants.
* @return $this Provides a fluent interface
* @throws Exception\InvalidArgumentException For invalid $name values.
*/
public function join($name, $on, $columns = [Select::SQL_STAR], $type = self::JOIN_INNER)
{
if (is_array($name) && (! is_string(key($name)) || count($name) !== 1)) {
throw new Exception\InvalidArgumentException(
sprintf("join() expects '%s' as a single element associative array", array_shift($name))
);
}
if (! is_array($columns)) {
$columns = [$columns];
}
$this->joins[] = [
'name' => $name,
'on' => $on,
'columns' => $columns,
'type' => $type ? $type : self::JOIN_INNER,
];
return $this;
}
/**
* Reset to an empty list of JOIN specifications.
*
* @return $this Provides a fluent interface
*/
public function reset()
{
$this->joins = [];
return $this;
}
/**
* Get count of attached predicates
*
* @return int
*/
#[ReturnTypeWillChange]
public function count()
{
return count($this->joins);
}
}