├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.php
├── composer.json
├── composer.lock
├── demo
├── setup-how-to-integrate.php
├── usage-native-pdo.php
├── usage-query-builder.php
└── usage-short-cut-methods.php
├── init.php
├── phpunit.xml
├── src
├── Builder.php
├── Builder
│ ├── Delete.php
│ ├── Ignore.php
│ ├── Insert.php
│ ├── Replace.php
│ ├── Select.php
│ └── Update.php
├── Configuration.php
├── Helpers.php
├── Library.php
├── Native.php
├── Report.php
├── Report
│ └── Database
│ │ └── Structure.php
└── Server.php
└── tests
├── LibraryTest.php
└── bootstrap.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .DS_Store
3 | composer
4 | demo/index.php
5 | clover.xml
6 | vendor
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | sudo: false
3 |
4 | matrix:
5 | fast_finish: true
6 | include:
7 | - php: 5.5
8 | - php: 5.6
9 | - php: 7.0
10 | - php: 7.1
11 | - php: 7.2
12 | - php: 8.0
13 | - php: 8.1
14 | - php: 8.2
15 |
16 | before_script:
17 | - composer self-update
18 | - composer install --prefer-source --no-progress --no-interaction
19 |
20 | script:
21 | - vendor/bin/phpunit
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Kodols
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MySQL Library for PHP
2 |
3 | [](https://travis-ci.org/kodols/php-mysql-library)
4 | [](https://packagist.org/packages/kodols/php-mysql-library)
5 | [](packagist.org/packages/kodols/php-mysql-library)
6 | [](packagist.org/packages/kodols/php-mysql-library)
7 |
8 | This library will give you access to everything you need from MySQL in PHP.
9 |
10 | See our [Object Reference](https://github.com/kodols/PHP-MySQL-Library/wiki) to learn what is possible, or view our [demo folder](https://github.com/kodols/PHP-MySQL-Library/tree/master/demo) for examples.
11 |
12 | ## About
13 |
14 | The library is a hybrid between PHP's PDO and generic query building.
15 |
16 | Started as a helper class for in-house projects and grown into a usefull tool for Kodols Ltd. A decision was made to make this library public give others the chance to use a well oriented library for database management.
17 |
18 | Library will keep getting support and upgrades as this has been become the goto library for Kodols Ltd. to use for our projects.
19 |
20 | This library supports access to the native PDO methods, few helper methods to simplify commonly used methods and a query builder to really give you access to build cool statements.
21 |
22 | ### Prerequisites
23 |
24 | This library will work on PHP 5.4 or later
25 |
26 | ### Installing
27 |
28 | You can clone this git repository into your project
29 |
30 | ```
31 | git clone git://github.com/kodols/PHP-MySQL-Library.git
32 | ```
33 |
34 | or you can use composer
35 |
36 | ```
37 | composer require kodols/php-mysql-library
38 | ```
39 |
40 | ## Deployment
41 |
42 | The integration process is very simple, you call the main library class, add a configuration and you are all set.
43 | However we would recommend spend some time to really prepare the environment so you get the best out of this library.
44 | The library is based in `src/` with its namespace `\Kodols\MySQL`. In our examples we will use a demo variable $KML (Kodols MySQL Library), but of course you can use any variable you like.
45 |
46 | ```
47 | $KML = new \Kodols\MySQL\Library;
48 | ```
49 |
50 | Once you have successfuly create the object you need to add MySQL connection details to it. The library supports multiple configurations attached and multiple connections established in the same request.
51 |
52 | ```
53 | $config = $KML->newConfiguration();
54 | $config->setHostname('my.host.com');
55 | $config->setUsername('web');
56 | $config->setPassword('42412');
57 | $config->setDatabase('project');
58 | ```
59 | The `$config` variable is `\Kodols\MySQL\Configuration` object, see Wiki for in depth details.
60 |
61 | Once configuration is created you can attach it to the main library via `$KML->attachConfiguration($config);` and start using the library. However if your environment has multiple database endpoints, or maybe you have production, development and local environment, then you can setup it as follows:
62 | ```
63 | $config = $KML->newConfiguration();
64 | $config->setHostname('my.host.com');
65 | ...
66 | $KML->attachConfiguration($config, 'live');
67 | ```
68 | So when you call the server variable you can choose with of the server endpoints you want to use.
69 |
70 | ## Contributors
71 |
72 | We welcome a good idea, bug fixes, suggestions and requests.
73 | This list will be updated every time a new contribution has been made.
74 |
75 | * **Edgars Kohs** - *author* - [Kodols Ltd.](http://www.kodols.com)
76 |
77 | ## License
78 |
79 | This project is licensed under the MIT License - see the [https://github.com/kodols/php-mysql-library/blob/master/LICENSE](LICENSE) file for details
80 |
--------------------------------------------------------------------------------
/build.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | =5.3.3"
96 | },
97 | "require-dev": {
98 | "phpunit/phpunit": "~4.0"
99 | },
100 | "suggest": {
101 | "dflydev/markdown": "~1.0",
102 | "erusev/parsedown": "~1.0"
103 | },
104 | "type": "library",
105 | "extra": {
106 | "branch-alias": {
107 | "dev-master": "2.0.x-dev"
108 | }
109 | },
110 | "autoload": {
111 | "psr-0": {
112 | "phpDocumentor": [
113 | "src/"
114 | ]
115 | }
116 | },
117 | "notification-url": "https://packagist.org/downloads/",
118 | "license": [
119 | "MIT"
120 | ],
121 | "authors": [
122 | {
123 | "name": "Mike van Riel",
124 | "email": "mike.vanriel@naenius.com"
125 | }
126 | ],
127 | "support": {
128 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
129 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/2.x"
130 | },
131 | "time": "2016-01-25T08:17:30+00:00"
132 | },
133 | {
134 | "name": "phpspec/prophecy",
135 | "version": "v1.5.0",
136 | "source": {
137 | "type": "git",
138 | "url": "https://github.com/phpspec/prophecy.git",
139 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7"
140 | },
141 | "dist": {
142 | "type": "zip",
143 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7",
144 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7",
145 | "shasum": ""
146 | },
147 | "require": {
148 | "doctrine/instantiator": "^1.0.2",
149 | "phpdocumentor/reflection-docblock": "~2.0",
150 | "sebastian/comparator": "~1.1"
151 | },
152 | "require-dev": {
153 | "phpspec/phpspec": "~2.0"
154 | },
155 | "type": "library",
156 | "extra": {
157 | "branch-alias": {
158 | "dev-master": "1.4.x-dev"
159 | }
160 | },
161 | "autoload": {
162 | "psr-0": {
163 | "Prophecy\\": "src/"
164 | }
165 | },
166 | "notification-url": "https://packagist.org/downloads/",
167 | "license": [
168 | "MIT"
169 | ],
170 | "authors": [
171 | {
172 | "name": "Konstantin Kudryashov",
173 | "email": "ever.zet@gmail.com",
174 | "homepage": "http://everzet.com"
175 | },
176 | {
177 | "name": "Marcello Duarte",
178 | "email": "marcello.duarte@gmail.com"
179 | }
180 | ],
181 | "description": "Highly opinionated mocking framework for PHP 5.3+",
182 | "homepage": "https://github.com/phpspec/prophecy",
183 | "keywords": [
184 | "Double",
185 | "Dummy",
186 | "fake",
187 | "mock",
188 | "spy",
189 | "stub"
190 | ],
191 | "support": {
192 | "issues": "https://github.com/phpspec/prophecy/issues",
193 | "source": "https://github.com/phpspec/prophecy/tree/master"
194 | },
195 | "time": "2015-08-13T10:07:40+00:00"
196 | },
197 | {
198 | "name": "phpunit/php-code-coverage",
199 | "version": "2.2.4",
200 | "source": {
201 | "type": "git",
202 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
203 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
204 | },
205 | "dist": {
206 | "type": "zip",
207 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
208 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
209 | "shasum": ""
210 | },
211 | "require": {
212 | "php": ">=5.3.3",
213 | "phpunit/php-file-iterator": "~1.3",
214 | "phpunit/php-text-template": "~1.2",
215 | "phpunit/php-token-stream": "~1.3",
216 | "sebastian/environment": "^1.3.2",
217 | "sebastian/version": "~1.0"
218 | },
219 | "require-dev": {
220 | "ext-xdebug": ">=2.1.4",
221 | "phpunit/phpunit": "~4"
222 | },
223 | "suggest": {
224 | "ext-dom": "*",
225 | "ext-xdebug": ">=2.2.1",
226 | "ext-xmlwriter": "*"
227 | },
228 | "type": "library",
229 | "extra": {
230 | "branch-alias": {
231 | "dev-master": "2.2.x-dev"
232 | }
233 | },
234 | "autoload": {
235 | "classmap": [
236 | "src/"
237 | ]
238 | },
239 | "notification-url": "https://packagist.org/downloads/",
240 | "license": [
241 | "BSD-3-Clause"
242 | ],
243 | "authors": [
244 | {
245 | "name": "Sebastian Bergmann",
246 | "email": "sb@sebastian-bergmann.de",
247 | "role": "lead"
248 | }
249 | ],
250 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
251 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
252 | "keywords": [
253 | "coverage",
254 | "testing",
255 | "xunit"
256 | ],
257 | "support": {
258 | "irc": "irc://irc.freenode.net/phpunit",
259 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
260 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/2.2"
261 | },
262 | "time": "2015-10-06T15:47:00+00:00"
263 | },
264 | {
265 | "name": "phpunit/php-file-iterator",
266 | "version": "1.4.5",
267 | "source": {
268 | "type": "git",
269 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
270 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
271 | },
272 | "dist": {
273 | "type": "zip",
274 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
275 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
276 | "shasum": ""
277 | },
278 | "require": {
279 | "php": ">=5.3.3"
280 | },
281 | "type": "library",
282 | "extra": {
283 | "branch-alias": {
284 | "dev-master": "1.4.x-dev"
285 | }
286 | },
287 | "autoload": {
288 | "classmap": [
289 | "src/"
290 | ]
291 | },
292 | "notification-url": "https://packagist.org/downloads/",
293 | "license": [
294 | "BSD-3-Clause"
295 | ],
296 | "authors": [
297 | {
298 | "name": "Sebastian Bergmann",
299 | "email": "sb@sebastian-bergmann.de",
300 | "role": "lead"
301 | }
302 | ],
303 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
304 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
305 | "keywords": [
306 | "filesystem",
307 | "iterator"
308 | ],
309 | "support": {
310 | "irc": "irc://irc.freenode.net/phpunit",
311 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
312 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5"
313 | },
314 | "time": "2017-11-27T13:52:08+00:00"
315 | },
316 | {
317 | "name": "phpunit/php-text-template",
318 | "version": "1.2.1",
319 | "source": {
320 | "type": "git",
321 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
322 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
323 | },
324 | "dist": {
325 | "type": "zip",
326 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
327 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
328 | "shasum": ""
329 | },
330 | "require": {
331 | "php": ">=5.3.3"
332 | },
333 | "type": "library",
334 | "autoload": {
335 | "classmap": [
336 | "src/"
337 | ]
338 | },
339 | "notification-url": "https://packagist.org/downloads/",
340 | "license": [
341 | "BSD-3-Clause"
342 | ],
343 | "authors": [
344 | {
345 | "name": "Sebastian Bergmann",
346 | "email": "sebastian@phpunit.de",
347 | "role": "lead"
348 | }
349 | ],
350 | "description": "Simple template engine.",
351 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
352 | "keywords": [
353 | "template"
354 | ],
355 | "support": {
356 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
357 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1"
358 | },
359 | "time": "2015-06-21T13:50:34+00:00"
360 | },
361 | {
362 | "name": "phpunit/php-timer",
363 | "version": "1.0.8",
364 | "source": {
365 | "type": "git",
366 | "url": "https://github.com/sebastianbergmann/php-timer.git",
367 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
368 | },
369 | "dist": {
370 | "type": "zip",
371 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
372 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
373 | "shasum": ""
374 | },
375 | "require": {
376 | "php": ">=5.3.3"
377 | },
378 | "require-dev": {
379 | "phpunit/phpunit": "~4|~5"
380 | },
381 | "type": "library",
382 | "autoload": {
383 | "classmap": [
384 | "src/"
385 | ]
386 | },
387 | "notification-url": "https://packagist.org/downloads/",
388 | "license": [
389 | "BSD-3-Clause"
390 | ],
391 | "authors": [
392 | {
393 | "name": "Sebastian Bergmann",
394 | "email": "sb@sebastian-bergmann.de",
395 | "role": "lead"
396 | }
397 | ],
398 | "description": "Utility class for timing",
399 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
400 | "keywords": [
401 | "timer"
402 | ],
403 | "support": {
404 | "irc": "irc://irc.freenode.net/phpunit",
405 | "issues": "https://github.com/sebastianbergmann/php-timer/issues",
406 | "source": "https://github.com/sebastianbergmann/php-timer/tree/master"
407 | },
408 | "time": "2016-05-12T18:03:57+00:00"
409 | },
410 | {
411 | "name": "phpunit/php-token-stream",
412 | "version": "1.4.12",
413 | "source": {
414 | "type": "git",
415 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
416 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16"
417 | },
418 | "dist": {
419 | "type": "zip",
420 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16",
421 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16",
422 | "shasum": ""
423 | },
424 | "require": {
425 | "ext-tokenizer": "*",
426 | "php": ">=5.3.3"
427 | },
428 | "require-dev": {
429 | "phpunit/phpunit": "~4.2"
430 | },
431 | "type": "library",
432 | "extra": {
433 | "branch-alias": {
434 | "dev-master": "1.4-dev"
435 | }
436 | },
437 | "autoload": {
438 | "classmap": [
439 | "src/"
440 | ]
441 | },
442 | "notification-url": "https://packagist.org/downloads/",
443 | "license": [
444 | "BSD-3-Clause"
445 | ],
446 | "authors": [
447 | {
448 | "name": "Sebastian Bergmann",
449 | "email": "sebastian@phpunit.de"
450 | }
451 | ],
452 | "description": "Wrapper around PHP's tokenizer extension.",
453 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
454 | "keywords": [
455 | "tokenizer"
456 | ],
457 | "support": {
458 | "issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
459 | "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4"
460 | },
461 | "abandoned": true,
462 | "time": "2017-12-04T08:55:13+00:00"
463 | },
464 | {
465 | "name": "phpunit/phpunit",
466 | "version": "4.8.36",
467 | "source": {
468 | "type": "git",
469 | "url": "https://github.com/sebastianbergmann/phpunit.git",
470 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517"
471 | },
472 | "dist": {
473 | "type": "zip",
474 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517",
475 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517",
476 | "shasum": ""
477 | },
478 | "require": {
479 | "ext-dom": "*",
480 | "ext-json": "*",
481 | "ext-pcre": "*",
482 | "ext-reflection": "*",
483 | "ext-spl": "*",
484 | "php": ">=5.3.3",
485 | "phpspec/prophecy": "^1.3.1",
486 | "phpunit/php-code-coverage": "~2.1",
487 | "phpunit/php-file-iterator": "~1.4",
488 | "phpunit/php-text-template": "~1.2",
489 | "phpunit/php-timer": "^1.0.6",
490 | "phpunit/phpunit-mock-objects": "~2.3",
491 | "sebastian/comparator": "~1.2.2",
492 | "sebastian/diff": "~1.2",
493 | "sebastian/environment": "~1.3",
494 | "sebastian/exporter": "~1.2",
495 | "sebastian/global-state": "~1.0",
496 | "sebastian/version": "~1.0",
497 | "symfony/yaml": "~2.1|~3.0"
498 | },
499 | "suggest": {
500 | "phpunit/php-invoker": "~1.1"
501 | },
502 | "bin": [
503 | "phpunit"
504 | ],
505 | "type": "library",
506 | "extra": {
507 | "branch-alias": {
508 | "dev-master": "4.8.x-dev"
509 | }
510 | },
511 | "autoload": {
512 | "classmap": [
513 | "src/"
514 | ]
515 | },
516 | "notification-url": "https://packagist.org/downloads/",
517 | "license": [
518 | "BSD-3-Clause"
519 | ],
520 | "authors": [
521 | {
522 | "name": "Sebastian Bergmann",
523 | "email": "sebastian@phpunit.de",
524 | "role": "lead"
525 | }
526 | ],
527 | "description": "The PHP Unit Testing framework.",
528 | "homepage": "https://phpunit.de/",
529 | "keywords": [
530 | "phpunit",
531 | "testing",
532 | "xunit"
533 | ],
534 | "support": {
535 | "issues": "https://github.com/sebastianbergmann/phpunit/issues",
536 | "source": "https://github.com/sebastianbergmann/phpunit/tree/4.8.36"
537 | },
538 | "time": "2017-06-21T08:07:12+00:00"
539 | },
540 | {
541 | "name": "phpunit/phpunit-mock-objects",
542 | "version": "2.3.8",
543 | "source": {
544 | "type": "git",
545 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
546 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
547 | },
548 | "dist": {
549 | "type": "zip",
550 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
551 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
552 | "shasum": ""
553 | },
554 | "require": {
555 | "doctrine/instantiator": "^1.0.2",
556 | "php": ">=5.3.3",
557 | "phpunit/php-text-template": "~1.2",
558 | "sebastian/exporter": "~1.2"
559 | },
560 | "require-dev": {
561 | "phpunit/phpunit": "~4.4"
562 | },
563 | "suggest": {
564 | "ext-soap": "*"
565 | },
566 | "type": "library",
567 | "extra": {
568 | "branch-alias": {
569 | "dev-master": "2.3.x-dev"
570 | }
571 | },
572 | "autoload": {
573 | "classmap": [
574 | "src/"
575 | ]
576 | },
577 | "notification-url": "https://packagist.org/downloads/",
578 | "license": [
579 | "BSD-3-Clause"
580 | ],
581 | "authors": [
582 | {
583 | "name": "Sebastian Bergmann",
584 | "email": "sb@sebastian-bergmann.de",
585 | "role": "lead"
586 | }
587 | ],
588 | "description": "Mock Object library for PHPUnit",
589 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
590 | "keywords": [
591 | "mock",
592 | "xunit"
593 | ],
594 | "support": {
595 | "irc": "irc://irc.freenode.net/phpunit",
596 | "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues",
597 | "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/2.3"
598 | },
599 | "abandoned": true,
600 | "time": "2015-10-02T06:51:40+00:00"
601 | },
602 | {
603 | "name": "sebastian/comparator",
604 | "version": "1.2.4",
605 | "source": {
606 | "type": "git",
607 | "url": "https://github.com/sebastianbergmann/comparator.git",
608 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
609 | },
610 | "dist": {
611 | "type": "zip",
612 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
613 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
614 | "shasum": ""
615 | },
616 | "require": {
617 | "php": ">=5.3.3",
618 | "sebastian/diff": "~1.2",
619 | "sebastian/exporter": "~1.2 || ~2.0"
620 | },
621 | "require-dev": {
622 | "phpunit/phpunit": "~4.4"
623 | },
624 | "type": "library",
625 | "extra": {
626 | "branch-alias": {
627 | "dev-master": "1.2.x-dev"
628 | }
629 | },
630 | "autoload": {
631 | "classmap": [
632 | "src/"
633 | ]
634 | },
635 | "notification-url": "https://packagist.org/downloads/",
636 | "license": [
637 | "BSD-3-Clause"
638 | ],
639 | "authors": [
640 | {
641 | "name": "Jeff Welch",
642 | "email": "whatthejeff@gmail.com"
643 | },
644 | {
645 | "name": "Volker Dusch",
646 | "email": "github@wallbash.com"
647 | },
648 | {
649 | "name": "Bernhard Schussek",
650 | "email": "bschussek@2bepublished.at"
651 | },
652 | {
653 | "name": "Sebastian Bergmann",
654 | "email": "sebastian@phpunit.de"
655 | }
656 | ],
657 | "description": "Provides the functionality to compare PHP values for equality",
658 | "homepage": "http://www.github.com/sebastianbergmann/comparator",
659 | "keywords": [
660 | "comparator",
661 | "compare",
662 | "equality"
663 | ],
664 | "support": {
665 | "issues": "https://github.com/sebastianbergmann/comparator/issues",
666 | "source": "https://github.com/sebastianbergmann/comparator/tree/1.2"
667 | },
668 | "time": "2017-01-29T09:50:25+00:00"
669 | },
670 | {
671 | "name": "sebastian/diff",
672 | "version": "1.4.1",
673 | "source": {
674 | "type": "git",
675 | "url": "https://github.com/sebastianbergmann/diff.git",
676 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
677 | },
678 | "dist": {
679 | "type": "zip",
680 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
681 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
682 | "shasum": ""
683 | },
684 | "require": {
685 | "php": ">=5.3.3"
686 | },
687 | "require-dev": {
688 | "phpunit/phpunit": "~4.8"
689 | },
690 | "type": "library",
691 | "extra": {
692 | "branch-alias": {
693 | "dev-master": "1.4-dev"
694 | }
695 | },
696 | "autoload": {
697 | "classmap": [
698 | "src/"
699 | ]
700 | },
701 | "notification-url": "https://packagist.org/downloads/",
702 | "license": [
703 | "BSD-3-Clause"
704 | ],
705 | "authors": [
706 | {
707 | "name": "Kore Nordmann",
708 | "email": "mail@kore-nordmann.de"
709 | },
710 | {
711 | "name": "Sebastian Bergmann",
712 | "email": "sebastian@phpunit.de"
713 | }
714 | ],
715 | "description": "Diff implementation",
716 | "homepage": "https://github.com/sebastianbergmann/diff",
717 | "keywords": [
718 | "diff"
719 | ],
720 | "support": {
721 | "issues": "https://github.com/sebastianbergmann/diff/issues",
722 | "source": "https://github.com/sebastianbergmann/diff/tree/master"
723 | },
724 | "time": "2015-12-08T07:14:41+00:00"
725 | },
726 | {
727 | "name": "sebastian/environment",
728 | "version": "1.3.7",
729 | "source": {
730 | "type": "git",
731 | "url": "https://github.com/sebastianbergmann/environment.git",
732 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
733 | },
734 | "dist": {
735 | "type": "zip",
736 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
737 | "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
738 | "shasum": ""
739 | },
740 | "require": {
741 | "php": ">=5.3.3"
742 | },
743 | "require-dev": {
744 | "phpunit/phpunit": "~4.4"
745 | },
746 | "type": "library",
747 | "extra": {
748 | "branch-alias": {
749 | "dev-master": "1.3.x-dev"
750 | }
751 | },
752 | "autoload": {
753 | "classmap": [
754 | "src/"
755 | ]
756 | },
757 | "notification-url": "https://packagist.org/downloads/",
758 | "license": [
759 | "BSD-3-Clause"
760 | ],
761 | "authors": [
762 | {
763 | "name": "Sebastian Bergmann",
764 | "email": "sebastian@phpunit.de"
765 | }
766 | ],
767 | "description": "Provides functionality to handle HHVM/PHP environments",
768 | "homepage": "http://www.github.com/sebastianbergmann/environment",
769 | "keywords": [
770 | "Xdebug",
771 | "environment",
772 | "hhvm"
773 | ],
774 | "support": {
775 | "issues": "https://github.com/sebastianbergmann/environment/issues",
776 | "source": "https://github.com/sebastianbergmann/environment/tree/1.3.7"
777 | },
778 | "time": "2016-05-17T03:18:57+00:00"
779 | },
780 | {
781 | "name": "sebastian/exporter",
782 | "version": "1.2.2",
783 | "source": {
784 | "type": "git",
785 | "url": "https://github.com/sebastianbergmann/exporter.git",
786 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
787 | },
788 | "dist": {
789 | "type": "zip",
790 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
791 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
792 | "shasum": ""
793 | },
794 | "require": {
795 | "php": ">=5.3.3",
796 | "sebastian/recursion-context": "~1.0"
797 | },
798 | "require-dev": {
799 | "ext-mbstring": "*",
800 | "phpunit/phpunit": "~4.4"
801 | },
802 | "type": "library",
803 | "extra": {
804 | "branch-alias": {
805 | "dev-master": "1.3.x-dev"
806 | }
807 | },
808 | "autoload": {
809 | "classmap": [
810 | "src/"
811 | ]
812 | },
813 | "notification-url": "https://packagist.org/downloads/",
814 | "license": [
815 | "BSD-3-Clause"
816 | ],
817 | "authors": [
818 | {
819 | "name": "Jeff Welch",
820 | "email": "whatthejeff@gmail.com"
821 | },
822 | {
823 | "name": "Volker Dusch",
824 | "email": "github@wallbash.com"
825 | },
826 | {
827 | "name": "Bernhard Schussek",
828 | "email": "bschussek@2bepublished.at"
829 | },
830 | {
831 | "name": "Sebastian Bergmann",
832 | "email": "sebastian@phpunit.de"
833 | },
834 | {
835 | "name": "Adam Harvey",
836 | "email": "aharvey@php.net"
837 | }
838 | ],
839 | "description": "Provides the functionality to export PHP variables for visualization",
840 | "homepage": "http://www.github.com/sebastianbergmann/exporter",
841 | "keywords": [
842 | "export",
843 | "exporter"
844 | ],
845 | "support": {
846 | "issues": "https://github.com/sebastianbergmann/exporter/issues",
847 | "source": "https://github.com/sebastianbergmann/exporter/tree/master"
848 | },
849 | "time": "2016-06-17T09:04:28+00:00"
850 | },
851 | {
852 | "name": "sebastian/global-state",
853 | "version": "1.1.1",
854 | "source": {
855 | "type": "git",
856 | "url": "https://github.com/sebastianbergmann/global-state.git",
857 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
858 | },
859 | "dist": {
860 | "type": "zip",
861 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
862 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
863 | "shasum": ""
864 | },
865 | "require": {
866 | "php": ">=5.3.3"
867 | },
868 | "require-dev": {
869 | "phpunit/phpunit": "~4.2"
870 | },
871 | "suggest": {
872 | "ext-uopz": "*"
873 | },
874 | "type": "library",
875 | "extra": {
876 | "branch-alias": {
877 | "dev-master": "1.0-dev"
878 | }
879 | },
880 | "autoload": {
881 | "classmap": [
882 | "src/"
883 | ]
884 | },
885 | "notification-url": "https://packagist.org/downloads/",
886 | "license": [
887 | "BSD-3-Clause"
888 | ],
889 | "authors": [
890 | {
891 | "name": "Sebastian Bergmann",
892 | "email": "sebastian@phpunit.de"
893 | }
894 | ],
895 | "description": "Snapshotting of global state",
896 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
897 | "keywords": [
898 | "global state"
899 | ],
900 | "support": {
901 | "issues": "https://github.com/sebastianbergmann/global-state/issues",
902 | "source": "https://github.com/sebastianbergmann/global-state/tree/1.1.1"
903 | },
904 | "time": "2015-10-12T03:26:01+00:00"
905 | },
906 | {
907 | "name": "sebastian/recursion-context",
908 | "version": "1.0.5",
909 | "source": {
910 | "type": "git",
911 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
912 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7"
913 | },
914 | "dist": {
915 | "type": "zip",
916 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
917 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
918 | "shasum": ""
919 | },
920 | "require": {
921 | "php": ">=5.3.3"
922 | },
923 | "require-dev": {
924 | "phpunit/phpunit": "~4.4"
925 | },
926 | "type": "library",
927 | "extra": {
928 | "branch-alias": {
929 | "dev-master": "1.0.x-dev"
930 | }
931 | },
932 | "autoload": {
933 | "classmap": [
934 | "src/"
935 | ]
936 | },
937 | "notification-url": "https://packagist.org/downloads/",
938 | "license": [
939 | "BSD-3-Clause"
940 | ],
941 | "authors": [
942 | {
943 | "name": "Jeff Welch",
944 | "email": "whatthejeff@gmail.com"
945 | },
946 | {
947 | "name": "Sebastian Bergmann",
948 | "email": "sebastian@phpunit.de"
949 | },
950 | {
951 | "name": "Adam Harvey",
952 | "email": "aharvey@php.net"
953 | }
954 | ],
955 | "description": "Provides functionality to recursively process PHP variables",
956 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
957 | "support": {
958 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
959 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/master"
960 | },
961 | "time": "2016-10-03T07:41:43+00:00"
962 | },
963 | {
964 | "name": "sebastian/version",
965 | "version": "1.0.6",
966 | "source": {
967 | "type": "git",
968 | "url": "https://github.com/sebastianbergmann/version.git",
969 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
970 | },
971 | "dist": {
972 | "type": "zip",
973 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
974 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
975 | "shasum": ""
976 | },
977 | "type": "library",
978 | "autoload": {
979 | "classmap": [
980 | "src/"
981 | ]
982 | },
983 | "notification-url": "https://packagist.org/downloads/",
984 | "license": [
985 | "BSD-3-Clause"
986 | ],
987 | "authors": [
988 | {
989 | "name": "Sebastian Bergmann",
990 | "email": "sebastian@phpunit.de",
991 | "role": "lead"
992 | }
993 | ],
994 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
995 | "homepage": "https://github.com/sebastianbergmann/version",
996 | "support": {
997 | "issues": "https://github.com/sebastianbergmann/version/issues",
998 | "source": "https://github.com/sebastianbergmann/version/tree/1.0.6"
999 | },
1000 | "time": "2015-06-21T13:59:46+00:00"
1001 | },
1002 | {
1003 | "name": "symfony/polyfill-ctype",
1004 | "version": "v1.27.0",
1005 | "source": {
1006 | "type": "git",
1007 | "url": "https://github.com/symfony/polyfill-ctype.git",
1008 | "reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
1009 | },
1010 | "dist": {
1011 | "type": "zip",
1012 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
1013 | "reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
1014 | "shasum": ""
1015 | },
1016 | "require": {
1017 | "php": ">=7.1"
1018 | },
1019 | "provide": {
1020 | "ext-ctype": "*"
1021 | },
1022 | "suggest": {
1023 | "ext-ctype": "For best performance"
1024 | },
1025 | "type": "library",
1026 | "extra": {
1027 | "branch-alias": {
1028 | "dev-main": "1.27-dev"
1029 | },
1030 | "thanks": {
1031 | "name": "symfony/polyfill",
1032 | "url": "https://github.com/symfony/polyfill"
1033 | }
1034 | },
1035 | "autoload": {
1036 | "files": [
1037 | "bootstrap.php"
1038 | ],
1039 | "psr-4": {
1040 | "Symfony\\Polyfill\\Ctype\\": ""
1041 | }
1042 | },
1043 | "notification-url": "https://packagist.org/downloads/",
1044 | "license": [
1045 | "MIT"
1046 | ],
1047 | "authors": [
1048 | {
1049 | "name": "Gert de Pagter",
1050 | "email": "BackEndTea@gmail.com"
1051 | },
1052 | {
1053 | "name": "Symfony Community",
1054 | "homepage": "https://symfony.com/contributors"
1055 | }
1056 | ],
1057 | "description": "Symfony polyfill for ctype functions",
1058 | "homepage": "https://symfony.com",
1059 | "keywords": [
1060 | "compatibility",
1061 | "ctype",
1062 | "polyfill",
1063 | "portable"
1064 | ],
1065 | "support": {
1066 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
1067 | },
1068 | "funding": [
1069 | {
1070 | "url": "https://symfony.com/sponsor",
1071 | "type": "custom"
1072 | },
1073 | {
1074 | "url": "https://github.com/fabpot",
1075 | "type": "github"
1076 | },
1077 | {
1078 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1079 | "type": "tidelift"
1080 | }
1081 | ],
1082 | "time": "2022-11-03T14:55:06+00:00"
1083 | },
1084 | {
1085 | "name": "symfony/yaml",
1086 | "version": "v3.4.47",
1087 | "source": {
1088 | "type": "git",
1089 | "url": "https://github.com/symfony/yaml.git",
1090 | "reference": "88289caa3c166321883f67fe5130188ebbb47094"
1091 | },
1092 | "dist": {
1093 | "type": "zip",
1094 | "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094",
1095 | "reference": "88289caa3c166321883f67fe5130188ebbb47094",
1096 | "shasum": ""
1097 | },
1098 | "require": {
1099 | "php": "^5.5.9|>=7.0.8",
1100 | "symfony/polyfill-ctype": "~1.8"
1101 | },
1102 | "conflict": {
1103 | "symfony/console": "<3.4"
1104 | },
1105 | "require-dev": {
1106 | "symfony/console": "~3.4|~4.0"
1107 | },
1108 | "suggest": {
1109 | "symfony/console": "For validating YAML files using the lint command"
1110 | },
1111 | "type": "library",
1112 | "autoload": {
1113 | "psr-4": {
1114 | "Symfony\\Component\\Yaml\\": ""
1115 | },
1116 | "exclude-from-classmap": [
1117 | "/Tests/"
1118 | ]
1119 | },
1120 | "notification-url": "https://packagist.org/downloads/",
1121 | "license": [
1122 | "MIT"
1123 | ],
1124 | "authors": [
1125 | {
1126 | "name": "Fabien Potencier",
1127 | "email": "fabien@symfony.com"
1128 | },
1129 | {
1130 | "name": "Symfony Community",
1131 | "homepage": "https://symfony.com/contributors"
1132 | }
1133 | ],
1134 | "description": "Symfony Yaml Component",
1135 | "homepage": "https://symfony.com",
1136 | "support": {
1137 | "source": "https://github.com/symfony/yaml/tree/v3.4.47"
1138 | },
1139 | "funding": [
1140 | {
1141 | "url": "https://symfony.com/sponsor",
1142 | "type": "custom"
1143 | },
1144 | {
1145 | "url": "https://github.com/fabpot",
1146 | "type": "github"
1147 | },
1148 | {
1149 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1150 | "type": "tidelift"
1151 | }
1152 | ],
1153 | "time": "2020-10-24T10:57:07+00:00"
1154 | }
1155 | ],
1156 | "aliases": [],
1157 | "minimum-stability": "stable",
1158 | "stability-flags": [],
1159 | "prefer-stable": false,
1160 | "prefer-lowest": false,
1161 | "platform": {
1162 | "php": "^5.4.0|~7.0|~8.0"
1163 | },
1164 | "platform-dev": [],
1165 | "plugin-api-version": "2.3.0"
1166 | }
1167 |
--------------------------------------------------------------------------------
/demo/setup-how-to-integrate.php:
--------------------------------------------------------------------------------
1 | newConfiguration();
29 | $config->setPassword('secret');
30 | $config->setDatabase('project');
31 |
32 | /*
33 | * Step 3:
34 | * Attach the configuration to the library via
35 | * attachConfiguration method
36 | *
37 | * argument 0: configuration object
38 | * argument 1: configuration identifier - default value "default"
39 | */
40 | $KML->attachConfiguration($config, 'demo');
41 |
42 | /*
43 | * Optional Step 4:
44 | * If your project has multiple database endpoints you may
45 | * add more than one configuration to the library.
46 | * If your configuration is similar to previously fiven one
47 | * you may just edit the one created before as that would not
48 | * affect already attached configurations. Alternatively, create
49 | * a new configuration object via newConfiguration() method
50 | */
51 | $config->setDatabase('projet_live');
52 | $KML->attachConfiguration($config, 'live');
53 |
54 | /*
55 | * Step 5:
56 | * You are all setup, start using the library
57 | */
58 |
59 | // to access the "demo" database:
60 | $demo = $KML->connect('demo');
61 | // to access the "live" database:
62 | $live = $KML->connect('live');
63 | // to access the "default" database:
64 | $default = $KML->connect();
65 |
--------------------------------------------------------------------------------
/demo/usage-native-pdo.php:
--------------------------------------------------------------------------------
1 | newConfiguration();
12 | $config->setDatabase('project');
13 |
14 | $KML->attachConfiguration($config);
15 |
16 | /*
17 | * Get the server object
18 | */
19 | $db = $KML->connect();
20 |
21 | /*
22 | * Start using generic PDO functions as per PHP documentation.
23 | */
24 |
25 | // http://php.net/manual/en/pdo.prepare.php
26 | $res = $db->prepare('SELECT * FROM users WHERE email LIKE ?');
27 | $res->execute([
28 | '%ed%'
29 | ]);
30 |
31 | var_dump([
32 | 'count' => $res->rowCount(),
33 | 'one_row' => $res->fetch(),
34 | 'all_rows' => $res->fetchAll()
35 | ]);
36 |
37 | // http://php.net/manual/en/pdo.query.php
38 | $res = $db->query('SELECT * FROM users');
39 |
40 | var_dump([
41 | 'count' => $res->rowCount(),
42 | 'one_row' => $res->fetch(),
43 | 'all_rows' => $res->fetchAll()
44 | ]);
45 |
46 | // etc.., full method view is available at http://php.net/manual/en/class.pdo.php
--------------------------------------------------------------------------------
/demo/usage-query-builder.php:
--------------------------------------------------------------------------------
1 | newConfiguration();
12 | $config->setDatabase('project');
13 |
14 | $KML->attachConfiguration($config);
15 |
16 | /*
17 | * Get the server object
18 | */
19 | $db = $KML->connect();
20 |
21 | // SELECT
22 | // *
23 | // FROM
24 | // users
25 | $db->build('select')
26 | ->from('users')
27 | ->execute();
28 |
29 | // SELECT
30 | // username
31 | // FROM
32 | // users
33 | $db->build('select')
34 | ->column('username')
35 | ->from('users')
36 | ->execute();
37 |
38 | // SELECT
39 | // a.username
40 | // FROM
41 | // users a
42 | // RIGHT JOIN projects b
43 | // ON b.user = a.id
44 | $db->build('select')
45 | ->column('a.username')
46 | ->from('users', 'a')
47 | ->join('projects', 'b', 'right')
48 | ->on('b.user', '=', 'a.id')
49 | ->execute();
50 |
51 | // SELECT
52 | // a.username,
53 | // (
54 | // SELECT
55 | // count(0)
56 | // FROM
57 | // projects b
58 | // WHERE
59 | // b.id = a.id
60 | // )
61 | // FROM
62 | // users a
63 | $db->build('select')
64 | ->column('a.username')
65 | ->subquery(
66 | $db->build('select')
67 | ->raw_column('count(0)')
68 | ->from('projects', 'b')
69 | ->raw_where('b.id', '=', 'a.id')
70 | )
71 | ->from('users', 'a')
72 | ->execute();
73 |
74 | // SELECT
75 | // *
76 | // FROM
77 | // business
78 | // WHERE
79 | // related IN("4","3","1")
80 | $db->build('select')
81 | ->from('business')
82 | ->where_in_values('related', [4, 3, 1])
83 | ->execute();
84 |
85 | // SELECT
86 | // a.name
87 | // FROM
88 | // users a
89 | // WHERE
90 | // a.id IN(
91 | // SELECT
92 | // b.user
93 | // FROM
94 | // projects b
95 | // WHERE
96 | // b.validated = "yes"
97 | // )
98 | $db->build('select')
99 | ->column('a.name')
100 | ->from('users', 'a')
101 | ->where_in_subquery(
102 | 'a.id',
103 | $db->build('select')
104 | ->column('b.user')
105 | ->from('projects', 'b')
106 | ->where('b.validated', '=', 'yes')
107 | )
108 | ->execute();
109 |
110 | // SELECT
111 | // id
112 | // FROM
113 | // users
114 | // WHERE
115 | // (
116 | // created BETWEEN "1485229920" AND "1485249932"
117 | // OR validated = "yes"
118 | // ) AND (
119 | // activated = "yes"
120 | // OR (
121 | // validated = "yes" AND
122 | // single = "no"
123 | // )
124 | // )
125 | $db->build('select')
126 | ->column('id')
127 | ->from('users')
128 | ->open()
129 | ->where('created', 'between', '1485229920', 'and', '1485249932')
130 | ->or_where('validated', '=', 'yes')
131 | ->close()
132 | ->open()
133 | ->where('activated', '=', 'yes')
134 | ->or_open()
135 | ->where('validated', '=', 'yes')
136 | ->where('single', '=', 'no')
137 | ->close()
138 | ->close()
139 | ->execute();
140 |
141 | // UPDATE
142 | // users
143 | // SET
144 | // username = "ed",
145 | // update_count = update_count + 1
146 | // WHERE
147 | // id = 1234
148 | $db->build('update')
149 | ->table('users')
150 | ->set('username', '=', 'ed')
151 | ->set('update_count', '=', 'update_count + 1', true)
152 | ->where('id', '=', '1234')
153 | ->execute();
154 |
155 | // UPDATE
156 | // original a
157 | // INNER JOIN updated b
158 | // ON a.URL = b.URL
159 | // SET a.funded = b.funded,
160 | // a.days = b.days
161 | $db->builder('update')
162 | ->table('original', 'a')
163 | ->join('updated', 'b', 'innser')
164 | ->on('a.URL', '=', 'b.URL')
165 | ->set('a.funded', '=', 'b.funded', true)
166 | ->set('a.days', '=', 'b.days', true)
167 | ->execute();
168 |
169 | // DELETE posts
170 | // FROM posts
171 | // INNER JOIN projects ON projects.project_id = posts.project_id
172 | // WHERE projects.client_id = "312"
173 | $db->builder('delete')
174 | ->column('posts')
175 | ->from('posts')
176 | ->join('projects')
177 | ->on('projects.project_id', '=', 'posts.project_id')
178 | ->where('projects.client_id', '=', "312")
179 | ->execute();
180 |
181 | // INSERT INTO
182 | // table
183 | // (username, password)
184 | // VALUES("ed","w3lcome")
185 | $insert_id = $db->builder('insert')
186 | ->into('table')
187 | ->set('username', 'ed')
188 | ->set('password', 'w3lcome')
189 | ->execute();
190 |
191 | // INSERT IGNORE INTO
192 | // table
193 | // (username, password)
194 | // VALUES("ed","w3lcome")
195 | $insert_id = $db->builder('ignore')
196 | ->into('table')
197 | ->set('username', 'ed')
198 | ->set('password', 'w3lcome')
199 | ->execute();
200 |
201 | // REPLACE INTO
202 | // table
203 | // VALUES("ed","w3lcome")
204 | $insert_id = $db->builder('replace')
205 | ->into('table')
206 | ->value('ed')
207 | ->value('w3lcome')
208 | ->execute();
209 |
--------------------------------------------------------------------------------
/demo/usage-short-cut-methods.php:
--------------------------------------------------------------------------------
1 | newConfiguration();
12 | $config->setDatabase('project');
13 |
14 | $KML->attachConfiguration($config);
15 |
16 | /*
17 | * Get the server object
18 | */
19 | $db = $KML->connect();
20 |
21 | /*
22 | * INSERT INTO users (username, password) VALUES("ed","w3lcome")
23 | */
24 | $insert_id = $db->insert('users', [
25 | 'username' => 'ed',
26 | 'password' => 'w3lcome'
27 | ]);
28 |
29 | /*
30 | * INSERT IGNORE INTO users (username, password) VALUES("ed","w3lcome")
31 | */
32 | $insert_id = $db->ignore('users', [
33 | 'username' => 'ed',
34 | 'password' => 'w3lcome'
35 | ]);
36 |
37 | /*
38 | * REPLACE INTO users (username, password) VALUES("ed","w3lcome")
39 | */
40 | $insert_id = $db->replace('users', [
41 | 'username' => 'ed',
42 | 'password' => 'w3lcome'
43 | ]);
44 |
45 | /*
46 | * DELETE FROM users WHERE username = "ed" AND password = "w3lcome"
47 | */
48 | $db->delete('users', [
49 | 'username' => 'ed',
50 | 'password' => 'w3lcome'
51 | ]);
52 |
53 | /*
54 | * UPDATE users SET username = "edward" WHERE username = "ed" AND password = "w3lcome"
55 | */
56 | $db->update('users', [
57 | 'username' => 'edward'
58 | ], [
59 | 'username' => 'ed',
60 | 'password' => 'w3lcome'
61 | ]);
62 |
--------------------------------------------------------------------------------
/init.php:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 | tests
16 |
17 |
18 |
19 |
20 | src
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Builder.php:
--------------------------------------------------------------------------------
1 | execute();
32 |
33 | return call_user_func_array([$resource, 'fetch'], $options);
34 | }
35 |
36 | // http://php.net/manual/en/pdostatement.fetchall.php
37 | public function fetchAll($fetch_style = null, $fetch_argument = null, $ctor_args = null)
38 | {
39 | $options = [];
40 |
41 | if ($fetch_style !== null) {
42 | $options[] = $fetch_style;
43 | }
44 |
45 | if ($fetch_argument !== null) {
46 | $options[] = $fetch_argument;
47 | }
48 |
49 | if ($ctor_args !== null) {
50 | $options[] = $ctor_args;
51 | }
52 |
53 | $resource = $this->execute();
54 |
55 | return call_user_func_array([$resource, 'fetchAll'], $options);
56 | }
57 |
58 | public function execute($keepParameters = false)
59 | {
60 | if (!$this->compiled) {
61 | $this->compile();
62 | }
63 |
64 | if ($this->server->isLogEnabled()) {
65 | $this->server->logQuery($this->buildFormat, $this->debug());
66 | }
67 |
68 | $native = $this->server->getNativePdo();
69 |
70 | $resource = $native->prepare($this->compiled_query);
71 | $resource->execute($this->compiled_params);
72 |
73 | $this->compiled = false;
74 | $this->compiled_query = '';
75 |
76 | if (!$keepParameters) {
77 | $this->compiled_params = [];
78 | }
79 |
80 | return $resource;
81 | }
82 |
83 | public function debug($return_pdo = false)
84 | {
85 | if (!$this->compiled) {
86 | $this->compile();
87 | }
88 |
89 | $query = $this->compiled_query;
90 |
91 | foreach ($this->compiled_params as $param_key => $param_value) {
92 | if (!is_numeric($param_key)) {
93 | $query = str_replace($param_key, '"' . $param_value . '"', $query);
94 | }
95 | }
96 |
97 | if ($return_pdo) {
98 | return [
99 | 'query' => $this->compiled_query,
100 | 'parameters' => $this->compiled_params
101 | ];
102 | }
103 |
104 | return $query;
105 | }
106 |
107 | protected function clean($variable)
108 | {
109 | $variable = str_replace(['`', ' ', "\n", "\r", "\t"], '', $variable);
110 |
111 | if (strpos($variable, '.') !== false) {
112 | return '`' . str_replace('.', '`.`', $variable) . '`';
113 | }
114 |
115 | return '`' . $variable . '`';
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/src/Builder/Delete.php:
--------------------------------------------------------------------------------
1 | compileIndexActive = hash('crc32', self::$compileIndex);
28 | $this->server = $server;
29 | }
30 |
31 | public function reset()
32 | {
33 | return new self($this->server);
34 | }
35 |
36 | protected function compile()
37 | {
38 | $this->compiled_query = '';
39 | $this->compiled_query .= 'DELETE';
40 |
41 | $raw_column = 0;
42 | $column = 0;
43 | $holder = [];
44 |
45 | foreach ($this->column_indexes as $index) {
46 | list($column_name, $column_alias) = $this->{$index}[$$index++];
47 |
48 | if ($index == 'column') {
49 | $column_name = $this->clean($column_name);
50 | }
51 |
52 | if ($column_alias !== null) {
53 | $column_alias = $this->clean($column_alias);
54 | $holder[] = $column_name . ' AS ' . $column_alias;
55 | } else {
56 | $holder[] = $column_name;
57 | }
58 | }
59 |
60 | if (count($holder)) {
61 | $this->compiled_query .= ' ' . implode(', ', $holder);
62 | }
63 |
64 | $this->compiled_query .= ' FROM';
65 |
66 | $holder = [];
67 | foreach ($this->from as $data) {
68 | $data[0] = $this->clean($data[0]);
69 |
70 | if ($data[1] !== null) {
71 | $data[1] = $this->clean($data[1]);
72 | $holder[] = $data[0] . ' AS ' . $data[1] . '';
73 | } else {
74 | $holder[] = $data[0];
75 | }
76 | }
77 |
78 | $this->compiled_query .= ' ' . implode(', ', $holder);
79 |
80 | foreach ($this->joins as $joinIndex => $joinData) {
81 | list($table, $alias, $format) = $joinData;
82 |
83 | $format = strtoupper($format);
84 | $table = $this->clean($table);
85 |
86 | if ($alias !== null) {
87 | $alias = $this->clean($alias);
88 | $this->compiled_query .= ' ' . $format . ($format ? ' ' : '') . 'JOIN ' . $table . ' AS ' . $alias;
89 | } else {
90 | $this->compiled_query .= ' ' . $format . ($format ? ' ' : '') . 'JOIN ' . $table;
91 | }
92 |
93 | if (isset($this->on[$joinIndex])) {
94 | $holder = '';
95 | foreach ($this->on[$joinIndex] as $on) {
96 | list($field1, $operator, $field2, $statement) = $on;
97 | $holder .= ($holder ? ' ' . $statement : 'ON');
98 |
99 | $field1 = $this->clean($field1);
100 | $field2 = $this->clean($field2);
101 |
102 | $holder .= ' ' . $field1 . ' ' . $operator . ' ' . $field2;
103 | }
104 |
105 | $this->compiled_query .= ' ' . $holder;
106 | }
107 | }
108 |
109 | $raw_where = 0;
110 | $where = 0;
111 | $where_in_values = 0;
112 | $where_in_subquery = 0;
113 |
114 | $holder = '';
115 | $was_change = true;
116 |
117 | foreach ($this->where_indexes as $windex) {
118 | if ($windex == 'and_open' || $windex == 'or_open') {
119 | $holder .= ($holder ? ($windex == 'and_open' ? ' AND ' : ' OR ') : '') . '(';
120 | $was_change = true;
121 | continue;
122 | } elseif ($windex == 'close') {
123 | $holder .= ')';
124 | continue;
125 | } elseif ($windex == 'where') {
126 | list($field, $operator, $value, $format, $values2, $splitter) = $this->{$windex}[$$windex++];
127 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
128 | $was_change = false;
129 |
130 | $field = $this->clean($field);
131 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
132 | $this->compiled_params[$key] = $value;
133 | $holder .= $field . ' ' . $operator . ' ' . $key;
134 |
135 | if ($format !== null) {
136 | $holder .= ' ' . $format;
137 | }
138 |
139 | if ($values2 !== null) {
140 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
141 | $this->compiled_params[$key] = $values2;
142 | $holder .= ' ' . $key;
143 | }
144 | } elseif ($windex == 'raw_where') {
145 | list($field, $operator, $value, $format, $values2, $splitter) = $this->{$windex}[$$windex++];
146 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
147 | $was_change = false;
148 |
149 | $field = $this->clean($field);
150 | $holder .= $field . ' ' . $operator . ' ' . $value;
151 |
152 | if ($format !== null) {
153 | $holder .= ' ' . $format;
154 | }
155 |
156 | if ($values2 !== null) {
157 | $holder .= ' ' . $values2;
158 | }
159 | } elseif ($windex == 'where_in_values') {
160 | list($field, $values, $splitter, $prefix) = $this->{$windex}[$$windex++];
161 | $field = $this->clean($field);
162 |
163 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
164 | $was_change = false;
165 |
166 | $holder .= $field . ($prefix ? ' ' . $prefix : '') . ' IN(';
167 |
168 | $i = 0;
169 | foreach ($values as $index => $value) {
170 | if ($i++) {
171 | $holder .= ', ';
172 | }
173 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
174 | $this->compiled_params[$key] = $value;
175 | $holder .= $key;
176 | }
177 | $holder .= ')';
178 | } elseif ($windex == 'where_in_subquery') {
179 | list($field, $value, $splitter, $prefix) = $this->{$windex}[$$windex++];
180 | $field = $this->clean($field);
181 |
182 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
183 | $was_change = false;
184 |
185 | $holder .= $field . ($prefix ? ' ' . $prefix : '') . ' IN(' . $value . ')';
186 | }
187 | }
188 |
189 | if ($holder) {
190 | $this->compiled_query .= ' WHERE ' . $holder;
191 | }
192 |
193 | $this->compiled = true;
194 | }
195 |
196 | private $raw_column = [];
197 |
198 | public function raw_column($name, $alias = null)
199 | {
200 | $this->compiled = false;
201 | $this->raw_column[] = [$name, $alias];
202 | $this->column_indexes[] = 'raw_column';
203 | return $this;
204 | }
205 |
206 | private $column = [];
207 |
208 | public function column($name, $alias = null)
209 | {
210 | $this->compiled = false;
211 | $this->column[] = [$name, $alias];
212 | $this->column_indexes[] = 'column';
213 | return $this;
214 | }
215 |
216 | public function subquery($query, $alias = null)
217 | {
218 | $this->compiled = false;
219 | if (!is_string($query)) {
220 | if ($query instanceof Select) {
221 | $query = $query->debug(true);
222 | $this->compiled_params = array_merge($this->compiled_params, $query['parameters']);
223 | $query = $query['query'];
224 | } else {
225 | throw new Exception('WHERE IN SUBQUERY requires either a raw sql query string or a SELECT builder that has not been executed.');
226 | }
227 | }
228 |
229 | $this->raw_column[] = ['(' . $query . ')', $alias];
230 | $this->column_indexes[] = 'raw_column';
231 |
232 | return $this;
233 | }
234 |
235 |
236 | private $from = [];
237 |
238 | public function from($name, $alias = null)
239 | {
240 | $this->compiled = false;
241 | $this->from[] = [$name, $alias];
242 | return $this;
243 | }
244 |
245 | private $joins = [];
246 |
247 | public function join($table, $alias = null, $format = 'LEFT')
248 | {
249 | $this->compiled = false;
250 | if (!$format) {
251 | $format = '';
252 | }
253 |
254 | $this->joins[] = [$table, $alias, $format];
255 |
256 | return $this;
257 | }
258 |
259 | private $on = [];
260 |
261 | public function on($field1, $operator, $field2, $format = 'AND')
262 | {
263 | $this->compiled = false;
264 | if (!count($this->joins)) {
265 | throw new Exception('Cannot call query builders ON if there was no join initiated.');
266 | }
267 |
268 | $joinIndex = count($this->joins) - 1;
269 |
270 | if (!isset($this->on[$joinIndex])) {
271 | $this->on[$joinIndex] = [];
272 | }
273 |
274 | $this->on[$joinIndex][] = [$field1, $operator, $field2, strtoupper($format)];
275 |
276 | return $this;
277 | }
278 |
279 | private $where = [];
280 |
281 | public function where($field, $operator, $value, $format = null, $values2 = null, $splitter = 'AND')
282 | {
283 | $this->compiled = false;
284 | $this->where_indexes[] = 'where';
285 | $this->where[] = [$field, $operator, $value, $format, $values2, $splitter];
286 | return $this;
287 | }
288 |
289 | public function or_where($field, $operator, $value, $format = null, $values2 = null)
290 | {
291 | return $this->where($field, $operator, $value, $format, $values2, 'OR');
292 | }
293 |
294 | public function and_where($field, $operator, $value, $format = null, $values2 = null)
295 | {
296 | return $this->where($field, $operator, $value, $format, $values2, 'AND');
297 | }
298 |
299 | private $raw_where = [];
300 |
301 | public function raw_where($field, $operator, $value, $format = null, $values2 = null, $splitter = 'AND')
302 | {
303 | $this->compiled = false;
304 | $this->where_indexes[] = 'raw_where';
305 | $this->raw_where[] = [$field, $operator, $value, $format, $values2, $splitter];
306 | return $this;
307 | }
308 |
309 | public function raw_or_where($field, $operator, $value, $format = null, $values2 = null)
310 | {
311 | return $this->raw_where($field, $operator, $value, $format, $values2, 'OR');
312 | }
313 |
314 | public function raw_and_where($field, $operator, $value, $format = null, $values2 = null)
315 | {
316 | return $this->raw_where($field, $operator, $value, $format, $values2, 'AND');
317 | }
318 |
319 | public function open()
320 | {
321 | $this->compiled = false;
322 | $this->where_indexes[] = 'and_open';
323 | return $this;
324 | }
325 |
326 | public function or_open()
327 | {
328 | $this->compiled = false;
329 | $this->where_indexes[] = 'or_open';
330 | return $this;
331 | }
332 |
333 | public function close()
334 | {
335 | $this->compiled = false;
336 | $this->where_indexes[] = 'close';
337 | return $this;
338 | }
339 |
340 | private $where_in_values = [];
341 |
342 | public function where_in_values($field, array $values, $splitter = 'AND', $prefix = '')
343 | {
344 | $this->compiled = false;
345 |
346 | if (!count($values)) {
347 | throw new Exception('The WHERE_IN_VALUES requires $values array to have values.');
348 | }
349 |
350 | $this->where_indexes[] = 'where_in_values';
351 | $this->where_in_values[] = [$field, $values, $splitter, $prefix];
352 | return $this;
353 | }
354 |
355 | public function or_where_in_values($field, array $values)
356 | {
357 | return $this->where_in_values($field, $values, 'OR');
358 | }
359 |
360 | public function and_where_in_values($field, array $values)
361 | {
362 | return $this->where_in_values($field, $values, 'AND');
363 | }
364 |
365 | public function where_not_in_values($field, array $values, $splitter = 'AND')
366 | {
367 | return $this->where_in_values($field, $values, $splitter, 'NOT');
368 | }
369 |
370 | public function and_where_not_in_values($field, array $values)
371 | {
372 | return $this->where_in_values($field, $values, 'AND', 'NOT');
373 | }
374 |
375 | public function or_where_not_in_values($field, array $values)
376 | {
377 | return $this->where_in_values($field, $values, 'OR', 'NOT');
378 | }
379 |
380 | private $where_in_subquery = [];
381 |
382 | public function where_in_subquery($field, $value, $splitter = 'AND', $prefix = '')
383 | {
384 | $this->compiled = false;
385 |
386 | if (!is_string($value)) {
387 | if ($value instanceof Select) {
388 | $value = $value->debug(true);
389 | $this->compiled_params = array_merge($this->compiled_params, $value['parameters']);
390 | $value = $value['query'];
391 | } else {
392 | throw new Exception('WHERE IN SUBQUERY requires either a raw sql query string or a SELECT builder that has not been executed.');
393 | }
394 | }
395 |
396 | $this->where_indexes[] = 'where_in_subquery';
397 | $this->where_in_subquery[] = [$field, $value, $splitter, $prefix];
398 | return $this;
399 | }
400 |
401 | public function and_where_in_subquery($field, $value)
402 | {
403 | return $this->where_in_subquery($field, $value);
404 | }
405 |
406 | public function or_where_in_subquery($field, $value)
407 | {
408 | return $this->where_in_subquery($field, $value, 'OR');
409 | }
410 |
411 | public function where_not_in_subquery($field, $value)
412 | {
413 | return $this->where_in_subquery($field, $value, 'AND', 'NOT');
414 | }
415 |
416 | public function and_where_not_in_subquery($field, $value)
417 | {
418 | return $this->where_in_subquery($field, $value, 'AND', 'NOT');
419 | }
420 |
421 | public function or_where_not_in_subquery($field, $value)
422 | {
423 | return $this->where_in_subquery($field, $value, 'OR', 'NOT');
424 | }
425 |
426 | }
427 |
--------------------------------------------------------------------------------
/src/Builder/Ignore.php:
--------------------------------------------------------------------------------
1 | options['on_duplicate_key_update'] = !empty($options['on_duplicate_key_update']);
24 | $this->server = $server;
25 | }
26 |
27 | public function into($name)
28 | {
29 | return $this->table($name);
30 | }
31 |
32 | public function table($name)
33 | {
34 | $this->compiled = false;
35 | $this->table = $name;
36 | return $this;
37 | }
38 |
39 | public function set($column, $value)
40 | {
41 | $this->compiled = false;
42 | $this->values[$column] = $value;
43 | return $this;
44 | }
45 |
46 | public function value($value)
47 | {
48 | $this->compiled = false;
49 | $this->values[] = $value;
50 | return $this;
51 | }
52 |
53 | protected function compile()
54 | {
55 | $this->compiled_query = $this->method . ' ';
56 | $this->compiled_params = [];
57 |
58 | $this->compiled_query .= $this->clean($this->table);
59 |
60 | $useColumnKeys = true;
61 | $columnKeys = '';
62 | $queryValues = '';
63 | $updates = [];
64 |
65 | foreach ($this->values as $key => $value) {
66 | $value_key = ':v' . count($this->compiled_params);
67 |
68 | if ($useColumnKeys) {
69 | if (is_numeric($key)) {
70 | $useColumnKeys = false;
71 | } else {
72 | $columnKeys .= ($columnKeys ? ',' : '') . $this->clean($key);
73 |
74 | if (!empty($this->options['on_duplicate_key_update'])) {
75 | $updates[] = $this->clean($key).'='.$value_key;
76 | }
77 | }
78 | }
79 |
80 | $queryValues .= ($queryValues ? ',' : '') . $value_key;
81 | $this->compiled_params[$value_key] = $value;
82 | }
83 |
84 | if ($useColumnKeys) {
85 | $this->compiled_query .= ' (' . $columnKeys . ')';
86 | }
87 |
88 | $this->compiled_query .= ' VALUES(' . $queryValues . ')';
89 |
90 | if($useColumnKeys && !empty($this->options['on_duplicate_key_update']) && count($updates)){
91 | $this->compiled_query .= ' ON DUPLICATE KEY UPDATE '.implode(', ', $updates);
92 | }
93 |
94 | $this->compiled = true;
95 | }
96 |
97 | public function execute($keepParameters = false)
98 | {
99 | parent::execute($keepParameters);
100 | return $this->server->lastInsertId();
101 | }
102 |
103 | }
--------------------------------------------------------------------------------
/src/Builder/Replace.php:
--------------------------------------------------------------------------------
1 | compileIndexActive = hash('crc32', self::$compileIndex);
27 | $this->server = $server;
28 | }
29 |
30 | public function reset()
31 | {
32 | return new self($this->server);
33 | }
34 |
35 | protected function compile()
36 | {
37 | $this->compiled_query = 'SELECT';
38 |
39 | if ($this->distinct) {
40 | if (!count($this->column_indexes)) {
41 | throw new Exception('Cannot use DISTINCT if no columns are selected');
42 | }
43 | $this->compiled_query .= ' DISTINCT';
44 | }
45 |
46 | $raw_column = 0;
47 | $column = 0;
48 | $subquery = 0;
49 | $holder = [];
50 |
51 | if (!count($this->column_indexes)) {
52 | $this->compiled_query .= ' * ';
53 | } else {
54 | foreach ($this->column_indexes as $index) {
55 | list($column_name, $column_alias) = $this->{$index}[$$index++];
56 |
57 | if ($index == 'column') {
58 | $column_name = $this->clean($column_name);
59 | }
60 |
61 | if ($column_alias !== null) {
62 | $column_alias = $this->clean($column_alias);
63 | $holder[] = $column_name . ' AS ' . $column_alias;
64 | } else {
65 | $holder[] = $column_name;
66 | }
67 | }
68 |
69 | if (count($holder)) {
70 | $this->compiled_query .= ' ' . implode(', ', $holder);
71 | }
72 | }
73 |
74 | $this->compiled_query .= ' FROM';
75 |
76 | $holder = [];
77 | foreach ($this->from as $data) {
78 | $data[0] = $this->clean($data[0]);
79 |
80 | if ($data[1] !== null) {
81 | $data[1] = $this->clean($data[1]);
82 | $holder[] = $data[0] . ' AS ' . $data[1] . '';
83 | } else {
84 | $holder[] = $data[0];
85 | }
86 | }
87 |
88 | $this->compiled_query .= ' ' . implode(', ', $holder);
89 |
90 | foreach ($this->joins as $joinIndex => $joinData) {
91 | list($table, $alias, $format) = $joinData;
92 |
93 | $format = strtoupper($format);
94 | $table = $this->clean($table);
95 |
96 | if ($alias !== null) {
97 | $alias = $this->clean($alias);
98 | $this->compiled_query .= ' ' . $format . ($format ? ' ' : '') . 'JOIN ' . $table . ' AS ' . $alias;
99 | } else {
100 | $this->compiled_query .= ' ' . $format . ($format ? ' ' : '') . 'JOIN ' . $table;
101 | }
102 |
103 | if (isset($this->on[$joinIndex])) {
104 | $holder = '';
105 | foreach ($this->on[$joinIndex] as $on) {
106 | list($field1, $operator, $field2, $statement, $applyAsString) = $on;
107 | $holder .= ($holder ? ' ' . $statement : 'ON');
108 |
109 | $field1 = $this->clean($field1);
110 | $field2 = $applyAsString === false ? $this->clean($field2) : $field2;
111 |
112 | $holder .= ' ' . $field1 . ' ' . $operator . ' ' . $field2;
113 | }
114 |
115 | $this->compiled_query .= ' ' . $holder;
116 | }
117 | }
118 |
119 | $raw_where = 0;
120 | $where = 0;
121 | $where_in_values = 0;
122 | $where_in_subquery = 0;
123 |
124 | $holder = '';
125 | $was_change = true;
126 |
127 | foreach ($this->where_indexes as $windex) {
128 | if ($windex == 'and_open' || $windex == 'or_open') {
129 | $holder .= ($holder ? ($windex == 'and_open' ? ' AND ' : ' OR ') : '') . '(';
130 | $was_change = true;
131 | continue;
132 | } elseif ($windex == 'close') {
133 | $holder .= ')';
134 | continue;
135 | } elseif ($windex == 'where') {
136 | list($field, $operator, $value, $format, $values2, $splitter) = $this->{$windex}[$$windex++];
137 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
138 | $was_change = false;
139 |
140 | $field = $this->clean($field);
141 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
142 | $this->compiled_params[$key] = $value;
143 | $holder .= $field . ' ' . $operator . ' ' . $key;
144 |
145 | if ($format !== null) {
146 | $holder .= ' ' . $format;
147 | }
148 |
149 | if ($values2 !== null) {
150 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
151 | $this->compiled_params[$key] = $values2;
152 | $holder .= ' ' . $key;
153 | }
154 | } elseif ($windex == 'raw_where') {
155 | list($field, $operator, $value, $format, $values2, $splitter) = $this->{$windex}[$$windex++];
156 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
157 | $was_change = false;
158 |
159 | $field = $this->clean($field);
160 | $holder .= $field . ' ' . $operator . ' ' . $value;
161 |
162 | if ($format !== null) {
163 | $holder .= ' ' . $format;
164 | }
165 |
166 | if ($values2 !== null) {
167 | $holder .= ' ' . $values2;
168 | }
169 | } elseif ($windex == 'where_in_values') {
170 | list($field, $values, $splitter, $prefix) = $this->{$windex}[$$windex++];
171 | $field = $this->clean($field);
172 |
173 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
174 | $was_change = false;
175 |
176 | $holder .= $field . ($prefix ? ' ' . $prefix : '') . ' IN(';
177 |
178 | $i = 0;
179 | foreach ($values as $index => $value) {
180 | if ($i++) {
181 | $holder .= ', ';
182 | }
183 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
184 | $this->compiled_params[$key] = $value;
185 | $holder .= $key;
186 | }
187 | $holder .= ')';
188 | } elseif ($windex == 'where_in_subquery') {
189 | list($field, $value, $splitter, $prefix) = $this->{$windex}[$$windex++];
190 | $field = $this->clean($field);
191 |
192 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
193 | $was_change = false;
194 |
195 | $holder .= $field . ($prefix ? ' ' . $prefix : '') . ' IN(' . $value . ')';
196 | }
197 | }
198 |
199 | if ($holder) {
200 | $this->compiled_query .= ' WHERE ' . $holder;
201 | }
202 |
203 | if (count($this->group_by) || count($this->raw_group_by)) {
204 | $this->compiled_query .= ' GROUP BY';
205 | $holder = '';
206 | foreach ($this->group_by as $column) {
207 | $column = $this->clean($column);
208 | $holder .= ($holder ? ', ' : '') . $column;
209 | }
210 | foreach ($this->raw_group_by as $column) {
211 | $holder .= ($holder ? ', ' : '') . $column;
212 | }
213 | $this->compiled_query .= ' ' . $holder;
214 | }
215 |
216 | if (count($this->order_by)) {
217 | $this->compiled_query .= ' ORDER BY';
218 | $holder = '';
219 | foreach ($this->order_by as $column) {
220 | list($name, $direction) = $column;
221 |
222 | $name = $this->clean($name);
223 | $holder .= ($holder ? ', ' : '') . $name . ' ' . strtoupper($direction);
224 | }
225 | $this->compiled_query .= ' ' . $holder;
226 | }
227 |
228 | if ($this->offset !== null && $this->limit !== null) {
229 | $this->compiled_query .= ' LIMIT ' . strval($this->offset) . ',' . strval($this->limit);
230 | } elseif ($this->offset !== null) {
231 | $this->compiled_query .= ' OFFSET ' . strval($this->offset);
232 | } elseif ($this->limit !== null) {
233 | $this->compiled_query .= ' LIMIT ' . strval($this->limit);
234 | }
235 |
236 | $this->compiled = true;
237 | }
238 |
239 | private $distinct = false;
240 |
241 | public function distinct()
242 | {
243 | $this->compiled = false;
244 | $this->distinct = true;
245 | return $this;
246 | }
247 |
248 | private $raw_column = [];
249 |
250 | public function raw_column($name, $alias = null)
251 | {
252 | $this->compiled = false;
253 | $this->raw_column[] = [$name, $alias];
254 | $this->column_indexes[] = 'raw_column';
255 | return $this;
256 | }
257 |
258 | private $column = [];
259 |
260 | public function column($name, $alias = null)
261 | {
262 | $this->compiled = false;
263 | $this->column[] = [$name, $alias];
264 | $this->column_indexes[] = 'column';
265 | return $this;
266 | }
267 |
268 | public function reset_column()
269 | {
270 | $this->compiled = false;
271 | $this->raw_column = [];
272 | $this->column = [];
273 | $this->column_indexes = [];
274 | return $this;
275 | }
276 |
277 | public function subquery($query, $alias = null)
278 | {
279 | $this->compiled = false;
280 | if (!is_string($query)) {
281 | if ($query instanceof Select) {
282 | $query = $query->debug(true);
283 | $this->compiled_params = array_merge($this->compiled_params, $query['parameters']);
284 | $query = $query['query'];
285 | } else {
286 | throw new Exception('WHERE IN SUBQUERY requires either a raw sql query string or a SELECT builder that has not been executed.');
287 | }
288 | }
289 |
290 | $this->raw_column[] = ['(' . $query . ')', $alias];
291 | $this->column_indexes[] = 'raw_column';
292 |
293 | return $this;
294 | }
295 |
296 |
297 | private $from = [];
298 |
299 | public function from($name, $alias = null)
300 | {
301 | $this->compiled = false;
302 | $this->from[] = [$name, $alias];
303 | return $this;
304 | }
305 |
306 | private $joins = [];
307 |
308 | public function join($table, $alias = null, $format = 'LEFT')
309 | {
310 | $this->compiled = false;
311 | if (!$format) {
312 | $format = '';
313 | }
314 |
315 | $this->joins[] = [$table, $alias, $format];
316 |
317 | return $this;
318 | }
319 |
320 | private $on = [];
321 |
322 | public function on($field1, $operator, $field2, $format = 'AND', $applyAsString = false)
323 | {
324 | $this->compiled = false;
325 | if (!count($this->joins)) {
326 | throw new Exception('Cannot call query builders ON if there was no join initiated.');
327 | }
328 |
329 | $joinIndex = count($this->joins) - 1;
330 |
331 | if (!isset($this->on[$joinIndex])) {
332 | $this->on[$joinIndex] = [];
333 | }
334 |
335 | $this->on[$joinIndex][] = [$field1, $operator, $field2, strtoupper($format), boolval($applyAsString)];
336 |
337 | return $this;
338 | }
339 |
340 | private $where = [];
341 |
342 | public function where($field, $operator, $value, $format = null, $values2 = null, $splitter = 'AND')
343 | {
344 | $this->compiled = false;
345 | $this->where_indexes[] = 'where';
346 | $this->where[] = [$field, $operator, $value, $format, $values2, $splitter];
347 | return $this;
348 | }
349 |
350 | public function or_where($field, $operator, $value, $format = null, $values2 = null)
351 | {
352 | return $this->where($field, $operator, $value, $format, $values2, 'OR');
353 | }
354 |
355 | public function and_where($field, $operator, $value, $format = null, $values2 = null)
356 | {
357 | return $this->where($field, $operator, $value, $format, $values2, 'AND');
358 | }
359 |
360 | private $raw_where = [];
361 |
362 | public function raw_where($field, $operator, $value, $format = null, $values2 = null, $splitter = 'AND')
363 | {
364 | $this->compiled = false;
365 | $this->where_indexes[] = 'raw_where';
366 | $this->raw_where[] = [$field, $operator, $value, $format, $values2, $splitter];
367 | return $this;
368 | }
369 |
370 | public function raw_or_where($field, $operator, $value, $format = null, $values2 = null)
371 | {
372 | return $this->raw_where($field, $operator, $value, $format, $values2, 'OR');
373 | }
374 |
375 | public function raw_and_where($field, $operator, $value, $format = null, $values2 = null)
376 | {
377 | return $this->raw_where($field, $operator, $value, $format, $values2, 'AND');
378 | }
379 |
380 | public function open()
381 | {
382 | $this->compiled = false;
383 | $this->where_indexes[] = 'and_open';
384 | return $this;
385 | }
386 |
387 | public function or_open()
388 | {
389 | $this->compiled = false;
390 | $this->where_indexes[] = 'or_open';
391 | return $this;
392 | }
393 |
394 | public function close()
395 | {
396 | $this->compiled = false;
397 | $this->where_indexes[] = 'close';
398 | return $this;
399 | }
400 |
401 | private $where_in_values = [];
402 |
403 | public function where_in_values($field, array $values, $splitter = 'AND', $prefix = '')
404 | {
405 | $this->compiled = false;
406 | if (!count($values)) {
407 | throw new Exception('The WHERE_IN_VALUES requires $values array to have values.');
408 | }
409 |
410 | $this->where_indexes[] = 'where_in_values';
411 | $this->where_in_values[] = [$field, $values, $splitter, $prefix];
412 | return $this;
413 | }
414 |
415 | public function or_where_in_values($field, array $values)
416 | {
417 | return $this->where_in_values($field, $values, 'OR');
418 | }
419 |
420 | public function and_where_in_values($field, array $values)
421 | {
422 | return $this->where_in_values($field, $values, 'AND');
423 | }
424 |
425 | public function where_not_in_values($field, array $values, $splitter = 'AND')
426 | {
427 | return $this->where_in_values($field, $values, $splitter, 'NOT');
428 | }
429 |
430 | public function and_where_not_in_values($field, array $values)
431 | {
432 | return $this->where_in_values($field, $values, 'AND', 'NOT');
433 | }
434 |
435 | public function or_where_not_in_values($field, array $values)
436 | {
437 | return $this->where_in_values($field, $values, 'OR', 'NOT');
438 | }
439 |
440 | private $where_in_subquery = [];
441 |
442 | public function where_in_subquery($field, $value, $splitter = 'AND', $prefix = '')
443 | {
444 | $this->compiled = false;
445 | if (!is_string($value)) {
446 | if ($value instanceof Select) {
447 | $value = $value->debug(true);
448 | $this->compiled_params = array_merge($this->compiled_params, $value['parameters']);
449 | $value = $value['query'];
450 | } else {
451 | throw new Exception('WHERE IN SUBQUERY requires either a raw sql query string or a SELECT builder that has not been executed.');
452 | }
453 | }
454 |
455 | $this->where_indexes[] = 'where_in_subquery';
456 | $this->where_in_subquery[] = [$field, $value, $splitter, $prefix];
457 | return $this;
458 | }
459 |
460 | public function and_where_in_subquery($field, $value)
461 | {
462 | return $this->where_in_subquery($field, $value);
463 | }
464 |
465 | public function or_where_in_subquery($field, $value)
466 | {
467 | return $this->where_in_subquery($field, $value, 'OR');
468 | }
469 |
470 | public function where_not_in_subquery($field, $value, $splitter = 'AND')
471 | {
472 | return $this->where_in_subquery($field, $value, $splitter, 'NOT');
473 | }
474 |
475 | public function and_where_not_in_subquery($field, $value)
476 | {
477 | return $this->where_in_subquery($field, $value, 'AND', 'NOT');
478 | }
479 |
480 | public function or_where_not_in_subquery($field, $value)
481 | {
482 | return $this->where_in_subquery($field, $value, 'OR', 'NOT');
483 | }
484 |
485 | private $group_by = [];
486 |
487 | public function group_by($column)
488 | {
489 | $this->compiled = false;
490 | $this->group_by[] = $column;
491 | return $this;
492 | }
493 |
494 | private $raw_group_by = [];
495 |
496 | public function raw_group_by($column)
497 | {
498 | $this->compiled = false;
499 | $this->raw_group_by[] = $column;
500 | return $this;
501 | }
502 |
503 | private $order_by = [];
504 |
505 | public function order_by($column, $direction)
506 | {
507 | $this->compiled = false;
508 | $direction = strtolower($direction);
509 |
510 | if (!in_array($direction, ['asc', 'desc'])) {
511 | throw new Exception('ORDER BY ' . $column . ' - the given direction "' . $direction . '" is not valid, provide ASC or DESC');
512 | }
513 |
514 | $this->order_by[] = [$column, $direction];
515 | return $this;
516 | }
517 |
518 | private $offset = null;
519 |
520 | public function offset($offset)
521 | {
522 | $this->compiled = false;
523 | if (!is_numeric($offset)) {
524 | throw new Exception('Offset must be an integer.');
525 | }
526 | $this->offset = $offset;
527 | return $this;
528 | }
529 |
530 | private $limit = null;
531 |
532 | public function limit($limit)
533 | {
534 | $this->compiled = false;
535 | if (!is_numeric($limit)) {
536 | throw new Exception('Offset must be an integer.');
537 | }
538 | $this->limit = $limit;
539 | return $this;
540 | }
541 |
542 | }
543 |
--------------------------------------------------------------------------------
/src/Builder/Update.php:
--------------------------------------------------------------------------------
1 | compileIndexActive = hash('crc32', self::$compileIndex);
26 | $this->server = $server;
27 | }
28 |
29 | public function reset()
30 | {
31 | return new self($this->server);
32 | }
33 |
34 | protected function compile()
35 | {
36 | $this->compiled_query .= 'UPDATE';
37 |
38 | $holder = [];
39 | foreach ($this->table as $data) {
40 | $data[0] = $this->clean($data[0]);
41 |
42 | if ($data[1] !== null) {
43 | $data[1] = $this->clean($data[1]);
44 | $holder[] = $data[0] . ' AS ' . $data[1] . '';
45 | } else {
46 | $holder[] = $data[0];
47 | }
48 | }
49 |
50 | $this->compiled_query .= ' ' . implode(', ', $holder);
51 |
52 | foreach ($this->joins as $joinIndex => $joinData) {
53 | list($table, $alias, $format) = $joinData;
54 |
55 | $format = strtoupper($format);
56 | $table = $this->clean($table);
57 |
58 | if ($alias !== null) {
59 | $alias = $this->clean($alias);
60 | $this->compiled_query .= ' ' . $format . ($format ? ' ' : '') . 'JOIN ' . $table . ' AS ' . $alias;
61 | } else {
62 | $this->compiled_query .= ' ' . $format . ($format ? ' ' : '') . 'JOIN ' . $table;
63 | }
64 |
65 | if (isset($this->on[$joinIndex])) {
66 | $holder = '';
67 | foreach ($this->on[$joinIndex] as $on) {
68 | list($field1, $operator, $field2, $statement) = $on;
69 | $holder .= ($holder ? ' ' . $statement : 'ON');
70 |
71 | $field1 = $this->clean($field1);
72 | $field2 = $this->clean($field2);
73 |
74 | $holder .= ' ' . $field1 . ' ' . $operator . ' ' . $field2;
75 | }
76 |
77 | $this->compiled_query .= ' ' . $holder;
78 | }
79 | }
80 |
81 | $holder = [];
82 |
83 | foreach ($this->set as $set) {
84 | list($column, $operator, $value, $rawValue) = $set;
85 |
86 | if ($rawValue) {
87 | $key = $value;
88 | } else {
89 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
90 | $this->compiled_params[$key] = $value;
91 | }
92 |
93 | $column = $this->clean($column);
94 | $holder[] = $column . ' ' . $operator . ' ' . $key;
95 | }
96 |
97 | if (!count($holder)) {
98 | throw new Exception('UPDATE build failed, no SET parameters given');
99 | }
100 |
101 | $this->compiled_query .= ' SET ' . implode(', ', $holder);
102 |
103 | $raw_where = 0;
104 | $where = 0;
105 | $where_in_values = 0;
106 | $where_in_subquery = 0;
107 |
108 | $holder = '';
109 | $was_change = true;
110 |
111 | foreach ($this->where_indexes as $windex) {
112 | if ($windex == 'and_open' || $windex == 'or_open') {
113 | $holder .= ($holder ? ($windex == 'and_open' ? ' AND ' : ' OR ') : '') . '(';
114 | $was_change = true;
115 | continue;
116 | } elseif ($windex == 'close') {
117 | $holder .= ')';
118 | continue;
119 | } elseif ($windex == 'where') {
120 | list($field, $operator, $value, $format, $values2, $splitter) = $this->{$windex}[$$windex++];
121 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
122 | $was_change = false;
123 |
124 | $field = $this->clean($field);
125 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
126 | $this->compiled_params[$key] = $value;
127 | $holder .= $field . ' ' . $operator . ' ' . $key;
128 |
129 | if ($format !== null) {
130 | $holder .= ' ' . $format;
131 | }
132 |
133 | if ($values2 !== null) {
134 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
135 | $this->compiled_params[$key] = $values2;
136 | $holder .= ' ' . $key;
137 | }
138 | } elseif ($windex == 'raw_where') {
139 | list($field, $operator, $value, $format, $values2, $splitter) = $this->{$windex}[$$windex++];
140 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
141 | $was_change = false;
142 |
143 | $field = $this->clean($field);
144 | $holder .= $field . ' ' . $operator . ' ' . $value;
145 |
146 | if ($format !== null) {
147 | $holder .= ' ' . $format;
148 | }
149 |
150 | if ($values2 !== null) {
151 | $holder .= ' ' . $values2;
152 | }
153 | } elseif ($windex == 'where_in_values') {
154 | list($field, $values, $splitter, $prefix) = $this->{$windex}[$$windex++];
155 | $field = $this->clean($field);
156 |
157 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
158 | $was_change = false;
159 |
160 | $holder .= $field . ($prefix ? ' ' . $prefix : '') . ' IN(';
161 |
162 | $i = 0;
163 | foreach ($values as $index => $value) {
164 | if ($i++) {
165 | $holder .= ', ';
166 | }
167 | $key = ':c' . $this->compileIndexActive . 'v' . hash('crc32', count($this->compiled_params));
168 | $this->compiled_params[$key] = $value;
169 | $holder .= $key;
170 | }
171 | $holder .= ')';
172 | } elseif ($windex == 'where_in_subquery') {
173 | list($field, $value, $splitter, $prefix) = $this->{$windex}[$$windex++];
174 | $field = $this->clean($field);
175 |
176 | $holder .= ($was_change ? '' : ' ' . $splitter . ' ');
177 | $was_change = false;
178 |
179 | $holder .= $field . ($prefix ? ' ' . $prefix : '') . ' IN(' . $value . ')';
180 | }
181 | }
182 |
183 | if ($holder) {
184 | $this->compiled_query .= ' WHERE ' . $holder;
185 | }
186 |
187 | $this->compiled = true;
188 | }
189 |
190 | private $table = [];
191 |
192 | public function table($name, $alias = null)
193 | {
194 | $this->compiled = false;
195 | $this->table[] = [$name, $alias];
196 | return $this;
197 | }
198 |
199 | private $joins = [];
200 |
201 | public function join($table, $alias = null, $format = 'LEFT')
202 | {
203 | $this->compiled = false;
204 | if (!$format) {
205 | $format = '';
206 | }
207 |
208 | $this->joins[] = [$table, $alias, $format];
209 |
210 | return $this;
211 | }
212 |
213 | private $on = [];
214 |
215 | public function on($field1, $operator, $field2, $format = 'AND')
216 | {
217 | $this->compiled = false;
218 | if (!count($this->joins)) {
219 | throw new Exception('Cannot call query builders ON if there was no join initiated.');
220 | }
221 |
222 | $joinIndex = count($this->joins) - 1;
223 |
224 | if (!isset($this->on[$joinIndex])) {
225 | $this->on[$joinIndex] = [];
226 | }
227 |
228 | $this->on[$joinIndex][] = [$field1, $operator, $field2, strtoupper($format)];
229 |
230 | return $this;
231 | }
232 |
233 | private $where = [];
234 |
235 | public function where($field, $operator, $value, $format = null, $values2 = null, $splitter = 'AND')
236 | {
237 | $this->compiled = false;
238 | $this->where_indexes[] = 'where';
239 | $this->where[] = [$field, $operator, $value, $format, $values2, $splitter];
240 | return $this;
241 | }
242 |
243 | public function or_where($field, $operator, $value, $format = null, $values2 = null)
244 | {
245 | return $this->where($field, $operator, $value, $format, $values2, 'OR');
246 | }
247 |
248 | public function and_where($field, $operator, $value, $format = null, $values2 = null)
249 | {
250 | return $this->where($field, $operator, $value, $format, $values2, 'AND');
251 | }
252 |
253 | private $raw_where = [];
254 |
255 | public function raw_where($field, $operator, $value, $format = null, $values2 = null, $splitter = 'AND')
256 | {
257 | $this->compiled = false;
258 | $this->where_indexes[] = 'raw_where';
259 | $this->raw_where[] = [$field, $operator, $value, $format, $values2, $splitter];
260 | return $this;
261 | }
262 |
263 | public function raw_or_where($field, $operator, $value, $format = null, $values2 = null)
264 | {
265 | return $this->raw_where($field, $operator, $value, $format, $values2, 'OR');
266 | }
267 |
268 | public function raw_and_where($field, $operator, $value, $format = null, $values2 = null)
269 | {
270 | return $this->raw_where($field, $operator, $value, $format, $values2, 'AND');
271 | }
272 |
273 | public function open()
274 | {
275 | $this->where_indexes[] = 'and_open';
276 | return $this;
277 | }
278 |
279 | public function or_open()
280 | {
281 | $this->where_indexes[] = 'or_open';
282 | return $this;
283 | }
284 |
285 | public function close()
286 | {
287 | $this->where_indexes[] = 'close';
288 | return $this;
289 | }
290 |
291 | private $where_in_values = [];
292 |
293 | public function where_in_values($field, array $values, $splitter = 'AND', $prefix = '')
294 | {
295 | $this->compiled = false;
296 | if (!count($values)) {
297 | throw new Exception('The WHERE_IN_VALUES requires $values array to have values.');
298 | }
299 |
300 | $this->where_indexes[] = 'where_in_values';
301 | $this->where_in_values[] = [$field, $values, $splitter, $prefix];
302 | return $this;
303 | }
304 |
305 | public function or_where_in_values($field, array $values)
306 | {
307 | return $this->where_in_values($field, $values, 'OR');
308 | }
309 |
310 | public function and_where_in_values($field, array $values)
311 | {
312 | return $this->where_in_values($field, $values, 'AND');
313 | }
314 |
315 | public function where_not_in_values($field, array $values, $splitter = 'AND')
316 | {
317 | return $this->where_in_values($field, $values, $splitter, 'NOT');
318 | }
319 |
320 | public function and_where_not_in_values($field, array $values)
321 | {
322 | return $this->where_in_values($field, $values, 'AND', 'NOT');
323 | }
324 |
325 | public function or_where_not_in_values($field, array $values)
326 | {
327 | return $this->where_in_values($field, $values, 'OR', 'NOT');
328 | }
329 |
330 | private $where_in_subquery = [];
331 |
332 | public function where_in_subquery($field, $value, $splitter = 'AND', $prefix = '')
333 | {
334 | $this->compiled = false;
335 | if (!is_string($value)) {
336 | if ($value instanceof Select) {
337 | $value = $value->debug(true);
338 | $this->compiled_params = array_merge($this->compiled_params, $value['parameters']);
339 | $value = $value['query'];
340 | } else {
341 | throw new Exception('WHERE IN SUBQUERY requires either a raw sql query string or a SELECT builder that has not been executed.');
342 | }
343 | }
344 |
345 | $this->where_indexes[] = 'where_in_subquery';
346 | $this->where_in_subquery[] = [$field, $value, $splitter, $prefix];
347 | return $this;
348 | }
349 |
350 | public function and_where_in_subquery($field, $value)
351 | {
352 | return $this->where_in_subquery($field, $value);
353 | }
354 |
355 | public function or_where_in_subquery($field, $value)
356 | {
357 | return $this->where_in_subquery($field, $value, 'OR');
358 | }
359 |
360 | public function where_not_in_subquery($field, $value)
361 | {
362 | return $this->where_in_subquery($field, $value, 'AND', 'NOT');
363 | }
364 |
365 | public function and_where_not_in_subquery($field, $value)
366 | {
367 | return $this->where_in_subquery($field, $value, 'AND', 'NOT');
368 | }
369 |
370 | public function or_where_not_in_subquery($field, $value)
371 | {
372 | return $this->where_in_subquery($field, $value, 'OR', 'NOT');
373 | }
374 |
375 | private $set = [];
376 |
377 | public function set($column, $operator, $value, $rawValue = false)
378 | {
379 | $this->compiled = false;
380 | $this->set[] = [$column, $operator, $value, $rawValue];
381 | return $this;
382 | }
383 |
384 | }
385 |
--------------------------------------------------------------------------------
/src/Configuration.php:
--------------------------------------------------------------------------------
1 | $prop;
37 | }
38 |
39 | if (substr($method, 0, 3) == 'set') {
40 | $prop = strtolower(substr($method, 3));
41 | if (!property_exists($this, $prop)) {
42 | throw new Exception('Trying to set an unknown configuration variable: ' . $prop);
43 | }
44 | if (!isset($arguments[0])) {
45 | throw new Exception('Trying to set configuration variable ' . $prop . ' without providing its value.');
46 | }
47 | $this->$prop = $arguments[0];
48 | return $this;
49 | }
50 |
51 | throw new Exception('Trying to call an unknown configuration method: ' . $method);
52 | }
53 |
54 | public function attach()
55 | {
56 | $class = new self(get_object_vars($this));
57 | return $class;
58 | }
59 |
60 | public function __construct($properties = [])
61 | {
62 | if (!count($properties)) {
63 | return;
64 | }
65 |
66 | foreach ($properties as $property => $value) {
67 | $this->$property = $value;
68 | }
69 | }
70 |
71 | }
--------------------------------------------------------------------------------
/src/Helpers.php:
--------------------------------------------------------------------------------
1 | !empty($options['on_duplicate_key_update']),
12 | ];
13 |
14 | $builder = $this->build($type, $options)->into($table);
15 |
16 | foreach ($values as $key => $value) {
17 | if (is_numeric($key)) {
18 | $builder->value($value);
19 | } else {
20 | $builder->set($key, $value);
21 | }
22 | }
23 |
24 | return $builder->execute();
25 | }
26 |
27 | public function insert($table, array $values = [], array $options = [])
28 | {
29 | return $this->__call_insert($table, $values, 'insert', $options);
30 | }
31 |
32 | public function ignore($table, array $values = [])
33 | {
34 | return $this->__call_insert($table, $values, 'ignore');
35 | }
36 |
37 | public function replace($table, array $values = [])
38 | {
39 | return $this->__call_insert($table, $values, 'replace');
40 | }
41 |
42 | public function delete($table, array $values = [])
43 | {
44 | $builder = $this->build('delete')->from($table);
45 |
46 | foreach ($values as $key => $value) {
47 | $builder->where($key, '=', $value);
48 | }
49 |
50 | $builder->execute();
51 | }
52 |
53 | public function update($table, array $set = [], array $where = [])
54 | {
55 | $builder = $this->build('update')->table($table);
56 |
57 | foreach ($set as $key => $value) {
58 | $builder->set($key, '=', $value);
59 | }
60 |
61 | foreach ($where as $key => $value) {
62 | $builder->where($key, '=', $value);
63 | }
64 |
65 | $builder->execute();
66 | }
67 |
68 | public function replaceMany($table, array $input, $get_query = false, $database = null){
69 | return $this->insertMany($table, $input, $get_query, $database, 'replace');
70 | }
71 |
72 | public function ignoreMany($table, array $input, $get_query = false, $database = null){
73 | return $this->insertMany($table, $input, $get_query, $database, 'insert ignore');
74 | }
75 |
76 | public function insertMany($table, array $input, $get_query = false, $database = null, $method = 'insert')
77 | {
78 | if (empty($input)) {
79 | return false;
80 | }
81 |
82 | $table = str_replace('.', '`.`', $table);
83 |
84 | $keys = [];
85 | $values = [];
86 | $data = [];
87 | $rows = count($input);
88 | $columns = count(reset($input));
89 |
90 | $query = $method . ' INTO ' . ($database !== null ? '`' . $database . '`.' : '') . '`' . $table . '` (';
91 |
92 | foreach (reset($input) as $key => $value) {
93 | $keys[] = '`' . $key . '`';
94 | }
95 |
96 | $query .= implode(',', $keys) . ') VALUES';
97 |
98 | foreach ($input as $index => $row)
99 | {
100 | foreach ($row as $key => $value)
101 | {
102 | $keyName = ':v' . $index . $key;
103 | $values[] = $keyName;
104 | $data[$keyName] = $value;
105 | }
106 |
107 | if ($index != 0) {
108 | $query .= ',';
109 | }
110 |
111 | $query .= ' (' . implode(',', $values) . ')';
112 |
113 | $values = [];
114 | }
115 |
116 | if ($get_query) {
117 | foreach ($data as $key => $value) {
118 | $query = str_replace($key, "'".str_replace("'","\\\'", $value), $query);
119 | }
120 | return $query;
121 | }
122 |
123 | $db = $this->prepare($query);
124 | $db->execute($data);
125 | }
126 | }
--------------------------------------------------------------------------------
/src/Library.php:
--------------------------------------------------------------------------------
1 | attach();
30 |
31 | return $this;
32 | }
33 |
34 | private static $connections = [];
35 |
36 | public function hasAttached($id)
37 | {
38 | return !empty(self::$configurationDetails[$id]);
39 | }
40 |
41 | public function connect($connection_id = 'default')
42 | {
43 | if (!isset(self::$connections[$connection_id])) {
44 | if (!isset(self::$configurationDetails[$connection_id])) {
45 | throw new Exception('Provided database connection id "' . $connection_id . '" has not been attached');
46 | }
47 | self::$connections[$connection_id] = new Server(self::$configurationDetails[$connection_id]);
48 | }
49 |
50 | return self::$connections[$connection_id];
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/src/Native.php:
--------------------------------------------------------------------------------
1 | isLogEnabled()) {
17 | $this->logQuery('native-pdo[beginTransaction]', '');
18 | }
19 | return $this->createPDO()->beginTransaction();
20 | }
21 |
22 | // http://php.net/manual/en/pdo.commit.php
23 | public function commit()
24 | {
25 | if ($this->isLogEnabled()) {
26 | $this->logQuery('native-pdo[commit]', '');
27 | }
28 | return $this->createPDO()->commit();
29 | }
30 |
31 | // http://php.net/manual/en/pdo.errorcode.php
32 | public function errorCode()
33 | {
34 | if ($this->isLogEnabled()) {
35 | $this->logQuery('native-pdo[errorCode]', '');
36 | }
37 | return $this->createPDO()->errorCode();
38 | }
39 |
40 | // http://php.net/manual/en/pdo.errorinfo.php
41 | public function errorInfo()
42 | {
43 | if ($this->isLogEnabled()) {
44 | $this->logQuery('native-pdo[errorInfo]', '');
45 | }
46 | return $this->createPDO()->errorInfo();
47 | }
48 |
49 | // http://php.net/manual/en/pdo.exec.php
50 | public function exec($statement)
51 | {
52 | if ($this->isLogEnabled()) {
53 | $this->logQuery('native-pdo[errorInfo]', $statement);
54 | }
55 | return $this->createPDO()->exec($statement);
56 | }
57 |
58 | // http://php.net/manual/en/pdo.getattribute.php
59 | public function getAttribute($attribute)
60 | {
61 | if ($this->isLogEnabled()) {
62 | $this->logQuery('native-pdo[getAttribute]', $name);
63 | }
64 | return $this->createPDO()->getAttribute($name);
65 | }
66 |
67 | // http://php.net/manual/en/pdo.getavailabledrivers.php
68 | public function getAvailableDrivers()
69 | {
70 | if ($this->isLogEnabled()) {
71 | $this->logQuery('native-pdo[getAvailableDrivers]', '');
72 | }
73 | return $this->createPOD()->getAvailableDrivers();
74 | }
75 |
76 | // http://php.net/manual/en/pdo.intransaction.php
77 | public function inTransaction()
78 | {
79 | if ($this->isLogEnabled()) {
80 | $this->logQuery('native-pdo[inTransaction]', '');
81 | }
82 | return $this->createPDO()->inTransaction();
83 | }
84 |
85 | // http://php.net/manual/en/pdo.lastinsertid.php
86 | public function lastInsertId($name = null)
87 | {
88 | if ($this->isLogEnabled()) {
89 | $this->logQuery('native-pdo[lastInsertId]', $name);
90 | }
91 | return $this->createPDO()->lastInsertId($name);
92 | }
93 |
94 | // http://php.net/manual/en/pdo.prepare.php
95 | public function prepare($statement, $driver_options = [])
96 | {
97 | if ($this->isLogEnabled()) {
98 | $this->logQuery('native-pdo[prepare]', [$statement, $driver_options]);
99 | }
100 | return $this->createPDO()->prepare($statement, $driver_options);
101 | }
102 |
103 | // http://php.net/manual/en/pdo.query.php
104 | public function query($statement, $mode = null, $info1 = null, $info2 = null)
105 | {
106 | $pdo = $this->createPDO();
107 | $options = [$statement];
108 |
109 | if ($mode !== null) {
110 | $options[] = $mode;
111 | }
112 |
113 | if ($info1 !== null) {
114 | $options[] = $info1;
115 | }
116 |
117 | if ($info2 !== null) {
118 | $options[] = $info2;
119 | }
120 |
121 | $this->logQuery('native-pdo[query]', $options);
122 |
123 | return call_user_func_array([$pdo, 'query'], $options);
124 | }
125 |
126 | // http://php.net/manual/en/pdo.quote.php
127 | public function quote($string, $parameter_type = null)
128 | {
129 | $pdo = $this->createPDO();
130 | $options = [$string];
131 |
132 | if ($parameter_type !== null) {
133 | $options[] = $parameter_type;
134 | }
135 |
136 | $this->logQuery('native-pdo[quote]', $options);
137 |
138 | return call_user_func_array([$pdo, 'quote'], $options);
139 | }
140 |
141 | // http://php.net/manual/en/pdo.rollback.php
142 | public function rollBack()
143 | {
144 | $this->logQuery('native-pdo[rollBack]', '');
145 | return $this->createPDO()->rollBack();
146 | }
147 |
148 | // http://php.net/manual/en/pdo.setattribute.php
149 | public function setAttribute($attribute, $value)
150 | {
151 | $this->logQuery('native-pdo[setAttribute]', [$attribute, $value]);
152 | return $this->createPDO()->setAttribute($attribute, $value);
153 | }
154 |
155 | }
--------------------------------------------------------------------------------
/src/Report.php:
--------------------------------------------------------------------------------
1 | attach($this);
14 | return $report->result();
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/src/Report/Database/Structure.php:
--------------------------------------------------------------------------------
1 | server = $server;
16 | $this->configuration = $server->getConfiguration();
17 | return $this;
18 | }
19 |
20 | private $result = null;
21 |
22 | public function result($fresh = false)
23 | {
24 | if ($this->result !== null) {
25 | if (!$fresh) {
26 | return $this->result;
27 | }
28 | }
29 |
30 | $info = [];
31 | $info['size'] = [
32 | 'bytes' => 0,
33 | 'mb' => 0
34 | ];
35 | $info['rows'] = 0;
36 | $info['name'] = $this->configuration->getDatabase();
37 |
38 | $tables = [];
39 |
40 | foreach ($this->server->build('select')
41 | ->column('ist.DATA_LENGTH')
42 | ->column('ist.INDEX_LENGTH')
43 | ->column('ist.TABLE_ROWS')
44 | ->column('ist.TABLE_NAME')
45 | ->column('ist.CREATE_TIME')
46 | ->from('information_schema.TABLES', 'ist')
47 | ->where('TABLE_SCHEMA', '=', $this->configuration->getDatabase())
48 | ->execute()
49 | ->fetchAll() as $ist) {
50 | $table = [];
51 | $table['size'] = [];
52 | $table['size']['bytes'] = $ist->DATA_LENGTH + $ist->INDEX_LENGTH;
53 | $table['size']['mb'] = @round(($table['size']['bytes'] / 1024 / 1024), 2);
54 | $table['rows'] = $ist->TABLE_ROWS;
55 | $table['name'] = $ist->TABLE_NAME;
56 | $table['created'] = strtotime($ist->CREATE_TIME);
57 |
58 | $info['size']['bytes'] += $table['size']['bytes'];
59 | $info['rows'] += $table['rows'];
60 |
61 | $tables[] = $table;
62 | }
63 |
64 | $info['size']['mb'] = @round(($info['size']['bytes'] / 1024 / 1024), 2);
65 |
66 | $this->result = [
67 | 'database' => $info,
68 | 'tables' => $tables
69 | ];
70 |
71 | return $this->result;
72 | }
73 |
74 | }
--------------------------------------------------------------------------------
/src/Server.php:
--------------------------------------------------------------------------------
1 | state = self::DISCONNECTED;
37 | $this->configuration = $configuration;
38 | }
39 |
40 | public function getConfiguration()
41 | {
42 | return $this->configuration;
43 | }
44 |
45 | protected function createPDO()
46 | {
47 | // do not connect if already connected
48 | if ($this->state == self::CONNECTED) {
49 | // do not connect if the grace timeout not reached
50 | if ((time() - $this->pdo_connection_time) <= $this->configuration->getTimeout()) {
51 | return $this->pdo;
52 | }
53 |
54 | // require a fresh connection
55 | $this->pdo = null;
56 | $this->state = self::DISCONNECTED;
57 | }
58 |
59 | $dsn = 'mysql:host=' . $this->configuration->getHostname() . ';';
60 | $dsn .= 'port=' . $this->configuration->getPort() . ';';
61 | $dsn .= 'dbname=' . $this->configuration->getDatabase();
62 |
63 | $options = [];
64 | $options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
65 | $options[PDO::ATTR_DEFAULT_FETCH_MODE] = PDO::FETCH_OBJ;
66 | $options[PDO::ATTR_PERSISTENT] = $this->configuration->getPersistent() ? true : false;
67 |
68 | $command = '';
69 | if ($encoding = $this->configuration->getEncoding()) {
70 | $command .= 'SET NAMES \'' . $encoding . '\'';
71 | }
72 |
73 | if (!empty($command)) {
74 | $options[PDO::MYSQL_ATTR_INIT_COMMAND] = $command;
75 | }
76 |
77 | $this->pdo = new PDO($dsn, $this->configuration->getUsername(), $this->configuration->getPassword(), $options);
78 | $this->pdo_connection_time = time();
79 | $this->state = self::CONNECTED;
80 | return $this->pdo;
81 | }
82 |
83 | public function getNativePdo()
84 | {
85 | return $this->createPDO();
86 | }
87 |
88 | public function build($format, array $options = [])
89 | {
90 | if ($format == 'insert') {
91 | return new Insert($this, $options);
92 | } elseif ($format == 'replace') {
93 | return new Replace($this);
94 | } elseif ($format == 'ignore') {
95 | return new Ignore($this);
96 | } elseif ($format == 'select') {
97 | return new Select($this);
98 | } elseif ($format == 'delete') {
99 | return new Delete($this);
100 | } elseif ($format == 'update') {
101 | return new Update($this);
102 | } else {
103 | throw new Exception('Requested build format "' . $format . '" does not exist."');
104 | }
105 | }
106 |
107 | public function isLogEnabled()
108 | {
109 | return (bool)$this->configuration->getLog();
110 | }
111 |
112 | public function logQuery($format, $query)
113 | {
114 | $backtrace = debug_backtrace();
115 | array_shift($backtrace); // remove builder call
116 |
117 | self::$queryLog[] = [
118 | 'format' => $format,
119 | 'query' => $query,
120 | 'caller' => [
121 | 'filename' => $backtrace[0]['file'],
122 | 'line_number' => $backtrace[0]['line']
123 | ]
124 | ];
125 | }
126 |
127 | public function getQueryLog()
128 | {
129 | return self::$queryLog;
130 | }
131 |
132 | }
--------------------------------------------------------------------------------
/tests/LibraryTest.php:
--------------------------------------------------------------------------------
1 | KML instanceof \Kodols\MySQL\Library) {
15 | $this->KML = new \Kodols\MySQL\Library;
16 | }
17 | }
18 |
19 | private function installBasicConfig($id)
20 | {
21 | $this->generateLibrary();
22 | $this->KML->attachConfiguration($this->KML->newConfiguration(), $id);
23 | }
24 |
25 | public function testConfigurationObject()
26 | {
27 | $this->generateLibrary();
28 |
29 | $config = $this->KML->newConfiguration();
30 |
31 | $this->assertInstanceOf(\Kodols\MySQL\Configuration::class, $config);
32 |
33 | $config->setDatabase('unittest');
34 | $this->assertEquals('unittest', $config->getDatabase());
35 |
36 | $this->assertInstanceOf(\Kodols\MySQL\Library::class, $this->KML->attachConfiguration($config, 'testConfigurationObject'));
37 | }
38 |
39 | public function testAbilityToExecuteNativeMethodsFromMainObject()
40 | {
41 | $this->installBasicConfig('testAbilityToExecuteNativeMethodsFromMainObject');
42 | $server = $this->KML->connect('testAbilityToExecuteNativeMethodsFromMainObject');
43 |
44 | $this->assertTrue(method_exists($server, 'beginTransaction'));
45 | $this->assertTrue(method_exists($server, 'commit'));
46 | $this->assertTrue(method_exists($server, 'errorCode'));
47 | $this->assertTrue(method_exists($server, 'errorInfo'));
48 | $this->assertTrue(method_exists($server, 'exec'));
49 | $this->assertTrue(method_exists($server, 'getAttribute'));
50 | $this->assertTrue(method_exists($server, 'getAvailableDrivers'));
51 | $this->assertTrue(method_exists($server, 'inTransaction'));
52 | $this->assertTrue(method_exists($server, 'lastInsertId'));
53 | $this->assertTrue(method_exists($server, 'prepare'));
54 | $this->assertTrue(method_exists($server, 'query'));
55 | $this->assertTrue(method_exists($server, 'quote'));
56 | $this->assertTrue(method_exists($server, 'rollBack'));
57 | $this->assertTrue(method_exists($server, 'setAttribute'));
58 | }
59 |
60 | public function testAbilityToExecuteHelperMethodsFromMainObject()
61 | {
62 | $this->installBasicConfig('testAbilityToExecuteHelperMethodsFromMainObject');
63 | $server = $this->KML->connect('testAbilityToExecuteHelperMethodsFromMainObject');
64 |
65 | $this->assertTrue(method_exists($server, 'insert'));
66 | $this->assertTrue(method_exists($server, 'ignore'));
67 | $this->assertTrue(method_exists($server, 'replace'));
68 | $this->assertTrue(method_exists($server, 'update'));
69 | $this->assertTrue(method_exists($server, 'delete'));
70 | }
71 |
72 | public function testBuilderInitialisation()
73 | {
74 | $this->installBasicConfig('testBuilderInitialisation');
75 | $server = $this->KML->connect('testBuilderInitialisation');
76 |
77 | $this->assertInstanceOf(\Kodols\MySQL\Builder\Delete::class, $server->build('delete'));
78 | $this->assertInstanceOf(\Kodols\MySQL\Builder\Update::class, $server->build('update'));
79 | $this->assertInstanceOf(\Kodols\MySQL\Builder\Select::class, $server->build('select'));
80 | $this->assertInstanceOf(\Kodols\MySQL\Builder\Insert::class, $server->build('insert'));
81 | $this->assertInstanceOf(\Kodols\MySQL\Builder\Ignore::class, $server->build('ignore'));
82 | $this->assertInstanceOf(\Kodols\MySQL\Builder\Replace::class, $server->build('replace'));
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |