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
<?php
/**
* @link http://github.com/zendframework/zend-db for the canonical source repository
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Db\Sql;
use Countable;
use Iterator;
/**
* 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
{
const JOIN_INNER = 'inner';
const JOIN_OUTER = 'outer';
const JOIN_LEFT = 'left';
const JOIN_RIGHT = 'right';
const JOIN_RIGHT_OUTER = 'right outer';
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.
*/
public function rewind()
{
$this->position = 0;
}
/**
* Return current join specification.
*
* @return array
*/
public function current()
{
return $this->joins[$this->position];
}
/**
* Return the current iterator index.
*
* @return int
*/
public function key()
{
return $this->position;
}
/**
* Advance to the next JOIN specification.
*/
public function next()
{
++$this->position;
}
/**
* Is the iterator at a valid position?
*
* @return bool
*/
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 self Provides a fluent interface
* @throws Exception\InvalidArgumentException for invalid $name values.
*/
public function join($name, $on, $columns = [Select::SQL_STAR], $type = Join::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 : Join::JOIN_INNER
];
return $this;
}
/**
* Reset to an empty list of JOIN specifications.
*
* @return self Provides a fluent interface
*/
public function reset()
{
$this->joins = [];
return $this;
}
/**
* Get count of attached predicates
*
* @return int
*/
public function count()
{
return count($this->joins);
}
}