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
|
53 |
|
public function __construct(Context $context){ |
15
|
53 |
|
$this->context = $context; |
16
|
53 |
|
} |
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
|
25 |
|
public function exec() { |
32
|
25 |
|
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
|
|
View Code Duplication |
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
|
|
|
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
|
|
|
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
|
|
|
} |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.