Skip to content

Commit a2619a8

Browse files
committed
Refactored subquery generation by closure
1 parent b0775d4 commit a2619a8

File tree

4 files changed

+85
-30
lines changed

4 files changed

+85
-30
lines changed

src/Query/Sql/Base.php

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ class Base extends BaseQuery
2525
*/
2626
protected $table = null;
2727

28+
/**
29+
* Function to check if sub queries have been generated correctly, to avoid translation errors
30+
*
31+
* @return bool
32+
*/
33+
protected function isValid()
34+
{
35+
return (bool)!empty($this->table);
36+
}
37+
2838
/**
2939
* Inherit property values from parent query
3040
*
@@ -42,7 +52,27 @@ protected function inheritFromParent(BaseQuery $parent)
4252
$this->table = $parent->table;
4353
}
4454
}
45-
55+
56+
/**
57+
* Process a subquery generator callback
58+
*
59+
* @param callable $generator
60+
* @return void
61+
*/
62+
protected function generateSubQuery($generator, $object = null)
63+
{
64+
// create new query object
65+
$subquery = is_null($object)? new Select : $object;
66+
67+
// run the closure callback on the sub query
68+
$generator($subquery);
69+
if (!$subquery->isValid()) {
70+
throw new Exception('Subquery generator did not generate a valid subquery.');
71+
}
72+
73+
return $subquery;
74+
}
75+
4676
/**
4777
* Create a new select query builder
4878
*
@@ -86,11 +116,7 @@ public function table($table, $alias = null)
86116
$alias = key($table);
87117
$table = reset($table);
88118

89-
// create new query object
90-
$subquery = new Select;
91-
92-
// run the closure callback on the sub query
93-
call_user_func_array($table, array(&$subquery));
119+
$subquery = $this->generateSubQuery($table);
94120

95121
// set the table
96122
// IMPORTANT: Only if we have a closure as table

src/Query/Sql/Select.php

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,19 @@ class Select extends SelectBase implements FetchableInterface
6464
*/
6565
protected $forwardKey = false;
6666

67+
/**
68+
* Function to check if sub queries have been generated correctly, to avoid translation errors
69+
*
70+
* @return bool
71+
*/
72+
protected function isValid()
73+
{
74+
return (bool)!empty($this->table);
75+
}
76+
6777
/**
6878
* Inherit property values from parent query
69-
*
79+
*
7080
* @param BaseQuery $parent
7181
* @return void
7282
*/
@@ -340,18 +350,22 @@ public function join($table, $localKey, $operator = null, $referenceKey = null,
340350
throw new Exception('Invalid join type "'.$type.'" given. Available type: inner, left, right, outer');
341351
}
342352

343-
// to make nested joins possible you can pass an closure
344-
// wich will create a new query where you can add your nested wheres
345-
if (is_object($localKey) && ($localKey instanceof \Closure))
346-
{
347-
// create new query object
348-
$subquery = new SelectJoin;
349-
350-
// run the closure callback on the sub query
351-
call_user_func_array($localKey, array(&$subquery));
352-
353-
// add the join
354-
$this->joins[] = array($type, $table, $subquery); return $this;
353+
if (is_object($localKey)) {
354+
// to make nested joins possible you can pass a closure
355+
// which will create a new query where you can add your nested wheres
356+
if ($localKey instanceof \Closure) {
357+
$localKey = $this->generateSubQuery($localKey, new SelectJoin);
358+
}
359+
// also allow using a manually constructed SelectJoin object
360+
if ($localKey instanceof SelectJoin) {
361+
$this->joins[] = [$type, $table, $localKey];
362+
return $this;
363+
}
364+
// continue, because localKey could be an expression object
365+
}
366+
367+
if (is_null($operator) || is_null($referenceKey)) {
368+
throw new Exception('When using non nested join conditions, an operator and a reference key is required.');
355369
}
356370

357371
$this->joins[] = array($type, $table, $localKey, $operator, $referenceKey); return $this;

src/Query/Sql/SelectBase.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ class SelectBase extends Base
3535
*/
3636
protected $limit = null;
3737

38+
/**
39+
* Function to check if sub queries have been generated correctly, to avoid translation errors
40+
*
41+
* @return bool
42+
*/
43+
protected function isValid()
44+
{
45+
return (bool)!empty($this->wheres);
46+
}
47+
3848
/**
3949
* Returns an string argument as parsed array if possible
4050
*
@@ -126,17 +136,12 @@ public function where($column, $param1 = null, $param2 = null, $type = 'and')
126136
$this->wheres[] = array($type, $subquery); return $this;
127137
}
128138

129-
// to make nested wheres possible you can pass an closure
130-
// wich will create a new query where you can add your nested wheres
131-
if (is_object($column) && ($column instanceof \Closure))
132-
{
133-
// create new query object
134-
$subquery = new SelectBase;
135-
136-
// run the closure callback on the sub query
137-
call_user_func_array($column, array( &$subquery ));
138-
139-
$this->wheres[] = array($type, $subquery); return $this;
139+
// to make nested wheres possible you can pass a closure
140+
// which will create a new query where you can add your nested wheres
141+
if (is_object($column) && ($column instanceof \Closure)) {
142+
$subquery = $this->generateSubQuery($column, new SelectBase);
143+
$this->wheres[] = [$type, $subquery];
144+
return $this;
140145
}
141146

142147
// when param2 is null we replace param2 with param one as the

src/Query/Sql/SelectJoin.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ class SelectJoin extends SelectBase
2727
*/
2828
protected $wheres = array();
2929

30+
/**
31+
* Function to check if sub queries have been generated correctly, to avoid translation errors
32+
*
33+
* @return bool
34+
*/
35+
protected function isValid()
36+
{
37+
return (bool)!empty($this->ons);
38+
}
39+
3040
/**
3141
* Add an on condition to the join object
3242
*

0 commit comments

Comments
 (0)