1
+ <?php
2
+
3
+ namespace Simply \Database ;
4
+
5
+ use Simply \Database \Connection \Connection ;
6
+
7
+ /**
8
+ * Query.
9
+ * @author Riikka Kalliomäki <[email protected] >
10
+ * @copyright Copyright (c) 2018 Riikka Kalliomäki
11
+ * @license http://opensource.org/licenses/mit-license.php MIT License
12
+ */
13
+ class Query
14
+ {
15
+ /** @var Connection */
16
+ private $ connection ;
17
+ private $ sql ;
18
+
19
+ /** @var Schema[] */
20
+ private $ schemas ;
21
+ private $ parameters ;
22
+
23
+ public function __construct (Connection $ connection , string $ sql )
24
+ {
25
+ $ this ->connection = $ connection ;
26
+ $ this ->sql = $ sql ;
27
+ $ this ->schemas = [];
28
+ $ this ->parameters = [];
29
+ }
30
+
31
+ public function withSchema (Schema $ schema , string $ alias = '' ): Query
32
+ {
33
+ $ query = clone $ this ;
34
+ $ query ->schemas [$ this ->formatAlias ($ alias )] = $ schema ;
35
+
36
+ return $ query ;
37
+ }
38
+
39
+ public function withParameters (array $ parameters ): Query
40
+ {
41
+ $ query = clone $ this ;
42
+
43
+ foreach ($ parameters as $ key => $ parameter ) {
44
+ if (\is_int ($ key )) {
45
+ $ query ->parameters [] = $ parameter ;
46
+ continue ;
47
+ }
48
+
49
+ $ query ->parameters [$ key ] = $ parameter ;
50
+ }
51
+
52
+ return $ query ;
53
+ }
54
+
55
+ public function withoutSchemas (): Query
56
+ {
57
+ $ query = clone $ this ;
58
+ $ query ->schemas = [];
59
+
60
+ return $ query ;
61
+ }
62
+
63
+ public function withoutParameters (): Query
64
+ {
65
+ $ query = clone $ this ;
66
+ $ query ->parameters = [];
67
+
68
+ return $ query ;
69
+ }
70
+
71
+ public function fetchResult (): \PDOStatement
72
+ {
73
+ $ placeholders = [];
74
+
75
+ foreach ($ this ->schemas as $ alias => $ schema ) {
76
+ if ($ alias === '' ) {
77
+ $ placeholders ['{table} ' ] = $ this ->connection ->formatTable ($ schema ->getTable ());
78
+ $ placeholders ['{fields} ' ] = $ this ->connection ->formatFields ($ schema ->getFields ());
79
+
80
+ continue ;
81
+ }
82
+
83
+ $ placeholders ["{ {$ alias }.table} " ] = $ this ->connection ->formatTable ($ schema ->getTable (), $ alias );
84
+ $ placeholders ["{ {$ alias }.fields} " ] = $ this ->connection ->formatFields (
85
+ $ schema ->getFields (),
86
+ $ alias ,
87
+ $ this ->formatPrefix ($ alias )
88
+ );
89
+ }
90
+
91
+ $ query = $ this ->connection ->query (strtr ($ this ->sql , $ placeholders ), $ this ->parameters );
92
+ $ query ->setFetchMode (\PDO ::FETCH_ASSOC );
93
+
94
+ return $ query ;
95
+ }
96
+
97
+ public function fetchRows (): array
98
+ {
99
+ return iterator_to_array ($ this ->generateRows ());
100
+ }
101
+
102
+ public function fetchModels (string $ alias = '' , array $ relationships = []): array
103
+ {
104
+ return iterator_to_array ($ this ->generateModels ($ alias , $ relationships ));
105
+ }
106
+
107
+ public function fetchCallback (callable $ callback ): array
108
+ {
109
+ return iterator_to_array ($ this ->generateCallback ($ callback ));
110
+ }
111
+
112
+ public function generateRows (): \Generator
113
+ {
114
+ foreach ($ this ->fetchResult () as $ row ) {
115
+ yield $ row ;
116
+ }
117
+ }
118
+
119
+ public function generateModels (string $ alias = '' , array $ relationships = []): \Generator
120
+ {
121
+ $ alias = $ this ->formatAlias ($ alias );
122
+
123
+ if (!isset ($ this ->schemas [$ alias ])) {
124
+ if ($ alias !== '' || \count ($ this ->schemas ) !== 1 ) {
125
+ throw new \InvalidArgumentException ('No schema selected for generating database models ' );
126
+ }
127
+
128
+ $ alias = array_keys ($ this ->schemas )[0 ];
129
+ }
130
+
131
+ $ schema = $ this ->schemas [$ alias ];
132
+ $ prefix = $ this ->formatPrefix ($ alias );
133
+ $ modelRelationships = [];
134
+
135
+ foreach ($ relationships as $ key => $ name ) {
136
+ $ modelRelationships [$ this ->formatPrefix ($ key )] = $ name ;
137
+ }
138
+
139
+ foreach ($ this ->fetchResult () as $ row ) {
140
+ yield $ schema ->createModel ($ row , $ prefix , $ modelRelationships );
141
+ }
142
+ }
143
+
144
+ public function generateCallback (callable $ callback ): \Generator
145
+ {
146
+ foreach ($ this ->fetchResult () as $ row ) {
147
+ yield $ callback ($ row );
148
+ }
149
+ }
150
+
151
+ private function formatAlias (string $ alias ): string
152
+ {
153
+ if ($ alias === '' ) {
154
+ return $ alias ;
155
+ }
156
+
157
+ return substr ($ alias , -1 ) === '_ ' ? substr ($ alias , 0 , -1 ) : $ alias ;
158
+ }
159
+
160
+ private function formatPrefix (string $ prefix ): string
161
+ {
162
+ if ($ prefix === '' ) {
163
+ return $ prefix ;
164
+ }
165
+
166
+ return substr ($ prefix , -1 ) === '_ ' ? $ prefix : $ prefix . '_ ' ;
167
+ }
168
+ }
0 commit comments