1
|
|
|
<?php |
2
|
|
|
namespace PhpBoot\DB\rules\basic; |
3
|
|
|
|
4
|
|
|
use PhpBoot\DB\Context; |
5
|
|
|
use PhpBoot\DB\impls\ExecImpl; |
6
|
|
|
use PhpBoot\DB\impls\LimitImpl; |
7
|
|
|
use PhpBoot\DB\impls\OrderByImpl; |
8
|
|
|
use PhpBoot\DB\impls\ExecResult; |
9
|
|
|
use PhpBoot\DB\impls\WhereImpl; |
10
|
|
|
require_once dirname(__DIR__).'/impls.php'; |
11
|
|
|
|
12
|
|
|
class BasicRule |
13
|
|
|
{ |
14
|
56 |
|
public function __construct(Context $context){ |
15
|
56 |
|
$this->context = $context; |
16
|
56 |
|
} |
17
|
|
|
|
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var Context |
21
|
|
|
*/ |
22
|
|
|
public $context; |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
class ExecRule extends BasicRule |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* Execute sql |
29
|
|
|
* @return ExecResult |
30
|
|
|
*/ |
31
|
28 |
|
public function exec() { |
32
|
28 |
|
return ExecImpl::exec($this->context); |
33
|
|
|
} |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
class LimitRule extends ExecRule |
37
|
|
|
{ |
38
|
|
|
/** |
39
|
|
|
* limit(1) => "LIMIT 1" |
40
|
|
|
* @param int $size |
41
|
|
|
* @return \PhpBoot\DB\rules\basic\ExecRule |
42
|
|
|
*/ |
43
|
3 |
|
public function limit($size) { |
44
|
3 |
|
LimitImpl::limit($this->context, $size); |
45
|
3 |
|
return new ExecRule($this->context); |
46
|
|
|
} |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
class OrderByRule extends LimitRule |
50
|
|
|
{ |
51
|
18 |
|
public function __construct($context){ |
52
|
18 |
|
parent::__construct($context); |
53
|
18 |
|
$this->impl = new OrderByImpl(); |
54
|
18 |
|
} |
55
|
|
|
/** |
56
|
|
|
* |
57
|
|
|
* orderBy('column') => "ORDER BY column" |
58
|
|
|
* orderBy('column', Sql::ORDER_BY_ASC) => "ORDER BY column ASC" |
59
|
|
|
* orderBy('column0')->orderBy('column1') => "ORDER BY column0, column1" |
60
|
|
|
* orderBy(['column0', 'column1'=>Sql::ORDER_BY_ASC]) => "ORDER BY column0,column1 ASC" |
61
|
|
|
* @param string $column |
62
|
|
|
* @param string $order Sql::ORDER_BY_ASC or Sql::ORDER_BY_DESC |
63
|
|
|
* |
64
|
|
|
* @return \PhpBoot\DB\rules\basic\LimitRule |
65
|
|
|
*/ |
66
|
4 |
|
public function orderBy($column, $order=null) { |
67
|
4 |
|
$this->impl->orderBy($this->context, $column, $order); |
68
|
4 |
|
return new LimitRule($this->context); |
69
|
|
|
} |
70
|
|
|
private $impl; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
View Code Duplication |
class WhereRule extends OrderByRule |
|
|
|
|
74
|
|
|
{ |
75
|
18 |
|
public function __construct(Context $context, $isTheFirst = true) |
76
|
|
|
{ |
77
|
18 |
|
parent::__construct($context); |
78
|
18 |
|
$this->isTheFirst = $isTheFirst; |
79
|
18 |
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* where('a=?', 1) => "WHERE a=1" |
83
|
|
|
* where('a=?', Sql::raw('now()')) => "WHERE a=now()" |
84
|
|
|
* where('a IN (?)', [1, 2]) => "WHERE a IN (1,2)" |
85
|
|
|
* where([ |
86
|
|
|
* 'a'=>1, |
87
|
|
|
* 'b'=>['IN'=>[1,2]] |
88
|
|
|
* 'c'=>['BETWEEN'=>[1,2]] |
89
|
|
|
* 'd'=>['<>'=>1] |
90
|
|
|
* ]) |
91
|
|
|
* => |
92
|
|
|
* "WHERE a=1 AND b IN(1,2) AND c BETWEEN 1 AND 2 AND d<>1" |
93
|
|
|
* |
94
|
|
|
* @param string|array|callable $conditions |
95
|
|
|
* @param mixed $_ |
96
|
|
|
* @return NextWhereRule |
97
|
|
|
*/ |
98
|
16 |
|
public function where($conditions=null, $_=null) { |
|
|
|
|
99
|
16 |
|
if(is_callable($conditions)){ |
100
|
1 |
|
$callback = function ($context)use($conditions){ |
101
|
1 |
|
$rule = new ScopedQuery($context); |
102
|
1 |
|
$conditions($rule); |
103
|
1 |
|
}; |
104
|
1 |
|
$conditions = $callback; |
105
|
1 |
|
} |
106
|
16 |
|
if($this->isTheFirst){ |
107
|
16 |
|
WhereImpl::where($this->context, 'WHERE' ,$conditions, array_slice(func_get_args(), 1)); |
108
|
16 |
|
}else{ |
109
|
2 |
|
WhereImpl::where($this->context, 'AND', $conditions, array_slice(func_get_args(), 1)); |
110
|
|
|
} |
111
|
16 |
|
return new NextWhereRule($this->context, false); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
protected $isTheFirst; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
View Code Duplication |
class NextWhereRule extends WhereRule |
|
|
|
|
118
|
|
|
{ |
119
|
|
|
/** |
120
|
|
|
* orWhere('a=?', 1) => "OR a=1" |
121
|
|
|
* orWhere('a=?', Sql::raw('now()')) => "OR a=now()" |
122
|
|
|
* orWhere('a IN (?)', [1, 2]) => "OR a IN (1,2)" |
123
|
|
|
* orWhere([ |
124
|
|
|
* 'a'=>1, |
125
|
|
|
* 'b'=>['IN'=>[1,2]] |
126
|
|
|
* 'c'=>['BETWEEN'=>[1,2]] |
127
|
|
|
* 'd'=>['<>'=>1] |
128
|
|
|
* ]) |
129
|
|
|
* => |
130
|
|
|
* "OR (a=1 AND b IN(1,2) AND c BETWEEN 1 AND 2 AND d<>1)" |
131
|
|
|
* |
132
|
|
|
* @param string|array|callable $conditions |
133
|
|
|
* @param mixed $_ |
134
|
|
|
* @return WhereRule |
135
|
|
|
*/ |
136
|
1 |
|
public function orWhere($conditions=null, $_=null) { |
|
|
|
|
137
|
1 |
|
if(is_callable($conditions)){ |
138
|
|
|
$callback = function ($context)use($conditions){ |
139
|
|
|
$rule = new ScopedQuery($context); |
140
|
|
|
$conditions($rule); |
141
|
|
|
}; |
142
|
|
|
$conditions = $callback; |
143
|
|
|
} |
144
|
1 |
|
WhereImpl::where($this->context, 'OR', $conditions, array_slice(func_get_args(), 1)); |
145
|
1 |
|
return new WhereRule($this->context, false); |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
|
149
|
|
View Code Duplication |
class ScopedQuery extends BasicRule |
|
|
|
|
150
|
|
|
{ |
151
|
|
|
|
152
|
3 |
|
public function __construct(Context $context, $isTheFirst = true) |
153
|
|
|
{ |
154
|
3 |
|
parent::__construct($context); |
155
|
3 |
|
$this->isTheFirst = $isTheFirst; |
156
|
3 |
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* @param $expr |
160
|
|
|
* @param null $_ |
161
|
|
|
* @return NextScopedQuery |
162
|
|
|
*/ |
163
|
3 |
|
public function where($expr, $_= null){ |
|
|
|
|
164
|
3 |
|
if(is_callable($expr)){ |
165
|
|
|
$callback = function ($context)use($expr){ |
166
|
|
|
$rule = new ScopedQuery($context, true); |
167
|
|
|
$expr($rule); |
168
|
|
|
}; |
169
|
|
|
$expr = $callback; |
170
|
|
|
} |
171
|
3 |
|
if($this->isTheFirst){ |
172
|
3 |
|
WhereImpl::where($this->context, '', $expr, array_slice(func_get_args(), 1)); |
173
|
3 |
|
}else{ |
174
|
3 |
|
WhereImpl::where($this->context, 'AND', $expr, array_slice(func_get_args(), 1)); |
175
|
|
|
} |
176
|
3 |
|
return new NextScopedQuery($this->context, false); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
protected $isTheFirst; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
View Code Duplication |
class NextScopedQuery extends ScopedQuery |
|
|
|
|
183
|
|
|
{ |
184
|
|
|
/** |
185
|
|
|
* @param $expr |
186
|
|
|
* @param null $_ |
187
|
|
|
* @return ScopedQuery |
188
|
|
|
*/ |
189
|
3 |
|
public function orWhere($expr, $_= null){ |
|
|
|
|
190
|
3 |
|
if(is_callable($expr)){ |
191
|
|
|
$callback = function ($context)use($expr){ |
192
|
|
|
$rule = new ScopedQuery($context, true); |
193
|
|
|
$expr($rule); |
194
|
|
|
}; |
195
|
|
|
$expr = $callback; |
196
|
|
|
} |
197
|
3 |
|
WhereImpl::where($this->context, 'OR', $expr, array_slice(func_get_args(), 1)); |
198
|
3 |
|
return new NextScopedQuery($this->context, false); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.