├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATES
│ ├── bug_report.md
│ ├── custom.md
│ └── feature_request.md
├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── docs
├── LibSQL.md
├── Providers
│ └── HttpClient.md
├── Quickstart.md
├── README.md
├── Traits
│ ├── Logging.md
│ └── MapResults.md
├── Types
│ ├── Authoriy.md
│ ├── Config.md
│ ├── ExpandedConfig.md
│ ├── ExpandedScheme.md
│ ├── HeirPart.md
│ ├── HttpResponse.md
│ ├── HttpResultSets.md
│ ├── HttpStatement.md
│ ├── KeyValue.md
│ ├── LibSQLResult.md
│ ├── Query.md
│ ├── TransactionMode.md
│ ├── Uri.md
│ └── UserInfo.md
└── Utils
│ ├── Exceptions
│ └── LibsqlError.md
│ ├── constants.md
│ └── helpers.md
├── examples
├── .gitkeep
├── local-file
│ ├── check-version.php
│ ├── execute.php
│ └── placeholders.php
├── remote-http
│ ├── batch-query.php
│ ├── sequence-query.php
│ ├── simple-query.php
│ └── transaction-query.php
└── remote-replica
│ └── connection.php
└── src
├── LibSQL.php
├── Providers
├── HttpClient.php
├── LocalClient.php
└── RemoteReplicaClient.php
├── Traits
├── Logging.php
└── MapResults.php
├── Types
├── Authority.php
├── Config.php
├── ExpandedConfig.php
├── ExpandedScheme.php
├── HierPart.php
├── HttpResponse.php
├── HttpResultSets.php
├── HttpStatement.php
├── HttpTransaction.php
├── KeyValue.php
├── LibSQLResult.php
├── Query.php
├── TransactionMode.php
├── Uri.php
└── UserInfo.php
└── Utils
├── Exceptions
└── LibsqlError.php
├── Mods.php
└── helpers.php
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: darkterminal # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: https://paypal.me/lazarusalhambra # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATES/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATES/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATES/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | playground/
2 | vendor/
3 | .vscode/
4 | taggen
5 | .env
6 | libsql-php
7 | examples/*.db
8 | *.log
9 | *.db
10 | _intelephense_helper.php
11 | orchestrators/
12 | *.db*
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Imam Ali Mustofa
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 |
🚨 THIS REPOSITORY IS READ-ONLY 🚨
2 | This repository is no longer under maintenance and has been moved to
the official Turso Database repository under the name Turso Client PHP
3 |
4 |
5 |
6 |
7 | Turso + PHP
8 |
9 |
10 |
11 |
12 | SQLite for Production. Powered by libSQL.
13 |
14 |
15 |
16 | Turso ·
17 | Quickstart ·
18 | Examples ·
19 | Docs ·
20 | Discord ·
21 | Blog & Tutorials
22 |
23 |
24 | ---
25 |
26 | ## Documentation
27 |
28 | 1. [Turso Quickstart](https://docs.turso.tech/quickstart) — Learn how create and connect your first database.
29 | 2. [SDK Quickstart](/docs/Quickstart.md) — Learn how to install and execute queries using the libSQL client.
30 | 3. [SDK Reference](/docs/LibSQL.md) — Dive deeper with the libSQL SDK reference and examples.
31 |
32 | ### What is Turso?
33 |
34 | [Turso](https://turso.tech) is a SQLite-compatible database built on [libSQL](https://docs.turso.tech/libsql), the Open Contribution fork of SQLite. It enables scaling to hundreds of thousands of databases per organization and supports replication to any location, including your own servers, for microsecond-latency access.
35 |
36 | Learn more about what you can do with Turso:
37 |
38 | - [Embedded Replicas](https://docs.turso.tech/features/embedded-replicas)
39 | - [Platform API](https://docs.turso.tech/features/platform-api)
40 | - [Data Edge](https://docs.turso.tech/features/data-edge)
41 | - [Branching](https://docs.turso.tech/features/branching)
42 | - [Point-in-Time Recovery](https://docs.turso.tech/features/point-in-time-recovery)
43 | - [Scale to Zero](https://docs.turso.tech/features/scale-to-zero)
44 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "darkterminal/libsql-client-php",
3 | "description": "PHP client API for libSQL",
4 | "license": "MIT",
5 | "autoload": {
6 | "psr-4": {
7 | "Darkterminal\\LibSQL\\": "src/"
8 | },
9 | "files": [
10 | "src/Utils/helpers.php"
11 | ]
12 | },
13 | "authors": [
14 | {
15 | "name": "Imam Ali Mustofa",
16 | "email": "darkterminal@duck.com"
17 | }
18 | ],
19 | "scripts": {
20 | "post-install-cmd": ["./vendor/bin/build"],
21 | "post-update-cmd": ["./vendor/bin/build"]
22 | },
23 | "require": {
24 | "guzzlehttp/guzzle": "^7.0",
25 | "darkterminal/libsql-php-ext": "^1.0"
26 | },
27 | "funding": [
28 | {
29 | "type": "github",
30 | "url": "https://github.com/sponsors/darkterminal"
31 | },
32 | {
33 | "type": "other",
34 | "url": "https://paypal.me/lazarusalhambra"
35 | }
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "a5cab5b0a3322cb4d3ef17c4d608e4ae",
8 | "packages": [
9 | {
10 | "name": "darkterminal/libsql-php-ext",
11 | "version": "v1.0.1",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/darkterminal/libsql-php-ext.git",
15 | "reference": "00bea7e8bfdcd55ba353bb3dfc41bdbe5b39baef"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/darkterminal/libsql-php-ext/zipball/00bea7e8bfdcd55ba353bb3dfc41bdbe5b39baef",
20 | "reference": "00bea7e8bfdcd55ba353bb3dfc41bdbe5b39baef",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": ">=8.3"
25 | },
26 | "bin": [
27 | "build"
28 | ],
29 | "type": "library",
30 | "autoload": {
31 | "files": [
32 | "php-src/constants.php",
33 | "php-src/helpers.php"
34 | ],
35 | "psr-4": {
36 | "Darkterminal\\LibSQLPHPExtension\\": "php-src/"
37 | }
38 | },
39 | "notification-url": "https://packagist.org/downloads/",
40 | "license": [
41 | "MIT"
42 | ],
43 | "authors": [
44 | {
45 | "name": "Imam Ali Mustofa",
46 | "email": "darkterminal@duck.com"
47 | }
48 | ],
49 | "description": "LibSQL Native Extension for PHP",
50 | "support": {
51 | "issues": "https://github.com/darkterminal/libsql-php-ext/issues",
52 | "source": "https://github.com/darkterminal/libsql-php-ext/tree/v1.0.1"
53 | },
54 | "funding": [
55 | {
56 | "url": "https://paypal.me/lazarusalhambra",
57 | "type": "custom"
58 | },
59 | {
60 | "url": "https://github.com/darkterminal",
61 | "type": "github"
62 | }
63 | ],
64 | "time": "2024-05-19T05:14:23+00:00"
65 | },
66 | {
67 | "name": "guzzlehttp/guzzle",
68 | "version": "7.8.1",
69 | "source": {
70 | "type": "git",
71 | "url": "https://github.com/guzzle/guzzle.git",
72 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104"
73 | },
74 | "dist": {
75 | "type": "zip",
76 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104",
77 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104",
78 | "shasum": ""
79 | },
80 | "require": {
81 | "ext-json": "*",
82 | "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
83 | "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
84 | "php": "^7.2.5 || ^8.0",
85 | "psr/http-client": "^1.0",
86 | "symfony/deprecation-contracts": "^2.2 || ^3.0"
87 | },
88 | "provide": {
89 | "psr/http-client-implementation": "1.0"
90 | },
91 | "require-dev": {
92 | "bamarni/composer-bin-plugin": "^1.8.2",
93 | "ext-curl": "*",
94 | "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
95 | "php-http/message-factory": "^1.1",
96 | "phpunit/phpunit": "^8.5.36 || ^9.6.15",
97 | "psr/log": "^1.1 || ^2.0 || ^3.0"
98 | },
99 | "suggest": {
100 | "ext-curl": "Required for CURL handler support",
101 | "ext-intl": "Required for Internationalized Domain Name (IDN) support",
102 | "psr/log": "Required for using the Log middleware"
103 | },
104 | "type": "library",
105 | "extra": {
106 | "bamarni-bin": {
107 | "bin-links": true,
108 | "forward-command": false
109 | }
110 | },
111 | "autoload": {
112 | "files": [
113 | "src/functions_include.php"
114 | ],
115 | "psr-4": {
116 | "GuzzleHttp\\": "src/"
117 | }
118 | },
119 | "notification-url": "https://packagist.org/downloads/",
120 | "license": [
121 | "MIT"
122 | ],
123 | "authors": [
124 | {
125 | "name": "Graham Campbell",
126 | "email": "hello@gjcampbell.co.uk",
127 | "homepage": "https://github.com/GrahamCampbell"
128 | },
129 | {
130 | "name": "Michael Dowling",
131 | "email": "mtdowling@gmail.com",
132 | "homepage": "https://github.com/mtdowling"
133 | },
134 | {
135 | "name": "Jeremy Lindblom",
136 | "email": "jeremeamia@gmail.com",
137 | "homepage": "https://github.com/jeremeamia"
138 | },
139 | {
140 | "name": "George Mponos",
141 | "email": "gmponos@gmail.com",
142 | "homepage": "https://github.com/gmponos"
143 | },
144 | {
145 | "name": "Tobias Nyholm",
146 | "email": "tobias.nyholm@gmail.com",
147 | "homepage": "https://github.com/Nyholm"
148 | },
149 | {
150 | "name": "Márk Sági-Kazár",
151 | "email": "mark.sagikazar@gmail.com",
152 | "homepage": "https://github.com/sagikazarmark"
153 | },
154 | {
155 | "name": "Tobias Schultze",
156 | "email": "webmaster@tubo-world.de",
157 | "homepage": "https://github.com/Tobion"
158 | }
159 | ],
160 | "description": "Guzzle is a PHP HTTP client library",
161 | "keywords": [
162 | "client",
163 | "curl",
164 | "framework",
165 | "http",
166 | "http client",
167 | "psr-18",
168 | "psr-7",
169 | "rest",
170 | "web service"
171 | ],
172 | "support": {
173 | "issues": "https://github.com/guzzle/guzzle/issues",
174 | "source": "https://github.com/guzzle/guzzle/tree/7.8.1"
175 | },
176 | "funding": [
177 | {
178 | "url": "https://github.com/GrahamCampbell",
179 | "type": "github"
180 | },
181 | {
182 | "url": "https://github.com/Nyholm",
183 | "type": "github"
184 | },
185 | {
186 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
187 | "type": "tidelift"
188 | }
189 | ],
190 | "time": "2023-12-03T20:35:24+00:00"
191 | },
192 | {
193 | "name": "guzzlehttp/promises",
194 | "version": "2.0.2",
195 | "source": {
196 | "type": "git",
197 | "url": "https://github.com/guzzle/promises.git",
198 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223"
199 | },
200 | "dist": {
201 | "type": "zip",
202 | "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223",
203 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223",
204 | "shasum": ""
205 | },
206 | "require": {
207 | "php": "^7.2.5 || ^8.0"
208 | },
209 | "require-dev": {
210 | "bamarni/composer-bin-plugin": "^1.8.2",
211 | "phpunit/phpunit": "^8.5.36 || ^9.6.15"
212 | },
213 | "type": "library",
214 | "extra": {
215 | "bamarni-bin": {
216 | "bin-links": true,
217 | "forward-command": false
218 | }
219 | },
220 | "autoload": {
221 | "psr-4": {
222 | "GuzzleHttp\\Promise\\": "src/"
223 | }
224 | },
225 | "notification-url": "https://packagist.org/downloads/",
226 | "license": [
227 | "MIT"
228 | ],
229 | "authors": [
230 | {
231 | "name": "Graham Campbell",
232 | "email": "hello@gjcampbell.co.uk",
233 | "homepage": "https://github.com/GrahamCampbell"
234 | },
235 | {
236 | "name": "Michael Dowling",
237 | "email": "mtdowling@gmail.com",
238 | "homepage": "https://github.com/mtdowling"
239 | },
240 | {
241 | "name": "Tobias Nyholm",
242 | "email": "tobias.nyholm@gmail.com",
243 | "homepage": "https://github.com/Nyholm"
244 | },
245 | {
246 | "name": "Tobias Schultze",
247 | "email": "webmaster@tubo-world.de",
248 | "homepage": "https://github.com/Tobion"
249 | }
250 | ],
251 | "description": "Guzzle promises library",
252 | "keywords": [
253 | "promise"
254 | ],
255 | "support": {
256 | "issues": "https://github.com/guzzle/promises/issues",
257 | "source": "https://github.com/guzzle/promises/tree/2.0.2"
258 | },
259 | "funding": [
260 | {
261 | "url": "https://github.com/GrahamCampbell",
262 | "type": "github"
263 | },
264 | {
265 | "url": "https://github.com/Nyholm",
266 | "type": "github"
267 | },
268 | {
269 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
270 | "type": "tidelift"
271 | }
272 | ],
273 | "time": "2023-12-03T20:19:20+00:00"
274 | },
275 | {
276 | "name": "guzzlehttp/psr7",
277 | "version": "2.6.2",
278 | "source": {
279 | "type": "git",
280 | "url": "https://github.com/guzzle/psr7.git",
281 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221"
282 | },
283 | "dist": {
284 | "type": "zip",
285 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221",
286 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221",
287 | "shasum": ""
288 | },
289 | "require": {
290 | "php": "^7.2.5 || ^8.0",
291 | "psr/http-factory": "^1.0",
292 | "psr/http-message": "^1.1 || ^2.0",
293 | "ralouphie/getallheaders": "^3.0"
294 | },
295 | "provide": {
296 | "psr/http-factory-implementation": "1.0",
297 | "psr/http-message-implementation": "1.0"
298 | },
299 | "require-dev": {
300 | "bamarni/composer-bin-plugin": "^1.8.2",
301 | "http-interop/http-factory-tests": "^0.9",
302 | "phpunit/phpunit": "^8.5.36 || ^9.6.15"
303 | },
304 | "suggest": {
305 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
306 | },
307 | "type": "library",
308 | "extra": {
309 | "bamarni-bin": {
310 | "bin-links": true,
311 | "forward-command": false
312 | }
313 | },
314 | "autoload": {
315 | "psr-4": {
316 | "GuzzleHttp\\Psr7\\": "src/"
317 | }
318 | },
319 | "notification-url": "https://packagist.org/downloads/",
320 | "license": [
321 | "MIT"
322 | ],
323 | "authors": [
324 | {
325 | "name": "Graham Campbell",
326 | "email": "hello@gjcampbell.co.uk",
327 | "homepage": "https://github.com/GrahamCampbell"
328 | },
329 | {
330 | "name": "Michael Dowling",
331 | "email": "mtdowling@gmail.com",
332 | "homepage": "https://github.com/mtdowling"
333 | },
334 | {
335 | "name": "George Mponos",
336 | "email": "gmponos@gmail.com",
337 | "homepage": "https://github.com/gmponos"
338 | },
339 | {
340 | "name": "Tobias Nyholm",
341 | "email": "tobias.nyholm@gmail.com",
342 | "homepage": "https://github.com/Nyholm"
343 | },
344 | {
345 | "name": "Márk Sági-Kazár",
346 | "email": "mark.sagikazar@gmail.com",
347 | "homepage": "https://github.com/sagikazarmark"
348 | },
349 | {
350 | "name": "Tobias Schultze",
351 | "email": "webmaster@tubo-world.de",
352 | "homepage": "https://github.com/Tobion"
353 | },
354 | {
355 | "name": "Márk Sági-Kazár",
356 | "email": "mark.sagikazar@gmail.com",
357 | "homepage": "https://sagikazarmark.hu"
358 | }
359 | ],
360 | "description": "PSR-7 message implementation that also provides common utility methods",
361 | "keywords": [
362 | "http",
363 | "message",
364 | "psr-7",
365 | "request",
366 | "response",
367 | "stream",
368 | "uri",
369 | "url"
370 | ],
371 | "support": {
372 | "issues": "https://github.com/guzzle/psr7/issues",
373 | "source": "https://github.com/guzzle/psr7/tree/2.6.2"
374 | },
375 | "funding": [
376 | {
377 | "url": "https://github.com/GrahamCampbell",
378 | "type": "github"
379 | },
380 | {
381 | "url": "https://github.com/Nyholm",
382 | "type": "github"
383 | },
384 | {
385 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
386 | "type": "tidelift"
387 | }
388 | ],
389 | "time": "2023-12-03T20:05:35+00:00"
390 | },
391 | {
392 | "name": "psr/http-client",
393 | "version": "1.0.3",
394 | "source": {
395 | "type": "git",
396 | "url": "https://github.com/php-fig/http-client.git",
397 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
398 | },
399 | "dist": {
400 | "type": "zip",
401 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
402 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
403 | "shasum": ""
404 | },
405 | "require": {
406 | "php": "^7.0 || ^8.0",
407 | "psr/http-message": "^1.0 || ^2.0"
408 | },
409 | "type": "library",
410 | "extra": {
411 | "branch-alias": {
412 | "dev-master": "1.0.x-dev"
413 | }
414 | },
415 | "autoload": {
416 | "psr-4": {
417 | "Psr\\Http\\Client\\": "src/"
418 | }
419 | },
420 | "notification-url": "https://packagist.org/downloads/",
421 | "license": [
422 | "MIT"
423 | ],
424 | "authors": [
425 | {
426 | "name": "PHP-FIG",
427 | "homepage": "https://www.php-fig.org/"
428 | }
429 | ],
430 | "description": "Common interface for HTTP clients",
431 | "homepage": "https://github.com/php-fig/http-client",
432 | "keywords": [
433 | "http",
434 | "http-client",
435 | "psr",
436 | "psr-18"
437 | ],
438 | "support": {
439 | "source": "https://github.com/php-fig/http-client"
440 | },
441 | "time": "2023-09-23T14:17:50+00:00"
442 | },
443 | {
444 | "name": "psr/http-factory",
445 | "version": "1.1.0",
446 | "source": {
447 | "type": "git",
448 | "url": "https://github.com/php-fig/http-factory.git",
449 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
450 | },
451 | "dist": {
452 | "type": "zip",
453 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
454 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
455 | "shasum": ""
456 | },
457 | "require": {
458 | "php": ">=7.1",
459 | "psr/http-message": "^1.0 || ^2.0"
460 | },
461 | "type": "library",
462 | "extra": {
463 | "branch-alias": {
464 | "dev-master": "1.0.x-dev"
465 | }
466 | },
467 | "autoload": {
468 | "psr-4": {
469 | "Psr\\Http\\Message\\": "src/"
470 | }
471 | },
472 | "notification-url": "https://packagist.org/downloads/",
473 | "license": [
474 | "MIT"
475 | ],
476 | "authors": [
477 | {
478 | "name": "PHP-FIG",
479 | "homepage": "https://www.php-fig.org/"
480 | }
481 | ],
482 | "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
483 | "keywords": [
484 | "factory",
485 | "http",
486 | "message",
487 | "psr",
488 | "psr-17",
489 | "psr-7",
490 | "request",
491 | "response"
492 | ],
493 | "support": {
494 | "source": "https://github.com/php-fig/http-factory"
495 | },
496 | "time": "2024-04-15T12:06:14+00:00"
497 | },
498 | {
499 | "name": "psr/http-message",
500 | "version": "2.0",
501 | "source": {
502 | "type": "git",
503 | "url": "https://github.com/php-fig/http-message.git",
504 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
505 | },
506 | "dist": {
507 | "type": "zip",
508 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
509 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
510 | "shasum": ""
511 | },
512 | "require": {
513 | "php": "^7.2 || ^8.0"
514 | },
515 | "type": "library",
516 | "extra": {
517 | "branch-alias": {
518 | "dev-master": "2.0.x-dev"
519 | }
520 | },
521 | "autoload": {
522 | "psr-4": {
523 | "Psr\\Http\\Message\\": "src/"
524 | }
525 | },
526 | "notification-url": "https://packagist.org/downloads/",
527 | "license": [
528 | "MIT"
529 | ],
530 | "authors": [
531 | {
532 | "name": "PHP-FIG",
533 | "homepage": "https://www.php-fig.org/"
534 | }
535 | ],
536 | "description": "Common interface for HTTP messages",
537 | "homepage": "https://github.com/php-fig/http-message",
538 | "keywords": [
539 | "http",
540 | "http-message",
541 | "psr",
542 | "psr-7",
543 | "request",
544 | "response"
545 | ],
546 | "support": {
547 | "source": "https://github.com/php-fig/http-message/tree/2.0"
548 | },
549 | "time": "2023-04-04T09:54:51+00:00"
550 | },
551 | {
552 | "name": "ralouphie/getallheaders",
553 | "version": "3.0.3",
554 | "source": {
555 | "type": "git",
556 | "url": "https://github.com/ralouphie/getallheaders.git",
557 | "reference": "120b605dfeb996808c31b6477290a714d356e822"
558 | },
559 | "dist": {
560 | "type": "zip",
561 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
562 | "reference": "120b605dfeb996808c31b6477290a714d356e822",
563 | "shasum": ""
564 | },
565 | "require": {
566 | "php": ">=5.6"
567 | },
568 | "require-dev": {
569 | "php-coveralls/php-coveralls": "^2.1",
570 | "phpunit/phpunit": "^5 || ^6.5"
571 | },
572 | "type": "library",
573 | "autoload": {
574 | "files": [
575 | "src/getallheaders.php"
576 | ]
577 | },
578 | "notification-url": "https://packagist.org/downloads/",
579 | "license": [
580 | "MIT"
581 | ],
582 | "authors": [
583 | {
584 | "name": "Ralph Khattar",
585 | "email": "ralph.khattar@gmail.com"
586 | }
587 | ],
588 | "description": "A polyfill for getallheaders.",
589 | "support": {
590 | "issues": "https://github.com/ralouphie/getallheaders/issues",
591 | "source": "https://github.com/ralouphie/getallheaders/tree/develop"
592 | },
593 | "time": "2019-03-08T08:55:37+00:00"
594 | },
595 | {
596 | "name": "symfony/deprecation-contracts",
597 | "version": "v3.5.0",
598 | "source": {
599 | "type": "git",
600 | "url": "https://github.com/symfony/deprecation-contracts.git",
601 | "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
602 | },
603 | "dist": {
604 | "type": "zip",
605 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
606 | "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
607 | "shasum": ""
608 | },
609 | "require": {
610 | "php": ">=8.1"
611 | },
612 | "type": "library",
613 | "extra": {
614 | "branch-alias": {
615 | "dev-main": "3.5-dev"
616 | },
617 | "thanks": {
618 | "name": "symfony/contracts",
619 | "url": "https://github.com/symfony/contracts"
620 | }
621 | },
622 | "autoload": {
623 | "files": [
624 | "function.php"
625 | ]
626 | },
627 | "notification-url": "https://packagist.org/downloads/",
628 | "license": [
629 | "MIT"
630 | ],
631 | "authors": [
632 | {
633 | "name": "Nicolas Grekas",
634 | "email": "p@tchwork.com"
635 | },
636 | {
637 | "name": "Symfony Community",
638 | "homepage": "https://symfony.com/contributors"
639 | }
640 | ],
641 | "description": "A generic function and convention to trigger deprecation notices",
642 | "homepage": "https://symfony.com",
643 | "support": {
644 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
645 | },
646 | "funding": [
647 | {
648 | "url": "https://symfony.com/sponsor",
649 | "type": "custom"
650 | },
651 | {
652 | "url": "https://github.com/fabpot",
653 | "type": "github"
654 | },
655 | {
656 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
657 | "type": "tidelift"
658 | }
659 | ],
660 | "time": "2024-04-18T09:32:20+00:00"
661 | }
662 | ],
663 | "packages-dev": [],
664 | "aliases": [],
665 | "minimum-stability": "stable",
666 | "stability-flags": [],
667 | "prefer-stable": false,
668 | "prefer-lowest": false,
669 | "platform": [],
670 | "platform-dev": [],
671 | "plugin-api-version": "2.6.0"
672 | }
673 |
--------------------------------------------------------------------------------
/docs/LibSQL.md:
--------------------------------------------------------------------------------
1 | # LibSQL
2 |
3 | The main class for interacting with the LibSQL service. This class provides functionality for creating an HTTP client and Local client based on the provided configuration. It supports different URL schemes such as "file:", "libsql:", "https:", and "http:". It also handles errors related to unsupported URL schemes and TLS configurations.
4 |
5 | ## Instanciated
6 |
7 | This constructor initializes a new instance of LibSQL based on the provided configuration. It supports both local and remote connections.
8 |
9 | For a **local connection**, an example configuration includes specifying a file URL along with flags for opening the database file. Encryption key can also be provided if needed.
10 |
11 | For a **remote connection**, the configuration includes the URL of the remote server, an authentication token, and an optional TLS flag.
12 |
13 | For a **remote replica connection**, need to configure with associative array that includes the `url` which is the path to the database file, `authToken`, `syncUrl` is remote server url / turso url, and two optional value is `syncInterval` default is 5 second and `read_your_writes` default is true.
14 |
15 | The constructor throws a `LibsqlError` if there's an issue creating the HTTP client or if the provided URL scheme is not supported. It distinguishes between remote and local connections and sets up the appropriate provider accordingly.
16 |
17 | ```php
18 | public function __construct(array $config)
19 | ```
20 |
21 | **Parameters:**
22 |
23 | - `$config`: The configuration array for the LibSQL service.
24 |
25 | **Example Local Connection**
26 |
27 | ```php
28 | "file:database.db",
31 | "flags" => LIBSQLPHP_OPEN_READWRITE | LIBSQLPHP_OPEN_CREATE,
32 | "encryptionKey" => ""
33 | ];
34 |
35 | $db = new LibSQL($config);
36 | ```
37 |
38 | **Example Remote Connection**
39 |
40 | ```php
41 | 'libsql://127.0.0.1:8001', // libsql://database-origanization.turso.io
44 | 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'),
45 | 'tls' => false
46 | ];
47 |
48 | $db = new LibSQL($config);
49 | ```
50 |
51 | **Example Remote Replica Connection**
52 |
53 | ```php
54 | $config = [
55 | "url" => "file:database.db",
56 | "authToken" => getenv('TURSO_DATABASE_TOKEN'),
57 | "syncUrl" => getenv('TURSO_DATABASE_URL'),
58 | "syncInterval" => 5,
59 | "read_your_writes" => true
60 | ];
61 |
62 | $db = new LibSQL($config);
63 | ```
64 |
65 | ## Connection
66 |
67 | This method `connect()` establishes a connection to the database based on the mode set during the initialization of the LibSQL instance. It throws a `LibsqlError` if the connection mode is not recognized.
68 |
69 | For a remote connection, it delegates the connection task to the HTTP provider's `connect()` method. For a local connection, it uses the local provider's `connect()` method.
70 |
71 | If the connection mode is neither remote nor local, it throws an error indicating that the connection mode is not found.
72 |
73 | **Return**
74 | - `bool` - If `true` connection is establish, `false` connection failed.
75 |
76 | ```php
77 | public function connect(): bool
78 | ```
79 |
80 | ## Version
81 |
82 | This method `version()` retrieves the version information of the database based on the connection mode set during the initialization of the LibSQL instance. If the connection mode is not recognized, it throws a `LibsqlError`.
83 |
84 | For a remote connection, it delegates the task to the HTTP provider's `version()` method. For a local connection, it uses the local provider's `version()` method.
85 |
86 | If the connection mode is neither remote nor local, it throws an error indicating that the connection mode is not found.
87 |
88 | ```php
89 | public function version(): string
90 | ```
91 |
92 | **Return**
93 | - `string` The version information of the database.
94 |
95 | ## Executes a Query
96 |
97 | This method `execute()` allows you to execute a query either locally or remotely based on the connection mode set during the initialization of the LibSQL instance. It supports both local and remote execution.
98 |
99 | For a remote execution, you can provide an instance of `HttpStatement` representing the query along with an optional baton value. The method returns an instance of `HttpResponse` containing the result of the execution.
100 |
101 | For a local execution, you provide the query as a string and optionally an array of parameters. It returns true if the execution is successful.
102 |
103 | If the connection mode is neither remote nor local, it throws an error indicating that the connection mode is not found.
104 |
105 | ```php
106 | public function execute(string|HttpStatement $query, string $baton = '', array $params = []): LibSQLPHPClientResult|HttpResponse
107 | ```
108 |
109 | > **NOTE: Use _Named Paramaters_ is recommended**
110 |
111 | **Remote Parameters**
112 |
113 | - `$query`
114 | - `HttpStatement` - **[Remote Only]** Parameter used for Remote connection only - [Ref:HttpStatement](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpStatement.php) / Doc: [Doc:HttpStatement](https://github.com/darkterminal/libsql-client-php/blob/main/docs/Types/HttpStatement.md)
115 | - `$baton`
116 | - `string` - **[Remote Only]** The baton value for the query.
117 |
118 | **Remote Return**
119 |
120 | - `HttpResponse` - **[Remote Only]** instance of `HttpResponse` for remote mode - [Ref:HttpResponse](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpResponse.php) / Doc: [Doc:HttpResponse](https://github.com/darkterminal/libsql-client-php/blob/main/docs/Types/HttpResponse.md)
121 |
122 | **Remote Usage Example**
123 |
124 | ```php
125 | $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
126 | $results = $db->execute(query: $query);
127 | echo $results->fetch(type: LibSQLResult::FETCH_OBJ) . PHP_EOL;
128 | ```
129 |
130 | **Local Paramaters**
131 |
132 | - `$query`
133 | - `string` - **[Local only]** Parameter used for Local connection only
134 | - `$params`
135 | - `array` - **[Local Only]** Parameters for the query.
136 |
137 | **Local Return**
138 |
139 | - `LibSQLPHPClientResult` - **[Local Only]** Parameters for the query. - [Ref:LibSQLPHPClientResult](https://github.com/darkterminal/libsql-php-ext/blob/main/src/Responses/LibSQLPHPClientResult.php)
140 |
141 | **Local Usage Example**
142 |
143 | ```php
144 | $result = $db->execute(query: "INSERT INTO users (name) VALUES (?)", params: ['Belina Bogge']);
145 | var_dump($result);
146 | ```
147 |
148 | ## (Remote) Executes a batch of queries
149 |
150 | > 💡 **NOTE: THIS INTERACTIVE TRANSACTIONS HAVE HIGHER LATENCY**
151 | > _In this operation, you will send as many HTTP Requests as the total array you defined. If the batch array has 2 rows of values as in the example, then this operation will send 2 HTTP Requests._
152 |
153 | This method `batch()` executes a batch of queries **exclusively for remote connections**. It supports different transaction behavior modes such as deferred (default), write, and read.
154 |
155 | The method expects an array of HTTP statements representing the queries to execute. Each HTTP statement should be created using the `HttpStatement::create()` method, specifying the SQL query and any parameters.
156 |
157 | An optional `$mode` parameter allows you to specify the transaction behavior mode, with the default being "deferred". You can use lowercase mode names or constants from the `TransactionMode` class.
158 |
159 | It's important to note that this method is only available for remote (HTTP) connections. If called for a local connection, it will throw a `LibsqlError`.
160 |
161 | The method returns an HTTP response containing the result of the batch execution. You can refer to the [Ref:HttpResponse](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpResponse.php) class for more information on the structure of the response.
162 |
163 | ```php
164 | public function batch(array $queries, string $mode = "deferred"): HttpResponse
165 | ```
166 |
167 | > 💡 **NOTE: Remote Only**
168 |
169 | **Parameters**
170 | - `$querys` - The array of queries to execute.
171 | - `$mode` - (Optional) The transaction behavior mode. Default is "deferred"
172 |
173 | Mode Options Available:
174 | - deferred (default)
175 | - write
176 | - read
177 |
178 | Everyting is in lower-case or you can use `TransactionMode` Class Constants
179 |
180 | **Return**
181 | - `HttpResponse` - The HTTP response containing the result of the batch execution. - [Ref:HttpResponse](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpResponse.php)
182 |
183 | **Example - [Ref:Example](https://docs.turso.tech/sdk/http/reference#interactive-query)**
184 |
185 | ```php
186 | $stmts = [
187 | HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Ramons", 32]),
188 | HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Georgia", 43])
189 | ];
190 | $results = $db->batch(queries: $stmts);
191 | print_r($results);
192 | ```
193 |
194 | ## (Local / Remote Replica) Executes a batch of queries
195 |
196 | This method `execute_batch()` executes a batch of queries exclusively for local (file) connections. It allows you to execute multiple SQL statements in a single batch.
197 |
198 | The method expects a string parameter `$query`, which represents the batch query to execute. This query can contain multiple SQL statements separated by semicolons.
199 |
200 | It's important to note that this method is only available for local (file) connections. If called for a remote connection, it will throw a `LibsqlError`.
201 |
202 | The method does not return any value (void), as it simply executes the batch query.
203 |
204 | ```php
205 | public function execute_batch(string $query): void
206 | ```
207 |
208 |
209 | **Example**
210 |
211 | ```php
212 | execute_batch("
214 | BEGIN;
215 | CREATE TABLE foo(x INTEGER);
216 | CREATE TABLE bar(y TEXT);
217 | COMMIT;
218 | ");
219 | ```
220 |
221 | ## Executes multiple SQL queries in a single HTTP request
222 |
223 | This method `executeMultiple()` allows you to execute multiple SQL queries in a single HTTP request, specifically designed for remote connections only.
224 |
225 | The method expects a string parameter `$query`, which represents the SQL queries to execute. These queries should be separated by semicolons.
226 |
227 | It's important to note that this method is only available for remote (HTTP) connections. If called for a local connection, it will throw a `LibsqlError`.
228 |
229 | The method returns a string containing the response from executing the queries.
230 |
231 | ```php
232 | public function executeMultiple(string $query): string
233 | ```
234 |
235 | **Example**
236 |
237 | ```php
238 | executeMultiple($query);
244 | print_r($result);
245 | ```
246 | Refs:
247 | - [Ref:http.ts Implementation](https://github.com/tursodatabase/libsql-client-ts/blob/main/packages/libsql-client/src/http.ts#L124-L140)
248 | - [Ref:HRANA_3_SPEC](https://github.com/tursodatabase/libsql/blob/main/docs/HRANA_3_SPEC.md#L844)
249 |
250 | ## Initiates a transaction for executing SQL queries either remotely or locally
251 |
252 | This method `transaction()` initiates a transaction for executing SQL queries either remotely or locally, depending on the connection mode set during initialization. It supports different transaction modes such as deferred, write, and read.
253 |
254 | For **remote usage**, you can start a new transaction using `$db->transaction()`, then add SQL statements using `addTransaction()`, and finally end the transaction using `endTransaction()`.
255 |
256 | For **local usage**, you can specify the transaction mode (defaulting to 'deferred') and then execute SQL statements using `exec()`. You can then commit the changes using `commit()` or rollback using `rollback()` based on the success of the operations.
257 |
258 | Here's an example of both remote and local usage:
259 |
260 | ```php
261 | // Remote Usage
262 | $transaction = $db->transaction();
263 | $transaction->addTransaction(HttpStatement::create("UPDATE users SET name = 'Turso DB' WHERE id = 1"));
264 | $transaction->addTransaction(HttpStatement::create("UPDATE users SET name = 'darkterminal' WHERE id = 2"));
265 | $result = $transaction->endTransaction();
266 | print_r($result);
267 |
268 | // Local / Remote Replica Usage
269 | $tx = $db->transaction(TransactionBehavior::Deferred);
270 | $tx->exec("INSERT INTO users (name) VALUES (?)", ["Emanuel"]);
271 | $tx->exec("INSERT INTO users (name) VALUES (?)", ["Darren"]);
272 |
273 | if ($operations_successful) {
274 | $tx->commit();
275 | echo "Commit the changes" . PHP_EOL;
276 | } else {
277 | $tx->rollback();
278 | echo "Rollback the changes" . PHP_EOL;
279 | }
280 | ```
281 |
282 | The method returns an instance of `HttpTransaction` for remote connections and `Transaction` for local connections.
283 |
284 | ## Synchronizes the database
285 |
286 | This method `sync()` synchronizes the database, but it's only supported for **RemoteReplica** and **LocalReplica**. If called in Remote (HTTP) or Local (FILE) mode, it will throw a `LibsqlError`.
287 |
288 | ## Close the database connection
289 |
290 | This method `close()` is responsible for closing the database connection, whether it's a remote (HTTP) connection or a local (FILE) connection. If the connection mode is not recognized, it throws a `LibsqlError`.
291 |
292 |
--------------------------------------------------------------------------------
/docs/Providers/HttpClient.md:
--------------------------------------------------------------------------------
1 | # HttpClient
2 |
3 | The `HttpClient` trait provides functionality to interact with HTTP resources, including executing HTTP requests and handling responses.
4 |
5 | ## Namespace:
6 | - `Darkterminal\LibSQL\Providers`
7 |
8 | ## Uses:
9 | - `Darkterminal\LibSQL\Types\HttpResponse`
10 | - `Darkterminal\LibSQL\Types\HttpStatement`
11 | - `Darkterminal\LibSQL\Types\TransactionMode`
12 | - `Darkterminal\LibSQL\Utils\Exceptions\LibsqlError`
13 | - `GuzzleHttp\Client`
14 | - `GuzzleHttp\Exception\RequestException`
15 | - `GuzzleHttp\Psr7\Request`
16 | - `Psr\Http\Message\ResponseInterface`
17 |
18 | ## Properties:
19 | - `$http`: Client
20 | - `$timeout`: int|float
21 | - `$url`: string
22 | - `$authToken`: string|null
23 | - `$headers`: array
24 | - `$baton`: string
25 | - `$collectors`: array
26 |
27 | ## Methods:
28 |
29 | ### protected function setup(string $url, string|null $authToken = null, int|float $timeout = 2.0)
30 | **Description:** Initializes a new HttpClient instance.
31 |
32 | **Link:** N/A
33 |
34 | **Parameters:**
35 | - `$url`: The base URL for HTTP requests.
36 | - `$authToken` (Optional): The authentication token for accessing the URL.
37 | - `$timeout`: The timeout duration for HTTP requests.
38 |
39 | ### public function connect(): bool|LibsqlError
40 | **Description:** Connects to the HTTP server.
41 |
42 | **Link:** N/A
43 |
44 | ### public function execute(HttpStatement $query, string $baton = ''): HttpResponse
45 | **Description:** Executes an HTTP statement.
46 |
47 | **Link:** [Turso - Simple Query](https://docs.turso.tech/sdk/http/reference#simple-query)
48 |
49 | **Parameters:**
50 | - `$query`: The HTTP statement to execute.
51 | - `$baton` (Optional): The baton string.
52 |
53 | ### public function batch(array $queries, string $mode = 'deferred'): HttpResponse
54 | **Description:** Executes a batch of HTTP statements.
55 |
56 | **Link:** [Turso - Interactive Query](https://docs.turso.tech/sdk/http/reference#interactive-query)
57 |
58 | **Parameters:**
59 | - `$queries`: The array of HTTP statements to execute.
60 | - `$mode` (Optional): The transaction mode (read, write, or deferred).
61 |
62 | ### public function executeMultiple(string $sql): void
63 | **Description:** Executes multiple SQL statements in sequence.
64 |
65 | **Link:** [Hrana Over HTTP - Sequence](https://github.com/tursodatabase/libsql/blob/main/docs/HRANA_3_SPEC.md#execute-a-sequence-of-sql-statements-1)
66 |
67 | **Parameters:**
68 | - `$sql`: The SQL statements to execute.
69 |
70 | ### public function startTransaction(string $mode = 'write'): self
71 | **Description:** Starts a transaction with the specified mode.
72 |
73 | **Link:** N/A
74 |
75 | **Parameters:**
76 | - `$mode` (Optional): The transaction mode (read, write, or deferred).
77 |
78 | ### public function addTransaction(HttpStatement $query): self
79 | **Description:** Adds a transaction to the transaction batch.
80 |
81 | **Link:** N/A
82 |
83 | **Parameters:**
84 | - `$query`: The HTTP statement to add to the transaction.
85 |
86 | ### public function endTransaction(): HttpResponse
87 | **Description:** Ends the current transaction batch and commits the transactions.
88 |
89 | **Link:** N/A
90 |
91 | ### public function rollback(): void
92 | **Description:** Rolls back the current transaction.
93 |
94 | **Link:** N/A
95 |
96 | ### public function commit(): void
97 | **Description:** Commits the current transaction.
98 |
99 | **Link:** N/A
100 |
101 | ### public function close(): void
102 | **Description:** Closes the HTTP client connection.
103 |
104 | **Link:** N/A
105 |
106 | ### public function version(): string
107 | **Description:** Retrieves the version from the HTTP server.
108 |
109 | **Link:** N/A
110 |
111 | ### protected function runQuery(array $payload, bool $trace = false): HttpResponse|ResponseInterface
112 | **Description:** Runs an HTTP query with the provided payload.
113 |
114 | **Link:** N/A
115 |
116 | **Parameters:**
117 | - `$payload`: The payload for the HTTP query.
118 | - `$trace` (Optional): Whether to return the raw response without mapping results.
119 |
120 | ### private function _makeRequest(array $data, bool $close = true, string $baton = ''): array
121 | **Description:** Creates a payload for making a request.
122 |
123 | **Link:** N/A
124 |
125 | **Parameters:**
126 | - `$data`: The data to include in the payload.
127 | - `$close` (Optional): Whether to include a close request.
128 | - `$baton` (Optional): The baton string.
129 |
130 | ### private function _close(): array
131 | **Description:** Creates a request array for closing the connection.
132 |
133 | **Link:** N/A
134 |
135 | ### private function _createRequest(string $type = \LIBSQL_EXECUTE, string $sql, ?array $args = [], ?bool $named_args = false): array
136 | **Description:** Creates a request array for execution with the provided SQL statement and arguments.
137 |
138 | **Link:** N/A
139 |
140 | **Parameters:**
141 | - `$type`: The type statement to execute.
142 | - `$sql`: The SQL statement to execute.
143 | - `$args` (Optional): The arguments for the SQL statement.
144 | - `$named_args` (Optional): Whether the arguments are named or positional.
145 |
146 | ### private function _argumentsGenerator($args): array
147 | **Description:** Generates arguments array for the HTTP request payload.
148 |
149 | **Link:** N/A
150 |
151 | **Parameters:**
152 | - `$args`: The arguments to be processed.
153 |
154 | ### private function _namedArgumentsGenerator(array $args): array
155 | **Description:** Generates named arguments array for the HTTP request payload.
156 |
157 | **Link:** N/A
158 |
159 | **Parameters:**
160 | - `$args`: The named arguments to be processed.
161 |
162 | ### private function _typeParser(mixed $value): string
163 | **Description:** Parses the type of the value.
164 |
165 | **Link:** N/A
166 |
167 | **Parameters:**
168 | - `$value`: The value to determine the type for.
169 |
--------------------------------------------------------------------------------
/docs/Quickstart.md:
--------------------------------------------------------------------------------
1 | # SDK Quickstart Guide
2 |
3 | ## Installation
4 |
5 | ```bash
6 | composer require darkterminal/libsql-client-php
7 | ```
8 |
9 | ## Local Usage
10 |
11 | ```php
12 | "file:database.db", // use in-memory database with :memory:
20 | "flags" => LIBSQLPHP_OPEN_READWRITE | LIBSQLPHP_OPEN_CREATE,
21 | "encryptionKey" => "" // optional
22 | ];
23 |
24 | $db = new LibSQL($config);
25 |
26 | if ($db->connect()) {
27 | echo "Connection Establised!" . PHP_EOL;
28 | echo "--- ". $db->version() ." ---" . PHP_EOL;
29 | }
30 | $db->close();
31 | ```
32 |
33 | ## Remote Usage
34 |
35 | ```php
36 | getenv('TURSO_DATABASE_URL'), // libsql://database-org.turso.io
46 | 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'), // your turso db token here
47 | ];
48 |
49 | $db = new LibSQL($config);
50 |
51 | if ($db->connect()) {
52 | echo "Connection Establised!" . PHP_EOL;
53 | echo "--- ". $db->version() ." ---" . PHP_EOL;
54 | }
55 |
56 |
57 | // Simple Query
58 | $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
59 | $results = $db->execute(query: $query);
60 | echo $results->fetch(type: LibSQLResult::FETCH_OBJ) . PHP_EOL;
61 | ```
62 |
63 | ## Remote Replica Connection
64 |
65 | ```php
66 | $config = [
67 | "url" => "file:database.db",
68 | "authToken" => getenv('TURSO_DATABASE_TOKEN'),
69 | "syncUrl" => getenv('TURSO_DATABASE_URL'),
70 | "syncInterval" => 5, // optional, default is 5 second
71 | "read_your_writes" => true // optional, default is true
72 | ];
73 |
74 | $db = new LibSQL($config);
75 | ```
76 |
77 | ## Read more
78 | - [LibSQL PHP SDK](LibSQL.md)
79 | - [Local Example](https://github.com/darkterminal/libsql-client-php/tree/main/examples/local-file)
80 | - [Remote Example](https://github.com/darkterminal/libsql-client-php/tree/main/examples/remote-http)
81 | - [Remote Replica Example](https://github.com/darkterminal/libsql-client-php/tree/main/examples/remote-http)
82 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction LibSQL Client PHP
2 |
3 | > _Keywords: Doc, Ref the link tags that will redirect you into (Doc) documentation and (Ref) the code._
4 |
5 | This is the first **LibSQL Client for PHP** that can interact with **LibSQL** server natively via the **LibSQL PHP Extension** which is written with Rust C Binding and communicates with PHP via FFI.
6 |
7 | The **LibSQL Client PHP** is a versatile library designed to facilitate interactions with both local and remote **LibSQL** databases from **PHP** applications. It abstracts the complexities of establishing connections, executing queries, managing transactions, and synchronizing databases, providing a unified API that supports various URL schemes including "`file:`", "`libsql:`", "`https:`", and "`http:`". The library caters to different operational modes, namely Remote and Local, allowing for seamless database operations across different environments.
8 |
9 | For remote connections, it leverages HTTP clients to communicate with LibSQL servers, supporting functionalities like executing batch queries, managing transactions with different behaviors (e.g., deferred, write, read), and executing multiple SQL queries in a single HTTP request. For local connections, it interfaces with local database files, offering capabilities to execute queries, perform batch operations, and manage transactions directly on the local file system.
10 |
11 | The library ensures robust error handling, throwing LibsqlError exceptions for unsupported URL schemes, TLS configuration issues, and other operational errors. It also provides a sync method for database synchronization in specific configurations, although this feature is not supported in basic Remote (HTTP) or Local (FILE) modes.
12 |
13 | Here's a quick overview of its key features:
14 |
15 | - **Connection Management**: Establishes connections to both local and remote databases with flexible configuration options.
16 | - **Query Execution**: Supports executing SQL queries, with special considerations for named parameters in remote connections.
17 | - **Batch Operations**: Enables executing a batch of queries in a single operation, particularly useful for remote connections.
18 | - **Transaction Management**: Facilitates starting, managing, and committing transactions with customizable behaviors.
19 | - **Synchronization**: Offers a synchronization mechanism for databases configured for replication, though with mode-specific limitations.
20 | - **Error Handling**: Robustly handles errors and operational exceptions, ensuring clear feedback on issues like unsupported configurations or operational failures.
21 |
22 | This library stands out for its adaptability and ease of use, making it a valuable tool for PHP developers working with LibSQL databases in varied environments.
23 |
24 | ## Table of Contents
25 |
26 | This table of contents is sorted hierarchically based on the _Main Class_ to its derivatives to make it easier for readers to understand the process that runs the **LibSQL Client PHP**.
27 |
28 | 1. [LibSQL](LibSQL.md) - The main class for interacting with the **LibSQL** service
29 | - 1.1 - [Instanciated](LibSQL.md#instanciated) - Initializes a new instance of **LibSQL**
30 | - 1.2 - [Connection](LibSQL.md#connection) - Establishes a connection to the database
31 | - 1.3 - [Version](LibSQL.md#version) - Retrieves the version information of the database
32 | - 1.4 - [Executes a Query](LibSQL.md#executes-a-query) - Allows you to execute a query either locally or remotely
33 | - 1.5 - [(Remote) Executes a Batch of Queries](LibSQL.md#remote-executes-a-batch-of-queries) - Executes a batch of queries **exclusively for remote connections**
34 | - 1.6 - [(Local) Executes a Batch of Queries](LibSQL.md#local-executes-a-batch-of-queries) - Executes a batch of queries exclusively for local (file) connections
35 | - 1.7 - [Executes Multiple](LibSQL.md#executes-multiple-sql-queries-in-a-single-http-request) - Allows you to execute multiple SQL queries in a single HTTP request
36 | - 1.8 - [Transaction](LibSQL.md#initiates-a-transaction-for-executing-sql-queries-either-remotely-or-locally) - Initiates a transaction for executing SQL queries either remotely or locally
37 | - 1.9 - [Sync](LibSQL.md#synchronizes-the-database) - Synchronizes the database
38 | - 1.0.1 - [Close](LibSQL.md#close-the-database-connection) - Close the database connection
39 | 2. Providers
40 | - 2.1 - [HttpClient](Providers/HttpClient.md) - The `HttpClient` class provides functionality to interact with HTTP resources
41 | - 2.2 - [LocalClient](Providers/LocalClient.md) - The `LocalClient` class provides functionality to interact with Local file database
42 |
--------------------------------------------------------------------------------
/docs/Traits/Logging.md:
--------------------------------------------------------------------------------
1 | # Logging
2 |
3 | This trait provides logging functionality for error messages.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Traits
7 |
8 | ## Methods:
9 | - public - log
10 | Description: Log a message to the error log file.
11 | Link: [None]
12 | Parameters:
13 | - $message (mixed): The message to log.
14 | - protected - checkAndCreateDirectoryAndFile
15 | Description: Check and create the directory and error log file if they don't exist.
16 | Link: [None]
17 | Parameters:
18 | - None
19 |
20 | ---
21 |
22 | ## Overview:
23 | The `Logging` trait provides two methods:
24 | - **log**: Logs a message to the error log file. It takes a message as input and appends it to the log file along with a timestamp.
25 | - **checkAndCreateDirectoryAndFile**: Checks if the directory and error log file exist. If they don't exist, it creates them. It returns the path to the error log file.
26 |
27 | This trait is used for logging error messages within the `LibSQL` library.
28 |
--------------------------------------------------------------------------------
/docs/Traits/MapResults.md:
--------------------------------------------------------------------------------
1 | # MapResults
2 |
3 | This trait provides methods to map results from JSON data to arrays or JSON objects.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Traits
7 |
8 | ## Uses:
9 | - Darkterminal\LibSQL\Types\HttpResultSets
10 |
11 | ## Methods:
12 | - protected - fetchArray
13 | Description: Fetch the results as an array.
14 | Link: [None]
15 | Parameters:
16 | - $data (string|array|HttpResultSets): The JSON data containing the results.
17 | - protected - fetchObject
18 | Description: Fetch the results as a JSON object.
19 | Link: [None]
20 | Parameters:
21 | - $data (string|array|HttpResultSets): The JSON data containing the results.
22 | - private - _results
23 | Description: Parse the JSON data and extract the results.
24 | Link: [None]
25 | Parameters:
26 | - $data (string|array|HttpResultSets): The JSON data containing the results.
27 |
28 | ---
29 |
30 | ## Overview:
31 | The `MapResults` trait provides methods to fetch the results from JSON data either as an array or a JSON object. It includes the following methods:
32 |
33 | - **fetchArray**: Fetches the results as an array.
34 | - **fetchObject**: Fetches the results as a JSON object.
35 | - **_results**: Private method to parse the JSON data and extract the results.
36 |
37 | The trait is used for mapping results within the `LibSQL` library and depends on the `HttpResultSets` type.
38 |
--------------------------------------------------------------------------------
/docs/Types/Authoriy.md:
--------------------------------------------------------------------------------
1 | # Authority
2 |
3 | Represents the authority part of a URI.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - UserInfo
10 |
11 | ## Properties:
12 | - **host** (string) - The host part of the authority.
13 | - **port** (int|null) - The port part of the authority, or null if not specified.
14 | - **userInfo** (UserInfo|null) - The user information part of the authority, or null if not specified.
15 |
16 | ## Methods:
17 | - **public** - `__construct`
18 | Description: Constructs a new Authority object.
19 | Parameters:
20 | - host (string) - The host part of the authority.
21 | - port (int|null) - The port part of the authority, or null if not specified.
22 | - userInfo (UserInfo|null) - The user information part of the authority, or null if not specified.
23 |
24 | - **public static** - `create`
25 | Description: Creates a new Authority object.
26 | Parameters:
27 | - host (string) - The host part of the authority.
28 | - port (int|null) - The port part of the authority, or null if not specified.
29 | - userInfo (UserInfo|null) - The user information part of the authority, or null if not specified.
30 |
31 | - **public** - `toArray`
32 | Description: Convert the Authority object to an array.
33 | Returns: An array representation of the Authority object.
34 |
35 | - **public** - `toObject`
36 | Description: Converts the Authority instance to a JSON string.
37 | Returns: The JSON representation of the Authority instance.
38 |
39 | ---
40 |
41 | ## Overview:
42 | The `Authority` class represents the authority part of a URI. It contains properties such as the host, port, and user information. This class provides methods to create an Authority object, convert it to an array, and serialize it to JSON.
43 |
--------------------------------------------------------------------------------
/docs/Types/Config.md:
--------------------------------------------------------------------------------
1 | # Config
2 |
3 | Configuration object for createClient.
4 |
5 | The client supports `libsql:`, `http:`/`https`:, `ws:`/`wss:` and `file:` URL. For more information, please refer to the project README:
6 | [Supported Urls](https://github.com/libsql/libsql-client-php#supported-urls)
7 |
8 | ## Namespace:
9 | - Darkterminal\LibSQL\Types
10 |
11 | ## Uses:
12 | None
13 |
14 | ## Properties:
15 | - **url** (string) - The database URL.
16 | - **authToken** (string|null) - Authentication token for the database.
17 | - **encryptionKey** (string|null) - Encryption key for the database.
18 | - **syncUrl** (string|null) - URL of a remote server to synchronize database with.
19 | - **syncInterval** (int|null) - Sync interval in seconds.
20 | - **tls** (bool|null) - Enables or disables TLS for libsql: URLs.
21 |
22 | ## Methods:
23 | - **public** - `__construct`
24 | Description: Constructs a new Config object.
25 | Parameters:
26 | - url (string) - The database URL.
27 | - authToken (string|null) - Authentication token for the database.
28 | - encryptionKey (string|null) - Encryption key for the database.
29 | - syncUrl (string|null) - URL of a remote server to synchronize database with.
30 | - syncInterval (int|null) - Sync interval in seconds.
31 | - tls (bool|null) - Enables or disables TLS for libsql: URLs.
32 |
33 | - **public static** - `create`
34 | Description: Creates a new Config object.
35 | Parameters:
36 | - url (string) - The database URL.
37 | - authToken (string|null) - Authentication token for the database.
38 | - encryptionKey (string|null) - Encryption key for the database.
39 | - syncUrl (string|null) - URL of a remote server to synchronize database with.
40 | - syncInterval (int|null) - Sync interval in seconds.
41 | - tls (bool|null) - Enables or disables TLS for libsql: URLs.
42 |
43 | - **public** - `toArray`
44 | Description: Convert the Config object to an array.
45 | Returns: The Config properties as an array.
46 |
47 | - **public** - `toObject`
48 | Description: Converts the Config instance to a JSON string.
49 | Returns: The JSON representation of the Config instance.
50 |
51 | ---
52 |
53 | ## Overview:
54 | The `Config` class represents a configuration object for creating a client. It contains properties such as the database URL, authentication token, encryption key, synchronization URL, synchronization interval, and TLS flag. This class provides methods to create a Config object, convert it to an array, and serialize it to JSON.
55 |
--------------------------------------------------------------------------------
/docs/Types/ExpandedConfig.md:
--------------------------------------------------------------------------------
1 | # ExpandedConfig
2 |
3 | Represents an expanded configuration object.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - Authority
10 |
11 | ## Properties:
12 | - **scheme** (string) - The scheme part of the configuration.
13 | - **tls** (bool) - Indicates whether TLS is enabled.
14 | - **authority** (Authority|null) - The authority part of the configuration, or null if not specified.
15 | - **path** (string) - The path part of the configuration.
16 | - **authToken** (string|null) - Authentication token for the configuration.
17 | - **syncUrl** (string|null) - URL of a remote server to synchronize configuration with.
18 | - **syncInterval** (int|null) - Sync interval in seconds.
19 |
20 | ## Methods:
21 | - **public** - `__construct`
22 | Description: Constructs a new ExpandedConfig object.
23 | Parameters:
24 | - scheme (string) - The scheme part of the configuration.
25 | - tls (bool) - Indicates whether TLS is enabled.
26 | - authority (Authority|null) - The authority part of the configuration, or null if not specified.
27 | - path (string) - The path part of the configuration.
28 | - authToken (string|null) - Authentication token for the configuration.
29 | - syncUrl (string|null) - URL of a remote server to synchronize configuration with.
30 | - syncInterval (int|null) - Sync interval in seconds.
31 |
32 | - **public static** - `create`
33 | Description: Creates a new ExpandedConfig object.
34 | Parameters:
35 | - scheme (string) - The scheme part of the configuration.
36 | - tls (bool) - Indicates whether TLS is enabled.
37 | - authority (Authority|null) - The authority part of the configuration, or null if not specified.
38 | - path (string) - The path part of the configuration.
39 | - authToken (string|null) - Authentication token for the configuration.
40 | - syncUrl (string|null) - URL of a remote server to synchronize configuration with.
41 | - syncInterval (int|null) - Sync interval in seconds.
42 |
43 | - **public** - `toArray`
44 | Description: Convert the ExpandedConfig object to an array.
45 | Returns: An array representation of the ExpandedConfig object.
46 |
47 | - **public** - `toObject`
48 | Description: Converts the ExpandedConfig instance to a JSON string.
49 | Returns: The JSON representation of the ExpandedConfig instance.
50 |
51 | ---
52 |
53 | ## Overview:
54 | The `ExpandedConfig` class represents an expanded configuration object. It contains properties such as the scheme, TLS flag, authority, path, authentication token, synchronization URL, and synchronization interval. This class provides methods to create an ExpandedConfig object, convert it to an array, and serialize it to JSON.
55 |
--------------------------------------------------------------------------------
/docs/Types/ExpandedScheme.md:
--------------------------------------------------------------------------------
1 | # ExpandedScheme
2 |
3 | The ExpandedScheme class provides constants representing expanded schemes for various protocols.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | None
10 |
11 | ## Properties:
12 | None
13 |
14 | ## Methods:
15 | None
16 |
17 | ## Constants:
18 | - **wss** (string) - Represents the wss scheme.
19 | - **ws** (string) - Represents the ws scheme.
20 | - **https** (string) - Represents the https scheme.
21 | - **http** (string) - Represents the http scheme.
22 | - **file** (string) - Represents the file scheme.
23 |
24 | ---
25 |
26 | ## Overview:
27 | The `ExpandedScheme` class provides constants representing expanded schemes for various protocols such as wss, ws, https, http, and file. These constants can be used to reference these schemes throughout the application.
28 |
--------------------------------------------------------------------------------
/docs/Types/HeirPart.md:
--------------------------------------------------------------------------------
1 | # HierPart
2 |
3 | Represents the hierarchical part of a URI.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - Authority
10 |
11 | ## Properties:
12 | - **authority** (Authority|null) - The authority part of the hierarchical part, or null if not specified.
13 | - **path** (string) - The path part of the hierarchical part.
14 |
15 | ## Methods:
16 | - **public** - `__construct`
17 | Description: Constructs a new HierPart object.
18 | Parameters:
19 | - authority (Authority|null) - The authority part of the hierarchical part, or null if not specified.
20 | - path (string) - The path part of the hierarchical part.
21 |
22 | - **public static** - `create`
23 | Description: Creates a new HierPart object.
24 | Parameters:
25 | - authority (Authority|null) - The authority part of the hierarchical part, or null if not specified.
26 | - path (string) - The path part of the hierarchical part.
27 |
28 | - **public** - `toArray`
29 | Description: Convert the HierPart object to an array.
30 | Returns: An array representation of the HierPart object.
31 |
32 | - **public** - `toObject`
33 | Description: Converts the HierPart instance to a JSON string.
34 | Returns: The JSON representation of the HierPart instance.
35 |
36 | ---
37 |
38 | ## Overview:
39 | The `HierPart` class represents the hierarchical part of a URI. It contains properties such as the authority and the path. This class provides methods to create a HierPart object, convert it to an array, and serialize it to JSON.
40 |
--------------------------------------------------------------------------------
/docs/Types/HttpResponse.md:
--------------------------------------------------------------------------------
1 | # HttpResponse
2 |
3 | The `HttpResponse` class represents an HTTP response from LibSQL Server. It contains properties such as the baton identifier, base URL, and HTTP result sets. This class provides methods to create an HttpResponse object, convert it to an array or JSON string, fetch results, and handle errors.
4 |
5 | ## Instanciated
6 |
7 | The constructor initializes a new `HttpResponse` instance with the provided parameters - `$baton`, `$base_url`, and `$results`. It assigns these parameters to the corresponding properties of the class. _(Leave this alone!)_
8 |
9 | ```php
10 | public function __construct(
11 | public string|null $baton,
12 | public string|null $base_url,
13 | public array|HttpResultSets $results
14 | )
15 | ```
16 | ## Create "static" Method
17 |
18 | Creates a new instance of the `HttpResponse` class.
19 |
20 | ```php
21 | public static function create(
22 | string|null $baton,
23 | string|null $base_url,
24 | array|HttpResultSets $results
25 | ): self
26 | ```
27 |
28 | **Example Usage**
29 |
30 | ```php
31 | $data = map_results($response->getBody());
32 | return HttpResponse::create($data['baton'], $data['base_url'], $data['results']);
33 | ```
34 |
35 | ## toArray
36 |
37 | Converts the result set to an associative array representation. It includes the baton, base URL, and the results converted to an array using the `objectToArray()` function.
38 |
39 | ```php
40 | public function toArray(): array
41 | ```
42 |
43 | ## toObject
44 |
45 | Converts the result set to a JSON-encoded string representation. It internally uses the `toArray()` method to convert the result set to an associative array before encoding it as JSON.
46 |
47 | ```php
48 | public function toObject(): string
49 | ```
50 |
51 | ## first
52 |
53 | Retrieve the first result set from the query execution.
54 |
55 | Returns a new instance of the current class containing the first result set obtained from the executed query. It converts the internal result object to an array and extracts the first element to create a new instance.
56 |
57 | ```php
58 | public function first(): self
59 | ```
60 |
61 | **Example Usage**
62 |
63 | ```php
64 | $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
65 | $results = $db->execute(query: $query);
66 | $results->first();
67 | ```
68 |
69 | ## fetch
70 |
71 | Fetch the result set from the query execution.
72 |
73 | Retrieves the result set from the executed query and returns it in the specified format. It converts the internal result object to an array and switches based on the provided type parameter to determine the format of the returned data.
74 |
75 | ```php
76 | public function fetch(int $type = LibSQLResult::FETCH_ASSOC): array|string
77 | ```
78 |
79 | **Example Usage**
80 |
81 | ```php
82 | $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
83 | $results = $db->execute(query: $query);
84 | echo $results->fetch(type: LibSQLResult::FETCH_OBJ) . PHP_EOL;
85 | ```
86 |
--------------------------------------------------------------------------------
/docs/Types/HttpResultSets.md:
--------------------------------------------------------------------------------
1 | # HttpResultSets
2 |
3 | Represents a set of HTTP result data.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - None
10 |
11 | ## Properties:
12 | - **cols** (array) - The columns of the result set.
13 | - **rows** (array) - The rows of the result set.
14 | - **affected_row_count** (int) - The number of affected rows.
15 | - **last_insert_rowid** (int|null) - The last inserted row ID.
16 | - **replication_index** (int|string) - The replication index.
17 |
18 | ## Methods:
19 | - **public** - `__construct`
20 | Description: Constructs a new HttpResultSets instance.
21 | Parameters:
22 | - cols (array) - The columns of the result set.
23 | - rows (array) - The rows of the result set.
24 | - affected_row_count (int) - The number of affected rows.
25 | - last_insert_rowid (int|null) - The last inserted row ID.
26 | - replication_index (int|string) - The replication index.
27 |
28 | - **public static** - `create`
29 | Description: Creates a new HttpResultSets instance.
30 | Parameters:
31 | - cols (array) - The columns of the result set.
32 | - rows (array) - The rows of the result set.
33 | - affected_row_count (int) - The number of affected rows.
34 | - last_insert_rowid (int|null) - The last inserted row ID.
35 | - replication_index (int|string) - The replication index.
36 |
37 | - **public** - `toArray`
38 | Description: Convert the HttpResultSets instance to an array.
39 | Returns: The array representation of the HttpResultSets instance.
40 |
41 | - **public** - `toObject`
42 | Description: Converts the HttpResultSets instance to a JSON string.
43 | Returns: The JSON representation of the HttpResultSets instance.
44 |
45 | ---
46 |
47 | ## Overview:
48 | The `HttpResultSets` class represents a set of HTTP result data. It contains properties such as the columns, rows, affected row count, last inserted row ID, and replication index. This class provides methods to create an HttpResultSets object, convert it to an array or JSON string.
49 |
--------------------------------------------------------------------------------
/docs/Types/HttpStatement.md:
--------------------------------------------------------------------------------
1 | # HttpStatement
2 |
3 | The `HttpStatement` class represents an HTTP statement with SQL and optional arguments. It contains properties such as the SQL statement, optional arguments, and whether the arguments are named or positional. This class provides methods to create an HttpStatement object, convert it to an array or JSON string.
4 |
5 | ## Instanciated
6 |
7 | Constructs a new `HttpStatement` instance. _(Leave this alone!)_
8 |
9 | ```php
10 | public function __construct(
11 | public string $sql,
12 | public ?array $args = [],
13 | public ?bool $named_args = false
14 | )
15 | ```
16 | ## Create "static" Method
17 |
18 | Creates a new `HttpStatement` instance.
19 |
20 | ```php
21 | public static function create(
22 | string $sql,
23 | ?array $args = [],
24 | ?bool $named_args = false
25 | ): self
26 | ```
27 |
28 | **Example Usage**
29 |
30 | ```php
31 | $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
32 |
33 | // or
34 |
35 | $stmts = [
36 | HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Ramons", 32]),
37 | HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Georgia", 43])
38 | ];
39 | ```
40 |
41 | ## toArray
42 |
43 | Converts the `HttpStatement` instance to an array.
44 |
45 | ```php
46 | public function toArray(): array
47 | ```
48 |
49 | ## toObject
50 |
51 | Converts the `HttpStatement` instance to a JSON string.
52 |
53 | ```php
54 | public function toObject(): string
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/Types/KeyValue.md:
--------------------------------------------------------------------------------
1 | # KeyValue
2 |
3 | Represents a key-value pair in a query string.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - None
10 |
11 | ## Properties:
12 | - **key** (string) - The key of the key-value pair.
13 | - **value** (string) - The value of the key-value pair.
14 |
15 | ## Methods:
16 | - **public** - `__construct`
17 | Description: Constructs a new KeyValue instance.
18 | Parameters:
19 | - key (string) - The key of the key-value pair.
20 | - value (string) - The value of the key-value pair.
21 |
22 | - **public static** - `create`
23 | Description: Creates a new KeyValue instance.
24 | Parameters:
25 | - key (string) - The key of the key-value pair.
26 | - value (string) - The value of the key-value pair.
27 |
28 | - **public** - `toArray`
29 | Description: Convert the KeyValue object to an array.
30 | Returns: An array representation of the KeyValue object.
31 |
32 | - **public** - `toObject`
33 | Description: Converts the KeyValue instance to a JSON string.
34 | Returns: The JSON representation of the KeyValue instance.
35 |
36 | ---
37 |
38 | ## Overview:
39 | The `KeyValue` class represents a key-value pair in a query string. It contains properties such as the key and value. This class provides methods to create a KeyValue object, convert it to an array or JSON string.
40 |
--------------------------------------------------------------------------------
/docs/Types/LibSQLResult.md:
--------------------------------------------------------------------------------
1 | # LibSQLResult
2 |
3 | Represents different formats for fetching SQL results.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - None
10 |
11 | ## Properties:
12 | None
13 |
14 | ## Methods:
15 | None
16 |
17 | ## Constants:
18 | - **FETCH_ASSOC** (int) - Represents the associative array format for fetching SQL results.
19 | - **FETCH_OBJ** (int) - Represents the object format for fetching SQL results.
20 | - **FETCH_RAW** (int) - Represents the raw format for fetching SQL results.
21 |
22 | ---
23 |
24 | ## Overview:
25 | The `LibSQLResult` class represents different formats for fetching SQL results. It provides constants such as `FETCH_ASSOC`, `FETCH_OBJ`, and `FETCH_RAW`, which can be used to specify the format in which SQL results should be fetched.
26 |
--------------------------------------------------------------------------------
/docs/Types/Query.md:
--------------------------------------------------------------------------------
1 | # Query
2 |
3 | Represents the query part of a URI.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - None
10 |
11 | ## Properties:
12 | - **pairs** (array) - An array of key-value pairs representing the query parameters.
13 |
14 | ## Methods:
15 | - **public** - `__construct`
16 | Description: Constructs a new Query instance.
17 | Parameters:
18 | - pairs (array) - An array of key-value pairs representing the query parameters.
19 |
20 | - **public static** - `create`
21 | Description: Creates a new Query instance.
22 | Parameters:
23 | - pairs (array) - An array of key-value pairs representing the query parameters.
24 |
25 | - **public** - `toArray`
26 | Description: Convert the Query object to an array.
27 | Returns: An array representation of the Query object.
28 |
29 | - **public** - `toObject`
30 | Description: Converts the Query instance to a JSON string.
31 | Returns: The JSON representation of the Query instance.
32 |
33 | ---
34 |
35 | ## Overview:
36 | The `Query` class represents the query part of a URI. It contains a property `pairs`, which is an array of key-value pairs representing the query parameters. This class provides methods to create a Query object, convert it to an array or JSON string.
37 |
--------------------------------------------------------------------------------
/docs/Types/TransactionMode.md:
--------------------------------------------------------------------------------
1 | # TransactionMode
2 |
3 | The TransactionMode class provides constants representing transaction modes for database operations.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - ReflectionClass from PHP Standard Library
10 | - LibsqlError exception
11 |
12 | ## Properties:
13 | None
14 |
15 | ## Methods:
16 | - **public static** - `checker`
17 | Description: Checks if the given transaction mode is valid.
18 | Parameters:
19 | - mode (string) - The transaction mode to check.
20 | Returns: The valid transaction mode if it exists.
21 | Throws: LibsqlError if the transaction mode is not supported.
22 |
23 | ## Constants:
24 | - **write** (string) - Represents the write transaction mode.
25 | - **read** (string) - Represents the read transaction mode.
26 | - **deferred** (string) - Represents the deferred transaction mode.
27 |
28 | ---
29 |
30 | ## Overview:
31 | The `TransactionMode` class provides constants representing transaction modes for database operations, including write, read, and deferred. It also provides a `checker` method to validate transaction modes. If an invalid transaction mode is provided, it throws a `LibsqlError` exception.
32 |
--------------------------------------------------------------------------------
/docs/Types/Uri.md:
--------------------------------------------------------------------------------
1 | # Uri
2 |
3 | Represents a URI object.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - None
10 |
11 | ## Properties:
12 | - **scheme** (string) - The scheme part of the URI.
13 | - **authority** (Authority|null) - The authority part of the URI.
14 | - **path** (string) - The path part of the URI.
15 | - **query** (Query|null) - The query part of the URI.
16 | - **fragment** (string|null) - The fragment part of the URI.
17 |
18 | ## Methods:
19 | - **public** - `__construct`
20 | Description: Constructs a new Uri instance.
21 | Parameters:
22 | - scheme (string) - The scheme part of the URI.
23 | - authority (Authority|null) - The authority part of the URI.
24 | - path (string) - The path part of the URI.
25 | - query (Query|null) - The query part of the URI.
26 | - fragment (string|null) - The fragment part of the URI.
27 |
28 | - **public static** - `create`
29 | Description: Creates a new Uri instance.
30 | Parameters:
31 | - scheme (string) - The scheme part of the URI.
32 | - authority (Authority|null) - The authority part of the URI.
33 | - path (string) - The path part of the URI.
34 | - query (Query|null) - The query part of the URI.
35 | - fragment (string|null) - The fragment part of the URI.
36 |
37 | - **public** - `toArray`
38 | Description: Convert the Uri object to an array.
39 | Returns: An array representation of the Uri object.
40 |
41 | - **public** - `toObject`
42 | Description: Converts the Uri instance to a JSON string.
43 | Returns: The JSON representation of the Uri instance.
44 |
45 | ---
46 |
47 | ## Overview:
48 | The `Uri` class represents a URI object. It contains properties such as the scheme, authority, path, query, and fragment parts of the URI. This class provides methods to create a Uri object, convert it to an array or JSON string.
49 |
--------------------------------------------------------------------------------
/docs/Types/UserInfo.md:
--------------------------------------------------------------------------------
1 | # UserInfo
2 |
3 | Represents the userInfo part of a URI authority.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Types
7 |
8 | ## Uses:
9 | - None
10 |
11 | ## Properties:
12 | - **username** (string|null) - The username part of the userInfo.
13 | - **password** (string|null) - The password part of the userInfo.
14 |
15 | ## Methods:
16 | - **public** - `__construct`
17 | Description: Constructs a new UserInfo instance.
18 | Parameters:
19 | - username (string|null) - The username part of the userInfo.
20 | - password (string|null) - The password part of the userInfo.
21 |
22 | - **public static** - `create`
23 | Description: Creates a new UserInfo instance.
24 | Parameters:
25 | - username (string|null) - The username part of the userInfo.
26 | - password (string|null) - The password part of the userInfo.
27 |
28 | - **public** - `toArray`
29 | Description: Convert the UserInfo object to an array.
30 | Returns: An array representation of the UserInfo object.
31 |
32 | - **public** - `toObject`
33 | Description: Converts the UserInfo instance to a JSON string.
34 | Returns: The JSON representation of the UserInfo instance.
35 |
36 | ---
37 |
38 | ## Overview:
39 | The `UserInfo` class represents the userInfo part of a URI authority. It contains properties such as the username and password. This class provides methods to create a UserInfo object, convert it to an array or JSON string.
40 |
--------------------------------------------------------------------------------
/docs/Utils/Exceptions/LibsqlError.md:
--------------------------------------------------------------------------------
1 | # LibsqlError
2 |
3 | Error thrown by the client.
4 |
5 | ## Namespace:
6 | - Darkterminal\LibSQL\Utils\Exceptions
7 |
8 | ## Uses:
9 | - Darkterminal\LibSQL\Traits\Logging
10 |
11 | ## Properties:
12 | - **code**: string
13 | Machine-readable error code.
14 | - **rawCode**: int|null
15 | Raw numeric error code.
16 |
17 | ## Methods:
18 | - public - __construct
19 | Description: Constructor.
20 | Link: [None]
21 | Parameters:
22 | - $message (string): The error message.
23 | - $code (string): The machine-readable error code.
24 | - $rawCode (int|null): The raw numeric error code.
25 | - $cause (Throwable|null): The cause of the error.
26 |
27 | ---
28 |
29 | ## Overview:
30 | The `LibsqlError` class represents an error thrown by the client. It extends the built-in PHP `\Exception` class and includes the trait `Logging` from the namespace `Darkterminal\LibSQL\Traits`. It provides properties to store a machine-readable error code and a raw numeric error code. The constructor initializes the error message, error code, raw code, and the cause of the error if provided.
31 |
--------------------------------------------------------------------------------
/docs/Utils/constants.md:
--------------------------------------------------------------------------------
1 | ### `URI_RE`
2 |
3 | **Description:** Regular expression pattern for parsing URIs.
4 |
5 | **Value:** `'/^(?[A-Za-z][A-Za-z.+-]*):(\/\/(?[^\/?#]*))?(?[^?#]*)(\?(?[^#]*))?(#(?.*))?$/`
6 |
7 | ---
8 |
9 | ### `AUTHORITY_RE`
10 |
11 | **Description:** Regular expression pattern for parsing the authority part of a URL.
12 |
13 | **Value:** `'/^((?[^:]*)(:(?.*))?@)?((?[^:\[\]]*)|(\[(?[^\[\]]*)\]))(:(?[0-9]*))?$/`
14 |
15 | ---
16 |
17 | ### `SUPPORTED_URL_LINK`
18 |
19 | **Description:** Link to the documentation page for supported URLs.
20 |
21 | **Value:** `"https://github.com/libsql/libsql-client-php#supported-urls"`
22 |
23 | ---
24 |
25 | ### `TURSO`
26 |
27 | **Description:** A constant with the value `'turso.io'`.
28 |
29 | **Value:** `'turso.io'`
30 |
31 | ---
32 |
33 | ### `PIPE_LINE_ENDPOINT`
34 |
35 | **Description:** Endpoint for pipeline operations.
36 |
37 | **Value:** `'/v3/pipeline'`
38 |
39 | ---
40 |
41 | ### `VERSION_ENDPOINT`
42 |
43 | **Description:** Endpoint for version information.
44 |
45 | **Value:** `'/version'`
46 |
47 | ---
48 |
49 | ### `HEALTH_ENDPOINT`
50 |
51 | **Description:** Endpoint for health status.
52 |
53 | **Value:** `'/health'`
54 |
55 | ---
56 |
57 | ### `LIBSQL_CLOSE`, `LIBSQL_EXECUTE`, `LIBSQL_BATCH`, `LIBSQL_SEQUENCE`, `LIBSQL_DESCRIBE`, `LIBSQL_STORE_SQL`, `LIBSQL_GET_AUTO_COMMIT`
58 |
59 | **Description:** Constants representing different operations for LibSQL.
60 |
61 | **Values:** `'close'`, `'execute'`, `'bath'`, `'sequence'`, `'describe'`, `'store_sql'`, `'get_autocommit'`
62 |
--------------------------------------------------------------------------------
/docs/Utils/helpers.md:
--------------------------------------------------------------------------------
1 | # Helpers
2 |
3 | ### `transactionModeToBegin(string $mode): string`
4 |
5 | **Description:** Converts a transaction mode to a corresponding BEGIN statement.
6 |
7 | **Parameters:**
8 | - `$mode` (string): The transaction mode.
9 |
10 | **Returns:** string
11 |
12 | **Throws:** `\RangeException` if an unknown transaction mode is provided.
13 |
14 | ---
15 |
16 | ### `expandConfig(array $config, bool $preferHttp): ExpandedConfig`
17 |
18 | **Description:** Expands the provided client configuration into an `ExpandedConfig` object.
19 |
20 | **Parameters:**
21 | - `$config` (array): The client configuration array.
22 | - `$preferHttp` (bool): Whether to prefer HTTP over WebSocket.
23 |
24 | **Returns:** `ExpandedConfig`
25 |
26 | **Throws:** `TypeError` if the provided configuration is not an array, `LibsqlError` if there is an error in the configuration or unsupported URL scheme.
27 |
28 | ---
29 |
30 | ### `parseUri(string $text): Uri`
31 |
32 | **Description:** Parses a URI string and returns a `Uri` object.
33 |
34 | **Parameters:**
35 | - `$text` (string): The URI string to parse.
36 |
37 | **Returns:** `Uri`
38 |
39 | **Throws:** `LibsqlError` if the URI is not in a valid format.
40 |
41 | ---
42 |
43 | ### `parseAuthority(string $text): Authority`
44 |
45 | **Description:** Parses the authority part of a URL and returns an `Authority` object.
46 |
47 | **Parameters:**
48 | - `$text` (string): The authority part of the URL.
49 |
50 | **Returns:** `Authority`
51 |
52 | **Throws:** `LibsqlError` if the authority part of the URL is not in a valid format.
53 |
54 | ---
55 |
56 | ### `parseQuery(string $text): Query`
57 |
58 | **Description:** Parses the query string of a URI and returns a `Query` object.
59 |
60 | **Parameters:**
61 | - `$text` (string): The query string to parse.
62 |
63 | **Returns:** `Query`
64 |
65 | ---
66 |
67 | ### `percentDecode(string $text): string`
68 |
69 | **Description:** Decodes a percent-encoded string.
70 |
71 | **Parameters:**
72 | - `$text` (string): The string to decode.
73 |
74 | **Returns:** string
75 |
76 | **Throws:** `LibsqlError` if the URL component has invalid percent encoding.
77 |
78 | ---
79 |
80 | ### `encodeBaseUrl(string $scheme, ?Authority $authority, string $path): array|string|int|false|null`
81 |
82 | **Description:** Encodes the components of a URI and returns a URL object.
83 |
84 | **Parameters:**
85 | - `$scheme` (string): The scheme of the URI.
86 | - `$authority` (Authority|null): The authority of the URI.
87 | - `$path` (string): The path of the URI.
88 |
89 | **Returns:** array|string|int|false|null
90 |
91 | **Throws:** `LibsqlError` if the URL requires authority.
92 |
93 | ---
94 |
95 | ### `encodeHost(string $host): string`
96 |
97 | **Description:** Encodes the host component of a URI.
98 |
99 | **Parameters:**
100 | - `$host` (string): The host to encode.
101 |
102 | **Returns:** string
103 |
104 | ---
105 |
106 | ### `encodePort(?int $port): string`
107 |
108 | **Description:** Encodes the port component of a URI.
109 |
110 | **Parameters:**
111 | - `$port` (int|null): The port to encode.
112 |
113 | **Returns:** string
114 |
115 | ---
116 |
117 | ### `encodeUserInfo(?UserInfo $userInfo): string`
118 |
119 | **Description:** Encodes the userInfo component of a URI.
120 |
121 | **Parameters:**
122 | - `$userInfo` (UserInfo|null): The userInfo to encode.
123 |
124 | **Returns:** string
125 |
126 | ---
127 |
128 | ### `is_base64(string $data): bool`
129 |
130 | **Description:** Checks if a string is base64 encoded.
131 |
132 | **Parameters:**
133 | - `$data` (string): The string to check.
134 |
135 | **Returns:** bool
136 |
137 | ---
138 |
139 | ### `checkColumnType(mixed $column): string`
140 |
141 | **Description:** Determines the type of a given column value.
142 |
143 | **Parameters:**
144 | - `$column` (mixed): The column value to check.
145 |
146 | **Returns:** string
147 |
148 | ---
149 |
150 | ### `map_results(string $data): array`
151 |
152 | **Description:** Maps JSON data to a structured format.
153 |
154 | **Parameters:**
155 | - `$data` (string): The JSON data to be mapped.
156 |
157 | **Returns:** array
158 |
159 | **Throws:** `LibsqlError` if there is an error in the JSON data.
160 |
161 | ---
162 |
163 | ### `objectToArray($object)`
164 |
165 | **Description:** Recursively converts an object to an array.
166 |
167 | **Parameters:**
168 | - `$object`: The object to convert.
169 |
170 | **Returns:** mixed (array)
171 |
--------------------------------------------------------------------------------
/examples/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darkterminal/libsql-client-php/cb61687433498c3340c5ed37b1ed33129dc9efc0/examples/.gitkeep
--------------------------------------------------------------------------------
/examples/local-file/check-version.php:
--------------------------------------------------------------------------------
1 | "file:database.db",
9 | "flags" => LIBSQLPHP_OPEN_READWRITE | LIBSQLPHP_OPEN_CREATE,
10 | "encryptionKey" => ""
11 | ];
12 |
13 | $db = new LibSQL($config);
14 |
15 | if ($db->connect()) {
16 | echo "Connection Establised!" . PHP_EOL;
17 | echo "--- ". $db->version() ." ---" . PHP_EOL;
18 | }
19 | $db->close();
20 |
--------------------------------------------------------------------------------
/examples/local-file/execute.php:
--------------------------------------------------------------------------------
1 | "file:database.db",
9 | "flags" => LIBSQLPHP_OPEN_READWRITE | LIBSQLPHP_OPEN_CREATE,
10 | "encryptionKey" => ""
11 | ];
12 |
13 | $db = new LibSQL($config);
14 |
15 | if ($db->connect()) {
16 | echo "Connection Establised!" . PHP_EOL;
17 | echo "--- ". $db->version() ." ---" . PHP_EOL;
18 |
19 | $result = $db->execute(query: "INSERT INTO users (name) VALUES (?)", params: ['Belina Bogge']);
20 | var_dump($result);
21 | }
22 | $db->close();
23 |
--------------------------------------------------------------------------------
/examples/local-file/placeholders.php:
--------------------------------------------------------------------------------
1 | "file:database.db",
9 | "flags" => LIBSQLPHP_OPEN_READWRITE | LIBSQLPHP_OPEN_CREATE,
10 | "encryptionKey" => ""
11 | ];
12 |
13 | $db = new LibSQL($config);
14 |
15 | if ($db->connect()) {
16 | echo "Connection Establised!" . PHP_EOL;
17 | echo "--- ". $db->version() ." ---" . PHP_EOL;
18 |
19 | $result = $db->execute(query: "SELECT * FROM users");
20 | var_dump($result->toArray());
21 | }
22 | $db->close();
23 |
--------------------------------------------------------------------------------
/examples/remote-http/batch-query.php:
--------------------------------------------------------------------------------
1 | 'libsql://127.0.0.1:8001',
10 | 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'),
11 | 'tls' => false
12 | ];
13 |
14 | $db = new LibSQL($config);
15 |
16 | if ($db->connect()) {
17 | echo "Connection Establised!" . PHP_EOL;
18 | echo "--- " . $db->version() . " ---" . PHP_EOL;
19 | }
20 |
21 | // Batch Query Example
22 | $stmts = [
23 | HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Ramons", 32]),
24 | HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Georgia", 43])
25 | ];
26 | $results = $db->batch(queries: $stmts);
27 | print_r($results);
28 |
--------------------------------------------------------------------------------
/examples/remote-http/sequence-query.php:
--------------------------------------------------------------------------------
1 | 'libsql://127.0.0.1:8001',
9 | 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'),
10 | 'tls' => false
11 | ];
12 |
13 | $db = new LibSQL($config);
14 |
15 | if ($db->connect()) {
16 | echo "Connection Establised!" . PHP_EOL;
17 | echo "--- " . $db->version() . " ---" . PHP_EOL;
18 | }
19 |
20 |
21 | // Simple Query and Parameter Binding Example
22 | $query = "
23 | UPDATE users SET name = 'Turso DB' WHERE id = 1;
24 | UPDATE users SET name = 'ducktermin;
25 | ";
26 | $result = $db->executeMultiple($query);
27 | print_r($result);
28 |
--------------------------------------------------------------------------------
/examples/remote-http/simple-query.php:
--------------------------------------------------------------------------------
1 | 'libsql://127.0.0.1:8001',
11 | 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'),
12 | 'tls' => false
13 | ];
14 |
15 | $db = new LibSQL($config);
16 |
17 | if ($db->connect()) {
18 | echo "Connection Establised!" . PHP_EOL;
19 | echo "--- ". $db->version() ." ---" . PHP_EOL;
20 | }
21 |
22 |
23 | // Simple Query
24 | $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
25 | $results = $db->execute(query: $query);
26 | echo $results->fetch(type: LibSQLResult::FETCH_OBJ) . PHP_EOL;
27 | // print_r($results->fetch(type: LibSQLResult::FETCH_ASSOC));
28 |
--------------------------------------------------------------------------------
/examples/remote-http/transaction-query.php:
--------------------------------------------------------------------------------
1 | 'libsql://127.0.0.1:8001',
10 | 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'),
11 | 'tls' => false
12 | ];
13 |
14 | $db = new LibSQL($config);
15 |
16 | if ($db->connect()) {
17 | echo "Connection Establised!" . PHP_EOL;
18 | echo "--- " . $db->version() . " ---" . PHP_EOL;
19 | }
20 |
21 | // Start a new transaction
22 | $transaction = $db->transaction();
23 |
24 | // Add the first SQL statement to the transaction
25 | if (true) {
26 | $transaction->addTransaction(HttpStatement::create("UPDATE users SET name = 'Turso DB' WHERE id = 1"));
27 | } else {
28 | // If a condition is not met, rollback the transaction and exit
29 | $transaction->rollback();
30 | exit();
31 | }
32 |
33 | // Add the second SQL statement to the transaction
34 | if (true) {
35 | $transaction->addTransaction(HttpStatement::create("UPDATE users SET name = 'darkterminal' WHERE id = 2"));
36 | } else {
37 | // If another condition is not met, rollback the transaction and exit
38 | $transaction->rollback();
39 | exit();
40 | }
41 |
42 | // End the transaction (commit changes)
43 | $result = $transaction->endTransaction();
44 | print_r($result);
45 |
--------------------------------------------------------------------------------
/examples/remote-replica/connection.php:
--------------------------------------------------------------------------------
1 | "file:database.db",
9 | "authToken" => getenv('TURSO_DATABASE_TOKEN'),
10 | "syncUrl" => getenv('TURSO_DATABASE_URL'),
11 | "syncInterval" => 5,
12 | "read_your_writes" => true
13 | ];
14 |
15 | $db = new LibSQL($config);
16 |
17 | if ($db->connect()) {
18 | echo "Connection Establised!" . PHP_EOL;
19 | echo "--- ". $db->version() ." ---" . PHP_EOL;
20 | }
21 | $db->close();
22 |
--------------------------------------------------------------------------------
/src/LibSQL.php:
--------------------------------------------------------------------------------
1 | [A-Za-z][A-Za-z.+-]*):(\/\/(?[^\/?#]*))?(?[^?#]*)(\?(?[^#]*))?(#(?.*))?$/';
27 |
28 | public const AUTHORITY_RE = '/^((?[^:]*)(:(?.*))?@)?((?[^:\[\]]*)|(\[(?[^\[\]]*)\]))(:(?[0-9]*))?$/';
29 |
30 | public const SUPPORTED_URL_LINK = "https://github.com/libsql/libsql-client-php#supported-urls";
31 |
32 | public const TURSO = 'turso.io';
33 |
34 | public const PIPE_LINE_ENDPOINT = '/v3/pipeline';
35 |
36 | public const VERSION_ENDPOINT = '/version';
37 |
38 | public const HEALTH_ENDPOINT = '/health';
39 |
40 | public const LIBSQL_CLOSE = 'close';
41 |
42 | public const LIBSQL_EXECUTE = 'execute';
43 |
44 | public const LIBSQL_BATCH = 'bath';
45 |
46 | public const LIBSQL_SEQUENCE = 'sequence';
47 |
48 | public const LIBSQL_DESCRIBE = 'describe';
49 |
50 | public const LIBSQL_STORE_SQL = 'store_sql';
51 |
52 | public const LIBSQL_GET_AUTO_COMMIT = 'get_autocommit';
53 |
54 | public const REMOTE = 'Remote';
55 |
56 | public const REMOTE_REPLICA = 'RemoteReplica';
57 |
58 | public const LOCAL = 'Local';
59 |
60 | /**
61 | * @var HttpClient $httpProvider The HTTP client provider.
62 | */
63 | protected HttpClient $httpProvider;
64 |
65 | /**
66 | * @var LocalClient $localProvider The local client provider.
67 | */
68 | protected LocalClient $localProvider;
69 |
70 | /**
71 | * @var RemoteReplicaClient $remoteReplicaProvicer The Remote Replica client provider
72 | */
73 | protected RemoteReplicaClient $remoteReplicaProvider;
74 |
75 | /**
76 | * @var string $mode The current connection mode (either "Remote" or "Local").
77 | */
78 | protected string $mode;
79 |
80 | /**
81 | * Constructs a new LibSQL instance.
82 | *
83 | * **Example Local Connection**
84 | *
85 | * ```
86 | * $config = [
87 | * "url" => "file:database.db",
88 | * "flags" => LIBSQLPHP_OPEN_READWRITE | LIBSQLPHP_OPEN_CREATE,
89 | * "encryptionKey" => ""
90 | * ];
91 | *
92 | * $db = new LibSQL($config);
93 | * $db->connect();
94 | * ```
95 | *
96 | * **Example Remote Connection**
97 | *
98 | * ```
99 | * $config = [
100 | * 'url' => 'libsql://127.0.0.1:8001', // libsql://database-origanization.turso.io
101 | * 'authToken' => getenv('LIBSQL_PHP_FA_TOKEN'),
102 | * 'tls' => false
103 | * ];
104 | *
105 | * $db = new LibSQL($config);
106 | * ```
107 | *
108 | * @param array $config The configuration array for the LibSQL service.
109 | * @throws LibsqlError If there is an error creating the HTTP client.
110 | */
111 | public function __construct(array $config)
112 | {
113 | $configBuilder = Mods::expandConfig($config, true);
114 |
115 | if ($configBuilder->scheme === ExpandedScheme::file && !empty($configBuilder->authToken) && !empty($configBuilder->syncUrl)) {
116 | $this->remoteReplicaProvider = new RemoteReplicaClient(
117 | $configBuilder->path,
118 | $configBuilder->authToken,
119 | $configBuilder->syncUrl,
120 | $configBuilder->syncInterval,
121 | $configBuilder->read_your_writes
122 | );
123 | $this->mode = 'RemoteReplica';
124 | } else if (in_array($configBuilder->scheme, [ExpandedScheme::http, ExpandedScheme::https]) && !empty($configBuilder->authToken)) {
125 | if ($configBuilder->scheme !== ExpandedScheme::https && $configBuilder->scheme !== ExpandedScheme::http) {
126 | throw new LibsqlError(
127 | 'The HTTP client supports only "libsql:", "https:" and "http:" URLs, got ' . $configBuilder->scheme,
128 | "URL_SCHEME_NOT_SUPPORTED",
129 | );
130 | }
131 |
132 | if ($configBuilder->scheme === ExpandedScheme::http && $configBuilder->tls) {
133 | throw new LibsqlError('A "http:" URL cannot opt into TLS by using ?tls=1', "URL_INVALID");
134 | } else if ($configBuilder->scheme === ExpandedScheme::https && !$configBuilder->tls) {
135 | throw new LibsqlError('A "https:" URL cannot opt out of TLS by using ?tls=0', "URL_INVALID");
136 | }
137 |
138 | $url = Mods::encodeBaseUrl($configBuilder->scheme, $configBuilder->authority, $configBuilder->path);
139 | $this->httpProvider = new HttpClient();
140 | $this->httpProvider->setup($url, $configBuilder->authToken);
141 | $this->mode = 'Remote';
142 | } else if ($configBuilder->scheme === ExpandedScheme::file && !empty($configBuilder->flags) && !empty($configBuilder->path)) {
143 | $this->localProvider = new LocalClient();
144 | $this->localProvider->setup($configBuilder->path, $configBuilder->flags, $configBuilder->encryptionKey);
145 | $this->mode = "Local";
146 | } else {
147 | throw new LibsqlError('Invalid Connection! Only support Remote and Local connection', 'ERR_INVALID_CONNECTION');
148 | }
149 | }
150 |
151 | /**
152 | * Checking connection mode
153 | *
154 | * @return string
155 | */
156 | public function connectionMode(): string
157 | {
158 | return $this->mode;
159 | }
160 |
161 | /**
162 | * Establishes a connection to the database.
163 | *
164 | * @throws LibsqlError Thrown if the connection mode is not recognized.
165 | *
166 | * @return bool True if the connection is successfully established, false otherwise.
167 | */
168 | public function connect(): bool
169 | {
170 | switch ($this->mode) {
171 | case LibSQL::REMOTE:
172 | return $this->httpProvider->connect();
173 | break;
174 | case LibSQL::LOCAL:
175 | return $this->localProvider->connect();
176 | break;
177 | case LibSQL::REMOTE_REPLICA:
178 | return $this->remoteReplicaProvider->connect();
179 | break;
180 | default:
181 | throw new LibsqlError("Connection mode is not found", "ERR_MODE_NOT_FOUND");
182 | break;
183 | }
184 | }
185 |
186 | /**
187 | * Retrieves the version information of the database.
188 | *
189 | * @throws LibsqlError Thrown if the connection mode is not recognized.
190 | *
191 | * @return string The version information of the database.
192 | */
193 | public function version(): string
194 | {
195 | switch ($this->mode) {
196 | case LibSQL::REMOTE:
197 | return $this->httpProvider->version();
198 | break;
199 | case LibSQL::LOCAL:
200 | return $this->localProvider->version();
201 | break;
202 | case LibSQL::REMOTE_REPLICA:
203 | return $this->remoteReplicaProvider->version();
204 | break;
205 | default:
206 | throw new LibsqlError("Connection mode is not found", "ERR_MODE_NOT_FOUND");
207 | break;
208 | }
209 | }
210 |
211 | /**
212 | * Executes a query.
213 | *
214 | * ### NOTE: Use _Named Paramaters_ is recommended
215 | *
216 | *
217 | * **Parameters**
218 | *
219 | * **$query**
220 | * - _HttpStatement_ - **[Remote Only]** Parameter used for Remote connection only - [Ref:HttpStatement](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpStatement.php)
221 | * - _string_ - **[Local only]** Parameter used for Local connection only
222 | *
223 | * **$baton**
224 | * - _string_ - **[Remote Only]** The baton value for the query.
225 | *
226 | * **$params**
227 | * - _array_ - **[Local Only]** Parameters for the query.
228 | *
229 | * **Return**
230 | *
231 | * - _HttpResponse_ - **[Remote Only]** instance of HttpResponse for remote mode - [Ref:HttpResponse](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpResponse.php)
232 | * - _bool_ - **[Local Only]** Parameters for the query.
233 | *
234 | * **Remote Usage Example**
235 | *
236 | * ```
237 | * $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
238 | * $results = $db->execute(query: $query);
239 | * echo $results->fetch(type: LibSQLResult::FETCH_OBJ) . PHP_EOL;
240 | * ```
241 | *
242 | * **Local Usage Example**
243 | *
244 | * ```
245 | * $result = $db->execute(query: "INSERT INTO users (name) VALUES (?)", params: ['Belina Bogge']);
246 | * var_dump($result);
247 | * ```
248 | *
249 | * @param string|HttpStatement $query The query to execute, either a string or an instance of HttpStatement.
250 | * @param string $baton (Optional) The baton value for the query.
251 | * @param array $params (Optional) Parameters for the query.
252 | *
253 | * @throws LibsqlError Thrown if the connection mode is not recognized.
254 | *
255 | * @return LibSQLPHPClientResult|HttpResponse True if successful for local mode; otherwise, an instance of HttpResponse for remote mode. - [Ref:Executes a Query](https://github.com/darkterminal/libsql-php-ext/blob/main/docs/LibSQL.md#executes-a-query)
256 | */
257 | public function execute(string|HttpStatement $query, string $baton = '', ?array $params = []): LibSQLPHPClientResult|HttpResponse
258 | {
259 | switch ($this->mode) {
260 | case LibSQL::REMOTE:
261 | return $this->httpProvider->execute($query, $baton);
262 | break;
263 | case LibSQL::LOCAL:
264 | return $this->localProvider->execute($query, $params);
265 | break;
266 | case LibSQL::REMOTE_REPLICA:
267 | return $this->remoteReplicaProvider->execute($query, $params);
268 | break;
269 | default:
270 | throw new LibsqlError("Connection mode is not found", "ERR_MODE_NOT_FOUND");
271 | break;
272 | }
273 | }
274 |
275 | /**
276 | * Executes a batch of queries.
277 | *
278 | * ### NOTE: Remote Only
279 | *
280 | * Mode Options Available:
281 | * - deferred (default)
282 | * - write
283 | * - read
284 | *
285 | * Everyting is in lower-case or you can use **TransactionMode** Class Constants
286 | *
287 | * **Example - [Ref:Example](https://docs.turso.tech/sdk/http/reference#interactive-query)**
288 | *
289 | * ```
290 | * $stmts = [
291 | * HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Ramons", 32]),
292 | * HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Georgia", 43])
293 | * ];
294 | * $results = $db->batch(queries: $stmts);
295 | * print_r($results);
296 | * ```
297 | *
298 | * @param array $queries The array of queries to execute.
299 | * @param string $mode (Optional) The transaction behavior mode. Default is "deferred"
300 | *
301 | * @throws LibsqlError Thrown if the function is called for a local mode connection.
302 | *
303 | * @return HttpResponse The HTTP response containing the result of the batch execution. - [Ref:HttpResponse](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpResponse.php)
304 | */
305 | public function batch(array $queries, string $mode = "deferred"): HttpResponse
306 | {
307 | if (in_array($this->mode, [LibSQL::LOCAL, LibSQL::REMOTE_REPLICA])) {
308 | throw new LibsqlError("This function only for Remote (HTTP) provider", "INVALID_FUNCTION_CALL");
309 | }
310 |
311 | return $this->httpProvider->batch($queries, $mode);
312 | }
313 |
314 | /**
315 | * Executes a batch of queries.
316 | *
317 | * ### NOTE: Local Only
318 | *
319 | * **Example - [Ref:Execute Batch](https://github.com/tursodatabase/libsql/blob/main/libsql/src/local/connection.rs#L116-L137)**
320 | *
321 | * ```
322 | * $db->execute_batch("
323 | * BEGIN;
324 | * CREATE TABLE foo(x INTEGER);
325 | * CREATE TABLE bar(y TEXT);
326 | * COMMIT;
327 | * ");
328 | * ```
329 | *
330 | * @param string $query The batch query to execute.
331 | *
332 | * @throws LibsqlError Thrown if the function is called for a remote mode connection.
333 | *
334 | * @return void
335 | */
336 | public function execute_batch(string $query): void
337 | {
338 | if ($this->mode === LibSQL::REMOTE) {
339 | }
340 |
341 | switch ($this->mode) {
342 | case LibSQL::LOCAL:
343 | $this->localProvider->batch($query);
344 | break;
345 | case LibSQL::REMOTE_REPLICA:
346 | $this->remoteReplicaProvider->batch($query);
347 | break;
348 | default:
349 | throw new LibsqlError("This function only for Local (FILE) provider", "INVALID_FUNCTION_CALL");
350 | break;
351 | }
352 | }
353 |
354 | /**
355 | * Executes multiple SQL queries in a single HTTP request.
356 | *
357 | * ### NOTE: Remote Only
358 | *
359 | * **Example*
360 | *
361 | * ```
362 | * $query = "
363 | * UPDATE users SET name = 'Turso DB' WHERE id = 1;
364 | * UPDATE users SET name = 'ducktermin;
365 | * ";
366 | * $result = $db->executeMultiple($query);
367 | * print_r($result);
368 | * ```
369 | * Refs:
370 | * - [Ref:http.ts Implementation](https://github.com/tursodatabase/libsql-client-ts/blob/main/packages/libsql-client/src/http.ts#L124-L140)
371 | * - [Ref:HRANA_3_SPEC](https://github.com/tursodatabase/libsql/blob/main/docs/HRANA_3_SPEC.md#L844)
372 | *
373 | * @param string $query The SQL queries to execute.
374 | *
375 | * @throws LibsqlError Thrown if the function is called for a local mode connection.
376 | *
377 | * @return string The response from executing the queries.
378 | */
379 | public function executeMultiple(string $query): string
380 | {
381 | if (in_array($this->mode, [LibSQL::LOCAL, LibSQL::REMOTE_REPLICA])) {
382 | throw new LibsqlError("This function only for Remote (HTTP) provider", "INVALID_FUNCTION_CALL");
383 | }
384 |
385 | return $this->httpProvider->executeMultiple($query);
386 | }
387 |
388 | /**
389 | * Initiates a transaction for executing SQL queries either remotely or locally.
390 | *
391 | * ### NOTE: Remote and Local Used - **Recommended Read Ref:Link below**
392 | *
393 | * Mode Options Available:
394 | * - deferred (default: in Local)
395 | * - write (default: in Remote)
396 | * - read
397 | *
398 | * **Example - Remote Usage**
399 | *
400 | * ```
401 | * // Start a new transaction
402 | * $transaction = $db->transaction();
403 | *
404 | * // Add the first SQL statement to the transaction
405 | * if (true) {
406 | * $transaction->addTransaction(HttpStatement::create("UPDATE users SET name = 'Turso DB' WHERE id = 1"));
407 | * } else {
408 | * // If a condition is not met, rollback the transaction and exit
409 | * $transaction->rollback();
410 | * exit();
411 | * }
412 | *
413 | * // Add the second SQL statement to the transaction
414 | * if (true) {
415 | * $transaction->addTransaction(HttpStatement::create("UPDATE users SET name = 'darkterminal' WHERE id = 2"));
416 | * } else {
417 | * // If another condition is not met, rollback the transaction and exit
418 | * $transaction->rollback();
419 | * exit();
420 | * }
421 | *
422 | * // End the transaction (commit changes)
423 | * $result = $transaction->endTransaction();
424 | * print_r($result);
425 | * ```
426 | *
427 | * **Example - Local Usage**
428 | *
429 | * ```
430 | * $operations_successful = false;
431 | * $tx = $db->transaction(TransactionBehavior::Deferred);
432 | * $tx->exec("INSERT INTO users (name) VALUES (?)", ["Emanuel"]);
433 | * $tx->exec("INSERT INTO users (name) VALUES (?)", ["Darren"]);
434 | *
435 | * if ($operations_successful) {
436 | * $tx->commit();
437 | * echo "Commit the changes" . PHP_EOL;
438 | * } else {
439 | * $tx->rollback();
440 | * echo "Rollback the changes" . PHP_EOL;
441 | * }
442 | * ```
443 | *
444 | * **Return**
445 | * - _**HttpTransaction**_ - The return class when using **Remote Connection** [Ref:HttpTransaction](https://github.com/darkterminal/libsql-client-php/blob/main/src/Types/HttpTransaction.php)
446 | * - _**Transaction**_ - The return class when using **Local Connection** - [Ref:Transaction](https://github.com/darkterminal/libsql-php-ext/blob/main/php-src/Responses/Transaction.php)
447 | *
448 | * @param string $mode The transaction mode. Defaults to 'write'.
449 | *
450 | * @throws LibsqlError Thrown if the connection mode is not recognized.
451 | *
452 | * @return HttpTransaction|Transaction An instance of HttpTransaction for remote connections or Transaction for local connections.
453 | */
454 | public function transaction(string $mode = 'write'): HttpTransaction|Transaction
455 | {
456 | switch ($this->mode) {
457 | case LibSQL::REMOTE:
458 | return $this->httpProvider->transaction($mode);
459 | break;
460 | case LibSQL::LOCAL:
461 | return $this->localProvider->transaction($mode);
462 | break;
463 | case LibSQL::REMOTE_REPLICA:
464 | return $this->remoteReplicaProvider->transaction($mode);
465 | break;
466 | default:
467 | throw new LibsqlError("Connection mode is not found", "ERR_MODE_NOT_FOUND");
468 | break;
469 | }
470 | }
471 |
472 | /**
473 | * Synchronizes the database.
474 | *
475 | * ### NOTE: This Only Support for RemoteReplica and LocalReplica - [Ref:Builder Details](https://github.com/tursodatabase/libsql/blob/main/libsql/src/database/builder.rs#L8-L25)
476 | *
477 | * @throws LibsqlError Thrown if sync is called in Remote (HTTP) or Local (FILE) mode.
478 | *
479 | * @return int
480 | */
481 | public function sync(): int
482 | {
483 | if ($this->mode === LibSQL::LOCAL || $this->mode === LibSQL::REMOTE) {
484 | throw new LibsqlError("sync not supported in Remote (HTTP) or Local (FILE) mode", "SYNC_NOT_SUPPORTED");
485 | }
486 |
487 | return $this->remoteReplicaProvider->sync();
488 | }
489 |
490 | /**
491 | * Closes the database connection.
492 | *
493 | * @throws LibsqlError Thrown if the connection mode is not recognized.
494 | *
495 | * @return void
496 | */
497 | public function close(): void
498 | {
499 | switch ($this->mode) {
500 | case LibSQL::REMOTE:
501 | $this->httpProvider->close();
502 | break;
503 | case LibSQL::LOCAL:
504 | $this->localProvider->close();
505 | break;
506 | case LibSQL::REMOTE_REPLICA:
507 | $this->remoteReplicaProvider->close();
508 | break;
509 | default:
510 | throw new LibsqlError("Connection mode is not recognized", "ERR_MODE_NOT_FOUND");
511 | break;
512 | }
513 | }
514 | }
515 |
--------------------------------------------------------------------------------
/src/Providers/HttpClient.php:
--------------------------------------------------------------------------------
1 | url = $url;
94 | $this->authToken = $authToken;
95 | $this->timeout = $timeout;
96 |
97 | $this->initializeHttp();
98 | }
99 |
100 | /**
101 | * Initializes the HTTP client with the specified headers and options.
102 | */
103 | private function initializeHttp(): void
104 | {
105 | $this->headers = [
106 | 'Content-Type' => 'Application/json'
107 | ];
108 | if (!empty($this->authToken)) {
109 | $this->headers['Authorization'] = 'Bearer ' . $this->authToken;
110 | }
111 |
112 | // Initialize Guzzle HTTP client
113 | $this->http = new Client([
114 | 'base_uri' => $this->url,
115 | 'timeout' => $this->timeout,
116 | 'headers' => $this->headers
117 | ]);
118 | }
119 |
120 | /**
121 | * Connect to the HTTP server.
122 | *
123 | * @return bool|LibsqlError True if connection is successful, otherwise a LibsqlError instance.
124 | * @throws LibsqlError If connection fails.
125 | */
126 | public function connect(): bool|LibsqlError
127 | {
128 | try {
129 | // Send a health check request to the server
130 | $request = new Request('GET', LibSQL::HEALTH_ENDPOINT, $this->headers);
131 | $response = $this->http->send($request);
132 | return $response->getStatusCode() === 200;
133 | } catch (\Throwable $e) {
134 | // If connection fails, throw a LibsqlError
135 | throw new LibsqlError("Connection failed! " . $e->getMessage(), "CONNECTION_ERROR");
136 | }
137 | }
138 |
139 | /**
140 | * Execute an HTTP statement.
141 | * This method follow @link [Turso - Simple Query](https://docs.turso.tech/sdk/http/reference#simple-query)
142 | *
143 | * @param HttpStatement $query The HTTP statement to execute.
144 | * @param string $baton (Optional) The baton string.
145 | *
146 | * @return HttpResponse The HTTP response containing the results of the execution.
147 | *
148 | * @throws LibsqlError If there is an error in the execution of the statement.
149 | */
150 | public function execute(HttpStatement $query, string $baton = ''): HttpResponse
151 | {
152 | // Create request payload
153 | $payload = $this->_createRequest(LibSQL::LIBSQL_EXECUTE, $query->sql, $query->args, $query->named_args);
154 | $request = (!empty($baton)) ? $this->_makeRequest($payload, false, $baton) : $this->_makeRequest($payload);
155 |
156 | // Send POST request
157 | $response = $this->runQuery($request, true);
158 |
159 | // Process response and return HttpResponse object
160 | $data = map_results($response->getBody());
161 | return HttpResponse::create($data['baton'], $data['base_url'], $data['results']);
162 | }
163 |
164 | /**
165 | * Execute a batch of HTTP statements.
166 | * This method follow @link [Turso - Interactive Query](https://docs.turso.tech/sdk/http/reference#interactive-query)
167 | *
168 | * @param array $queries The array of HTTP statements to execute.
169 | * @param string $mode (Optional) The transaction mode read, write, or deferred. Default is 'deferred'.
170 | *
171 | * @return HttpResponse The HTTP response containing the results of the batch execution.
172 | *
173 | * @throws LibsqlError If there is an error in the batch execution.
174 | */
175 | public function batch(array $queries, string $mode = 'deferred'): HttpResponse
176 | {
177 | try {
178 | // Check if the transaction mode is valid
179 | TransactionMode::checker($mode);
180 |
181 | // Create the start transaction request
182 | $startTransaction = $this->_createRequest(LibSQL::LIBSQL_EXECUTE, Mods::transactionModeToBegin($mode));
183 |
184 | // Initialize the batch payload
185 | $batchPayload = [];
186 |
187 | // Iterate through each statement and add it to the batch payload
188 | foreach ($queries as $stmt) {
189 | /** @var HttpStatement $stmt */
190 | \array_push($batchPayload, $this->_createRequest(LibSQL::LIBSQL_EXECUTE, $stmt->sql, $stmt->args, $stmt->named_args));
191 | }
192 |
193 | // Add a commit request to the batch payload
194 | \array_push($batchPayload, $this->_createRequest(LibSQL::LIBSQL_EXECUTE, 'COMMIT'));
195 |
196 | // Execute the batch request asynchronously
197 | return $this->http->postAsync(LibSQL::PIPE_LINE_ENDPOINT, [
198 | 'json' => $this->_makeRequest($startTransaction, false)
199 | ])->then(
200 | function (ResponseInterface $res) use ($batchPayload) {
201 | // Handle the response from the start transaction request
202 | $beginResult = map_results($res->getBody());
203 | $trx = HttpResponse::create($beginResult['baton'], $beginResult['base_url'], $beginResult['results']);
204 |
205 | // Execute the batch payload asynchronously
206 | return $this->http->postAsync(LibSQL::PIPE_LINE_ENDPOINT, [
207 | 'json' => $this->_makeRequest($batchPayload, true, $trx->baton)
208 | ])->then(
209 | function (ResponseInterface $res) {
210 | // Handle the response from the batch execution
211 | $transactionResults = map_results($res->getBody());
212 | return HttpResponse::create($transactionResults['baton'], $transactionResults['base_url'], $transactionResults['results']);
213 | },
214 | function (RequestException $e) {
215 | // Handle request exceptions during batch execution
216 | throw new LibsqlError($e->getRequest()->getMethod() . " - " . $e->getMessage(), "INVALID_BATCH_TRANSACTION");
217 | }
218 | )->wait();
219 | },
220 | function (RequestException $e) {
221 | $this->_close();
222 | // Handle request exceptions during start transaction
223 | throw new LibsqlError($e->getRequest()->getMethod() . ' - ' . $e->getMessage(), "INVALID_START_TRANSACTION");
224 | }
225 | )->wait();
226 | } catch (\Throwable $e) {
227 | $this->_close();
228 | // If execution fails, throw a LibsqlError
229 | throw new LibsqlError($e->getMessage(), "BATCH_TRANSACTION_TERMINATED");
230 | }
231 | }
232 |
233 | /**
234 | * Execute multiple SQL statements in sequence.
235 | * This method follow @link [Hrana Over HTTP - Sequence](https://github.com/tursodatabase/libsql/blob/main/docs/HRANA_3_SPEC.md#execute-a-sequence-of-sql-statements-1)
236 | *
237 | * @param string $sql The SQL statements to execute.
238 | *
239 | * @return string
240 | *
241 | * @throws LibsqlError If execution fails.
242 | */
243 | public function executeMultiple(string $sql): string
244 | {
245 | try {
246 | $payload = $this->_createSequenceRequest(\str_replace(["\r", "\n", "\r\n"], '', $sql));
247 | $response = $this->http->post(LibSQL::PIPE_LINE_ENDPOINT, [
248 | 'json' => $this->_makeRequest($payload)
249 | ]);
250 | return $response->getBody();
251 | } catch (\Throwable $e) {
252 | $this->_close();
253 | // If execution fails, throw a LibsqlError
254 | throw new LibsqlError($e->getMessage(), "MULTIPLE_EXEC_ERROR");
255 | }
256 | }
257 |
258 | /**
259 | * Start a transaction with the specified mode.
260 | *
261 | * @param string $mode (Optional) The transaction mode read, write, and deferred. Default is 'write'.
262 | *
263 | * @return self The current instance of HttpClient.
264 | *
265 | * @throws LibsqlError If there is an error starting the transaction.
266 | */
267 | public function transaction(string $mode = 'write'): HttpTransaction
268 | {
269 | TransactionMode::checker($mode);
270 | return new HttpTransaction($mode);
271 | }
272 |
273 | /**
274 | * Close the HTTP client connection.
275 | */
276 | public function close(): void
277 | {
278 | $this->runQuery($this->_makeRequest($this->_close()));
279 | }
280 |
281 | public function version(): string
282 | {
283 | $response = $this->http->get(LibSQL::VERSION_ENDPOINT);
284 | return $response->getBody();
285 | }
286 |
287 | /**
288 | * Run an HTTP query with the provided payload.
289 | *
290 | * @param array $payload The payload for the HTTP query.
291 | * @param bool $trace (Optional) Whether to return the raw response without mapping results. Default is false.
292 | *
293 | * @return HttpResponse|ResponseInterface The HTTP response containing the results of the query, or the raw response if trace is true.
294 | */
295 | protected function runQuery(array $payload, bool $trace = false): HttpResponse|ResponseInterface
296 | {
297 | $response = $this->http->post(LibSQL::PIPE_LINE_ENDPOINT, [
298 | 'json' => $payload
299 | ]);
300 |
301 | if ($trace === false) {
302 | $data = map_results($response->getBody());
303 | return HttpResponse::create($data['baton'], $data['base_url'], $data['results']);
304 | }
305 |
306 | return $response;
307 | }
308 |
309 | /**
310 | * Create a payload for making a request.
311 | *
312 | * @param array $data The data to include in the payload.
313 | * @param bool $close (Optional) Whether to include a close request. Default is true.
314 | * @param string $baton (Optional) The baton string.
315 | *
316 | * @return array The payload for the request.
317 | */
318 | protected function _makeRequest(array $data, bool $close = true, string $baton = ''): array
319 | {
320 | // Initialize the payload with the "requests" key
321 | $payload = [
322 | 'requests' => \sizeof($data) >= 3 ? $data : [$data]
323 | ];
324 |
325 | // Add the close request if needed
326 | if ($close) {
327 | $payload['requests'][] = $this->_close();
328 | }
329 |
330 | // Add the baton if provided
331 | if (!empty($baton)) {
332 | $payload["baton"] = $baton;
333 | }
334 |
335 | return $payload;
336 | }
337 |
338 | /**
339 | * Create a request array for closing the connection.
340 | *
341 | * @return array The request array for closing the connection.
342 | */
343 | protected function _close(): array
344 | {
345 | return ["type" => LibSQL::LIBSQL_CLOSE];
346 | }
347 |
348 | /**
349 | * Create a request array for execution with the provided SQL statement and arguments.
350 | *
351 | * @param string $type The type statement to execute.
352 | * @param string $sql The SQL statement to execute.
353 | * @param array|null $args (Optional) The arguments for the SQL statement.
354 | * @param bool|null $named_args (Optional) Whether the arguments are named or positional.
355 | *
356 | * @return array The request array for execution.
357 | */
358 | protected function _createRequest(
359 | string $type = LibSQL::LIBSQL_EXECUTE,
360 | string $sql,
361 | ?array $args = [],
362 | ?bool $named_args = false
363 | ): array {
364 | // Initialize the execute request array
365 | $executeRequest = [
366 | "type" => $type,
367 | "stmt" => [
368 | "sql" => $sql
369 | ]
370 | ];
371 |
372 | // Determine if arguments are positional or named and set accordingly
373 | if ($named_args === false && !empty($args)) {
374 | $executeRequest["stmt"]["args"] = $this->_argumentsGenerator($args);
375 | }
376 |
377 | if ($named_args === true) {
378 | $executeRequest["stmt"]["named_args"] = $this->_namedArgumentsGenerator($args);
379 | }
380 |
381 | return $executeRequest;
382 | }
383 |
384 | protected function _createSequenceRequest(
385 | string $sql,
386 | int|null $sql_id = null
387 | ): array {
388 | // Initialize the execute request array
389 | $executeRequest = [
390 | "type" => LibSQL::LIBSQL_SEQUENCE,
391 | "sql" => $sql
392 | ];
393 |
394 | if (!empty($sql_id)) {
395 | $executeRequest['sql_id'] = $sql_id;
396 | }
397 |
398 | return $executeRequest;
399 | }
400 |
401 | /**
402 | * Generate arguments array for the HTTP request payload.
403 | *
404 | * @param mixed $args The arguments to be processed.
405 | *
406 | * @return array The generated arguments array.
407 | * @throws LibsqlError If an invalid argument type is encountered.
408 | */
409 | protected function _argumentsGenerator($args): array
410 | {
411 | $argsArray = [];
412 |
413 | // Iterate through each argument and generate the appropriate representation
414 | foreach ($args as $arg) {
415 | $type = $this->_typeParser($arg);
416 |
417 | // Handle special cases for certain argument types
418 | if ($type === 'blob') {
419 | $arg = \base64_encode($arg);
420 | } else if ($type === 'float') {
421 | // Convert argument to float if it's of type 'float'
422 | \settype($arg, 'float');
423 | } else if ($type === 'integer') {
424 | // Ensure integer values are represented as strings
425 | $arg = "$arg";
426 | }
427 |
428 | // Add argument to the array with its type and value
429 | $argsArray[] = [
430 | "type" => $type,
431 | "value" => $arg
432 | ];
433 | }
434 |
435 | return $argsArray;
436 | }
437 |
438 | /**
439 | * Generate named arguments array for the HTTP request payload.
440 | *
441 | * @param array $args The named arguments to be processed.
442 | *
443 | * @return array The generated named arguments array.
444 | * @throws LibsqlError If an invalid argument type is encountered.
445 | */
446 | protected function _namedArgumentsGenerator(array $args): array
447 | {
448 | $argsArray = [];
449 |
450 | // Iterate through each named argument and generate the appropriate representation
451 | foreach ($args as $name => $value) {
452 | $type = $this->_typeParser($value);
453 |
454 | // Handle special cases for certain argument types
455 | if ($type === 'blob') {
456 | $value = \base64_encode($value);
457 | } else if ($type === 'float') {
458 | // Convert argument to float if it's of type 'float'
459 | \settype($value, 'float');
460 | } else if ($type === 'integer') {
461 | // Ensure integer values are represented as strings
462 | $value = "$value";
463 | }
464 |
465 | // Add named argument to the array with its name, type, and value
466 | $argsArray[] = [
467 | "name" => $name,
468 | "value" => [
469 | "type" => $type,
470 | "value" => $value
471 | ]
472 | ];
473 | }
474 |
475 | return $argsArray;
476 | }
477 |
478 | /**
479 | * Parse the type of the value.
480 | *
481 | * @param mixed $value The value to determine the type for.
482 | *
483 | * @return string The type of the value.
484 | * @throws LibsqlError If the type of the value cannot be determined or is invalid.
485 | */
486 | protected function _typeParser(mixed $value): string
487 | {
488 | // Check the type of the value using the provided function
489 | $type = Mods::checkColumnType($value);
490 |
491 | // Throw an error if the type is unknown
492 | if ($type === 'unknown') {
493 | throw new LibsqlError(
494 | "Invalid arguments types. The type field within each arg corresponds to the column datatype and can be one of the following: null, integer, float, text, or blob.",
495 | "INVALID_TYPE_ARGUMENT"
496 | );
497 | }
498 |
499 | return $type;
500 | }
501 | }
502 |
--------------------------------------------------------------------------------
/src/Providers/LocalClient.php:
--------------------------------------------------------------------------------
1 | path = $path;
52 | $this->flags = $flags;
53 | $this->encryptionKey = $encryptionKey;
54 | $this->db = new LibSQLPHP($this->path, $this->flags, $this->encryptionKey);
55 | }
56 |
57 | /**
58 | * Establishes a connection to the local LibSQL database.
59 | *
60 | * @return bool True if the connection is successful, false otherwise.
61 | */
62 | public function connect(): bool
63 | {
64 | return $this->db->is_connected();
65 | }
66 |
67 | /**
68 | * Executes an SQL query on the local database.
69 | *
70 | * @param string $sql The SQL query to execute.
71 | * @param array $params Optional parameters to bind to the query.
72 | * @return LibSQLPHPClientResult The result of the query execution.
73 | */
74 | public function execute(string $sql, array $params = []): LibSQLPHPClientResult
75 | {
76 | return $this->db->client_exec($sql, $params);
77 | }
78 |
79 | /**
80 | * Executes a batch of SQL queries on the local database.
81 | *
82 | * @param string $sql The batch of SQL queries to execute.
83 | * @return void
84 | */
85 | public function batch(string $sql): void
86 | {
87 | $this->db->execute_batch($sql);
88 | }
89 |
90 | /**
91 | * Initiates a transaction on the local database.
92 | *
93 | * @param string $mode The transaction mode: 'write', 'read', or 'deferred'.
94 | * @return Transaction The transaction object representing the initiated transaction.
95 | */
96 | public function transaction(string $mode): Transaction
97 | {
98 | switch ($mode) {
99 | case 'write':
100 | $mode = TransactionBehavior::Immediate;
101 | break;
102 | case 'read':
103 | $mode = TransactionBehavior::ReadOnly;
104 | break;
105 | case 'deferred':
106 | $mode = TransactionBehavior::Deferred;
107 | break;
108 | }
109 |
110 | return $this->db->transaction($mode);
111 | }
112 |
113 | /**
114 | * Closes the connection to the local LibSQL database.
115 | *
116 | * @return void
117 | */
118 | public function close(): void
119 | {
120 | $this->db->close();
121 | }
122 |
123 | /**
124 | * Retrieves the version of the local LibSQL database.
125 | *
126 | * @return string The version of the local LibSQL database.
127 | * @throws LibsqlError If an error occurs while retrieving the version.
128 | */
129 | public function version(): string
130 | {
131 | try {
132 | return $this->db->version();
133 | } catch (\Exception $e) {
134 | throw new LibsqlError($e->getMessage(), "ERR_GET_VERSION");
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/Providers/RemoteReplicaClient.php:
--------------------------------------------------------------------------------
1 | path = $path;
37 | $this->authToken = $authToken;
38 | $this->syncUrl = $syncUrl;
39 | $this->syncInterval = $syncInterval;
40 | $this->read_your_writes = $read_your_writes;
41 | $this->db = new LibSQLPHP(
42 | path: $this->path,
43 | url: $this->syncUrl,
44 | token: $this->authToken,
45 | sync_interval: $this->syncInterval,
46 | read_your_writes: $this->read_your_writes
47 | );
48 | }
49 |
50 | /**
51 | * Checks if the client is connected to the remote replica database.
52 | *
53 | * @return bool True if connected, false otherwise.
54 | */
55 | public function connect(): bool
56 | {
57 | return $this->db->is_connected();
58 | }
59 |
60 | /**
61 | * Executes a SQL query on the remote replica database.
62 | *
63 | * @param string $sql The SQL query to execute.
64 | * @param array $params The parameters for the SQL query.
65 | * @return LibSQLPHPClientResult The result of the query execution.
66 | */
67 | public function execute(string $sql, array $params = []): LibSQLPHPClientResult
68 | {
69 | return $this->db->client_exec($sql, $params);
70 | }
71 |
72 | /**
73 | * Executes a batch of SQL queries on the remote replica database.
74 | *
75 | * @param string $sql The batch of SQL queries to execute.
76 | * @return void
77 | */
78 | public function batch(string $sql): void
79 | {
80 | $this->db->execute_batch($sql);
81 | }
82 |
83 | /**
84 | * Starts a transaction on the remote replica database.
85 | *
86 | * @param string $mode The mode of the transaction ('write', 'read', or 'deferred').
87 | * @return Transaction The transaction object.
88 | */
89 | public function transaction(string $mode): Transaction
90 | {
91 | switch ($mode) {
92 | case 'write':
93 | $mode = TransactionBehavior::Immediate;
94 | break;
95 | case 'read':
96 | $mode = TransactionBehavior::ReadOnly;
97 | break;
98 | case 'deferred':
99 | $mode = TransactionBehavior::Deferred;
100 | break;
101 | }
102 |
103 | return $this->db->transaction($mode);
104 | }
105 |
106 | /**
107 | * Closes the connection to the remote replica database.
108 | *
109 | * @return void
110 | */
111 | public function close(): void
112 | {
113 | $this->db->close();
114 | }
115 |
116 | /**
117 | * Syncs data with the remote replica database.
118 | *
119 | * @return int The result of the sync operation (0 for success, non-zero for failure).
120 | */
121 | public function sync(): int
122 | {
123 | $exec = $this->db->sync();
124 | return $exec === 0;
125 | }
126 |
127 | /**
128 | * Retrieves the version of the remote replica database.
129 | *
130 | * @return string The version of the remote replica database.
131 | *
132 | * @throws LibsqlError If an error occurs while retrieving the version.
133 | */
134 | public function version(): string
135 | {
136 | try {
137 | return $this->db->version();
138 | } catch (\Exception $e) {
139 | throw new LibsqlError($e->getMessage(), "ERR_GET_VERSION");
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/Traits/Logging.php:
--------------------------------------------------------------------------------
1 | checkAndCreateDirectoryAndFile();
22 | $logMessage = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL;
23 | file_put_contents($filePath, $logMessage, FILE_APPEND);
24 | }
25 |
26 | /**
27 | * Check and create the directory and error log file if they don't exist.
28 | *
29 | * @return string The path to the error log file.
30 | */
31 | protected function checkAndCreateDirectoryAndFile(): string
32 | {
33 | $homeDirectory = getenv('HOME');
34 | $directoryPath = $homeDirectory . '/.libsql-php';
35 | $filePath = $directoryPath . '/errors.log';
36 |
37 | if (!file_exists($directoryPath)) {
38 | mkdir($directoryPath, 0777, true);
39 | }
40 |
41 | if (!file_exists($filePath)) {
42 | touch($filePath);
43 | }
44 |
45 | return $filePath;
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/src/Traits/MapResults.php:
--------------------------------------------------------------------------------
1 | _results($data);
24 | }
25 |
26 | /**
27 | * Fetch the results as a JSON object.
28 | *
29 | * @param string|array|HttpResultSets $data The JSON data containing the results.
30 | *
31 | * @return string The results mapped as a JSON object.
32 | */
33 | protected function fetchObject(string|array|HttpResultSets $data): string
34 | {
35 | return \json_encode($this->_results($data), \JSON_PRETTY_PRINT);
36 | }
37 |
38 | /**
39 | * Parse the JSON data and extract the results.
40 | *
41 | * @param string|array|HttpResultSets $data The JSON data containing the results.
42 | *
43 | * @return array The extracted results.
44 | */
45 | private function _results(string|array|HttpResultSets $data): array
46 | {
47 | $result = [];
48 |
49 | if (\is_string($data)) {
50 | $data = json_decode($data, true);
51 | }
52 |
53 | if (\is_array($data)) {
54 |
55 | foreach ($data as $dataTable) {
56 | if (isset($dataTable['rows']) && isset($dataTable['cols'])) {
57 | foreach ($dataTable['rows'] as $row) {
58 | $rowData = [];
59 | $cols = $dataTable['cols'];
60 |
61 | for ($i = 0; $i < count($cols); $i++) {
62 | switch ($row[$i]['type']) {
63 | case 'text':
64 | $value = (string) $row[$i]['value'];
65 | break;
66 | case 'integer':
67 | $value = (int) $row[$i]['value'];
68 | break;
69 | case 'float':
70 | $value = (float) $row[$i]['value'];
71 | break;
72 | case 'null':
73 | $value = null;
74 | break;
75 | }
76 |
77 | $colName = $cols[$i]['name'];
78 | $colValue = $value;
79 | $rowData[$colName] = $colValue;
80 | }
81 |
82 | $result[] = $rowData;
83 | }
84 | }
85 | }
86 | }
87 |
88 | // Iterate over each row
89 | if (isset($data['results'][0]['response']['result']['rows'])) {
90 | foreach ($data['results'][0]['response']['result']['rows'] as $row) {
91 | $rowData = [];
92 | $cols = $data['results'][0]['response']['result']['cols'];
93 |
94 | // Iterate over each column
95 | for ($i = 0; $i < count($cols); $i++) {
96 | switch ($row[$i]['type']) {
97 | case 'text':
98 | $value = (string) $row[$i]['value'];
99 | break;
100 | case 'integer':
101 | $value = (int) $row[$i]['value'];
102 | break;
103 | case 'float':
104 | $value = (float) $row[$i]['value'];
105 | break;
106 | case 'null':
107 | $value = null;
108 | break;
109 | default:
110 | $value = (string) $row[$i]['value'];
111 | break;
112 | }
113 |
114 | $colName = $cols[$i]['name'];
115 | $colValue = $value;
116 | $rowData[$colName] = $colValue;
117 | }
118 |
119 | // Use 'name' column as key and 'value' column as value
120 | $result[] = $rowData;
121 | }
122 | }
123 |
124 | return $result;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Types/Authority.php:
--------------------------------------------------------------------------------
1 | host = $host;
18 | $this->port = $port;
19 | $this->userInfo = $userInfo;
20 | }
21 |
22 | public static function create(
23 | string $host,
24 | ?int $port,
25 | ?UserInfo $userInfo
26 | ): self
27 | {
28 | return new self($host, $port, $userInfo);
29 | }
30 |
31 | /**
32 | * Convert the Authority object to an array.
33 | *
34 | * @return array An array representation of the Authority object.
35 | */
36 | public function toArray(): array
37 | {
38 | return [
39 | 'host' => $this->host,
40 | 'port' => !empty($this->port) ? $this->port : null,
41 | 'userInfo' => !empty($this->userInfo) ? $this->userInfo->toArray() : null
42 | ];
43 | }
44 |
45 | /**
46 | * Converts the HttpResponse instance to a JSON string.
47 | *
48 | * @return string The JSON representation of the HttpResponse instance.
49 | */
50 | public function toObject(): string
51 | {
52 | return \json_encode($this->toArray());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Types/Config.php:
--------------------------------------------------------------------------------
1 | url = $url;
33 | $this->authToken = $authToken;
34 | $this->encryptionKey = $encryptionKey;
35 | $this->syncUrl = $syncUrl;
36 | $this->syncInterval = $syncInterval;
37 | $this->tls = $tls;
38 | }
39 |
40 | public static function create(
41 | string $url,
42 | ?string $authToken = null,
43 | ?string $encryptionKey = null,
44 | ?string $syncUrl = null,
45 | ?int $syncInterval = null,
46 | ?bool $tls = null
47 | ): self {
48 | return new self(
49 | $url,
50 | $authToken,
51 | $encryptionKey,
52 | $syncUrl,
53 | $syncInterval,
54 | $tls
55 | );
56 | }
57 |
58 | /**
59 | * Convert the Config to an array.
60 | * @return array The Config properties as an array.
61 | */
62 | public function toArray(): array
63 | {
64 | return [
65 | 'url' => $this->url,
66 | 'authToken' => $this->authToken,
67 | 'encryptionKey' => $this->encryptionKey,
68 | 'syncUrl' => $this->syncUrl,
69 | 'syncInterval' => $this->syncInterval,
70 | 'tls' => $this->tls,
71 | ];
72 | }
73 |
74 | /**
75 | * Converts the HttpResponse instance to a JSON string.
76 | *
77 | * @return string The JSON representation of the HttpResponse instance.
78 | */
79 | public function toObject(): string
80 | {
81 | return \json_encode($this->toArray());
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Types/ExpandedConfig.php:
--------------------------------------------------------------------------------
1 | scheme = $scheme;
27 | $this->flags = $flags;
28 | $this->encryptionKey = $encryptionKey;
29 | $this->tls = $tls;
30 | $this->authority = $authority;
31 | $this->path = $path;
32 | $this->authToken = $authToken;
33 | $this->syncUrl = $syncUrl;
34 | $this->syncInterval = $syncInterval;
35 | $this->read_your_writes = $read_your_writes;
36 | }
37 |
38 | public static function create(
39 | string $scheme,
40 | ?int $flags,
41 | ?string $encryptionKey = "",
42 | ?bool $tls = false,
43 | ?Authority $authority,
44 | ?string $path,
45 | ?string $authToken = null,
46 | ?string $syncUrl = null,
47 | ?int $syncInterval = null,
48 | ?bool $read_your_writes = true
49 | ): self {
50 | return new self(
51 | $scheme,
52 | $flags,
53 | $encryptionKey,
54 | $tls,
55 | $authority,
56 | $path,
57 | $authToken,
58 | $syncUrl,
59 | $syncInterval,
60 | $read_your_writes
61 | );
62 | }
63 |
64 | /**
65 | * Convert the ExpandedConfig object to an array.
66 | *
67 | * @return array An array representation of the ExpandedConfig object.
68 | */
69 | public function toArray(): array
70 | {
71 | return [
72 | 'scheme' => $this->scheme,
73 | 'flags' => $this->flags,
74 | 'encryptionKey' => $this->encryptionKey,
75 | 'tls' => $this->tls,
76 | 'authority' => $this->authority ? $this->authority->toArray() : null,
77 | 'path' => $this->path,
78 | 'authToken' => $this->authToken,
79 | 'syncUrl' => $this->syncUrl,
80 | 'syncInterval' => $this->syncInterval,
81 | 'read_your_writes' => $this->read_your_writes,
82 | ];
83 | }
84 |
85 | /**
86 | * Converts the ExpandedConfig instance to a JSON string.
87 | *
88 | * @return string The JSON representation of the ExpandedConfig instance.
89 | */
90 | public function toObject(): string
91 | {
92 | return \json_encode($this->toArray());
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/Types/ExpandedScheme.php:
--------------------------------------------------------------------------------
1 | authority = $authority;
17 | $this->path = $path;
18 | }
19 |
20 | public static function create(
21 | ?Authority $authority,
22 | string $path
23 | ): self
24 | {
25 | return new self($authority, $path);
26 | }
27 |
28 | /**
29 | * Convert the HierPart object to an array.
30 | *
31 | * @return array An array representation of the HierPart object.
32 | */
33 | public function toArray(): array
34 | {
35 | return [
36 | 'authority' => !empty($this->authority) ? $this->authority->toArray() : null,
37 | 'path' => $this->path
38 | ];
39 | }
40 |
41 | /**
42 | * Converts the HierPart instance to a JSON string.
43 | *
44 | * @return string The JSON representation of the HierPart instance.
45 | */
46 | public function toObject(): string
47 | {
48 | return \json_encode($this->toArray());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Types/HttpResponse.php:
--------------------------------------------------------------------------------
1 | baton = $baton;
28 | $this->base_url = $base_url;
29 | $this->results = $results;
30 | }
31 |
32 | /**
33 | * Creates a new HttpResponse instance.
34 | *
35 | * This method creates a new instance of the HttpResponse class.
36 | *
37 | * @param string|null $baton The baton identifier.
38 | * @param string|null $base_url The base URL for the HTTP response.
39 | * @param array|HttpResultSets $results The HTTP result sets.
40 | * @return self The created HttpResponse instance.
41 | */
42 | public static function create(
43 | string|null $baton,
44 | string|null $base_url,
45 | array|HttpResultSets $results
46 | ): self {
47 | return new self($baton, $base_url, $results);
48 | }
49 |
50 |
51 | /**
52 | * Convert the result set to an associative array.
53 | *
54 | * This method converts the result set to an associative array representation.
55 | * It includes the baton, base URL, and the results converted to an array using the `objectToArray()` function.
56 | *
57 | * @return array An associative array representation of the result set containing baton, base URL, and results.
58 | */
59 | public function toArray(): array
60 | {
61 | return [
62 | 'baton' => $this->baton,
63 | 'base_url' => $this->base_url,
64 | 'results' => \objectToArray($this->results)
65 | ];
66 | }
67 |
68 |
69 | /**
70 | * Convert the result set to a JSON-encoded string.
71 | *
72 | * This method converts the result set to a JSON-encoded string representation.
73 | * It internally uses the `toArray()` method to convert the result set to an associative array
74 | * before encoding it as JSON.
75 | *
76 | * @return string The JSON-encoded string representation of the result set.
77 | */
78 | public function toObject(): string
79 | {
80 | return \json_encode($this->toArray());
81 | }
82 |
83 |
84 | /**
85 | * Retrieve the first result set from the query execution.
86 | *
87 | * This method returns a new instance of the current class containing the first result set
88 | * obtained from the executed query. It converts the internal result object to an array and
89 | * extracts the first element to create a new instance.
90 | *
91 | * @return self A new instance of the current class containing the first result set.
92 | */
93 | public function first(): self
94 | {
95 | $data = \objectToArray($this->results);
96 | $result = \current($data);
97 | return new self(
98 | $this->baton,
99 | $this->base_url,
100 | HttpResultSets::create(
101 | $result['cols'],
102 | $result['rows'],
103 | $result['affected_row_count'],
104 | $result['last_insert_rowid'],
105 | $result['replication_index']
106 | )
107 | );
108 | }
109 |
110 | /**
111 | * Fetch the result set from the query execution.
112 | *
113 | * This method retrieves the result set from the executed query and returns it in the specified format.
114 | * It converts the internal result object to an array and switches based on the provided type parameter
115 | * to determine the format of the returned data.
116 | *
117 | * @param int $type The type of fetch operation. Default is LibSQLResult::FETCH_ASSOC.
118 | * @return array|string The result set in the specified format.
119 | * @throws LibsqlError When an undefined fetch option is provided.
120 | */
121 | public function fetch(int $type = LibSQLResult::FETCH_ASSOC): array|string
122 | {
123 | $results = objectToArray($this->results);
124 | switch ($type) {
125 | case LibSQLResult::FETCH_ASSOC:
126 | return $this->fetchArray($results);
127 | break;
128 | case LibSQLResult::FETCH_OBJ:
129 | return $this->fetchObject($results);
130 | break;
131 | default:
132 | throw new LibsqlError("Error Undefined fetch options", "UNDEFINED_FETCH_OPTIONS");
133 | break;
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/Types/HttpResultSets.php:
--------------------------------------------------------------------------------
1 | cols = $cols;
52 | $this->rows = $rows;
53 | $this->affected_row_count = $affected_row_count;
54 | $this->last_insert_rowid = $last_insert_rowid;
55 | $this->replication_index = $replication_index;
56 | }
57 |
58 | /**
59 | * Creates a new HttpResultSets instance.
60 | *
61 | * @param array $cols The columns of the result set.
62 | * @param array $rows The rows of the result set.
63 | * @param int $affected_row_count The number of affected rows.
64 | * @param int $last_insert_rowid The last inserted row ID.
65 | * @param int $replication_index The replication index.
66 | * @return self The created HttpResultSets instance.
67 | */
68 | public static function create(
69 | array $cols,
70 | array $rows,
71 | int $affected_row_count,
72 | int|null $last_insert_rowid,
73 | int|string $replication_index
74 | ): self {
75 | return new self($cols, $rows, $affected_row_count, $last_insert_rowid, $replication_index);
76 | }
77 |
78 | /**
79 | * Converts the HttpResultSets instance to an array.
80 | *
81 | * @return array The array representation of the HttpResultSets instance.
82 | */
83 | public function toArray(): array
84 | {
85 | return [
86 | 'cols' => $this->cols,
87 | 'rows' => $this->rows,
88 | 'affected_row_count' => $this->affected_row_count,
89 | 'last_insert_rowid' => $this->last_insert_rowid,
90 | 'replication_index' => $this->replication_index,
91 | ];
92 | }
93 |
94 | /**
95 | * Converts the HttpResultSets instance to a JSON string.
96 | *
97 | * @return string The JSON representation of the HttpResultSets instance.
98 | */
99 | public function toObject(): string
100 | {
101 | return \json_encode($this->toArray());
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Types/HttpStatement.php:
--------------------------------------------------------------------------------
1 | sql = $sql;
22 | $this->args = $args;
23 | $this->named_args = $named_args;
24 | }
25 |
26 | /**
27 | * Creates a new HttpStatement instance.
28 | *
29 | * **Example Usage**
30 | *
31 | * ```
32 | * $query = HttpStatement::create(sql: 'SELECT name, id FROM users LIMIT 5');
33 | *
34 | * // or
35 | *
36 | * $stmts = [
37 | * HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Ramons", 32]),
38 | * HttpStatement::create(sql: 'INSERT INTO users (name, age) VALUES (?, ?)', args: ["Georgia", 43])
39 | * ];
40 | * ```
41 | *
42 | * @param string $sql The SQL statement.
43 | * @param array|null $args The optional arguments for the SQL statement.
44 | * @return self The created HttpStatement instance.
45 | */
46 | public static function create(
47 | string $sql,
48 | ?array $args = [],
49 | ?bool $named_args = false
50 | ): self {
51 | return new self($sql, $args, $named_args);
52 | }
53 |
54 | /**
55 | * Converts the HttpStatement instance to an array.
56 | *
57 | * @return array The array representation of the HttpStatement instance.
58 | */
59 | public function toArray(): array
60 | {
61 | return [
62 | 'sql' => $this->sql,
63 | 'args' => $this->args,
64 | 'named_args' => $this->named_args
65 | ];
66 | }
67 |
68 | /**
69 | * Converts the HttpStatement instance to a JSON string.
70 | *
71 | * @return string The JSON representation of the HttpStatement instance.
72 | */
73 | public function toObject(): string
74 | {
75 | return \json_encode($this->toArray());
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Types/HttpTransaction.php:
--------------------------------------------------------------------------------
1 | _createRequest(LibSQL::LIBSQL_EXECUTE, Mods::transactionModeToBegin($mode));
16 | $response = $this->runQuery($this->_makeRequest($request, false), true);
17 | $data = map_results($response->getBody());
18 | $this->baton = $data['baton'];
19 | return $this;
20 | }
21 |
22 | /**
23 | * Add a transaction to the transaction batch.
24 | *
25 | * @param HttpStatement $query The HTTP statement to add to the transaction.
26 | *
27 | * @return self The current instance of HttpClient.
28 | */
29 | public function addTransaction(HttpStatement $query): self
30 | {
31 | \array_push($this->collectors, $this->_createRequest(LibSQL::LIBSQL_EXECUTE, $query->sql, $query->args, $query->named_args));
32 | return $this;
33 | }
34 |
35 | /**
36 | * End the current transaction batch and commit the transactions.
37 | *
38 | * @return HttpResponse The HTTP response containing the results of the transaction batch.
39 | */
40 | public function endTransaction(): HttpResponse
41 | {
42 | \array_push($this->collectors, $this->_rawCommit());
43 | $response = $this->runQuery($this->_makeRequest($this->collectors, true, $this->baton), true);
44 | $data = map_results($response->getBody());
45 | return HttpResponse::create($data['baton'], $data['base_url'], $data['results']);
46 | }
47 |
48 | /**
49 | * Rollback the current transaction.
50 | */
51 | public function rollback(): void
52 | {
53 | $this->runQuery($this->_makeRequest($this->_createRequest(LibSQL::LIBSQL_EXECUTE, 'ROLLBACK'), true, $this->baton));
54 | }
55 |
56 | protected function _rawRollback(): array
57 | {
58 | return $this->_createRequest(LibSQL::LIBSQL_EXECUTE, 'ROLLBACK');
59 | }
60 |
61 | /**
62 | * Commit the current transaction.
63 | */
64 | public function commit(): void
65 | {
66 | $this->runQuery($this->_makeRequest($this->_createRequest(LibSQL::LIBSQL_EXECUTE, 'COMMIT'), true, $this->baton));
67 | }
68 |
69 | protected function _rawCommit(): array
70 | {
71 | return $this->_createRequest(LibSQL::LIBSQL_EXECUTE, 'COMMIT');
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Types/KeyValue.php:
--------------------------------------------------------------------------------
1 | key = $key;
17 | $this->value = $value;
18 | }
19 |
20 | public static function create(
21 | string $key,
22 | string $value
23 | ): self
24 | {
25 | return new self($key, $value);
26 | }
27 |
28 | /**
29 | * Convert the KeyValue object to an array.
30 | *
31 | * @return array An array representation of the KeyValue object.
32 | */
33 | public function toArray(): array
34 | {
35 | return [
36 | 'key' => $this->key,
37 | 'value' => $this->value,
38 | ];
39 | }
40 |
41 | /**
42 | * Converts the KeyValue instance to a JSON string.
43 | *
44 | * @return string The JSON representation of the KeyValue instance.
45 | */
46 | public function toObject(): string
47 | {
48 | return \json_encode($this->toArray());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Types/LibSQLResult.php:
--------------------------------------------------------------------------------
1 | pairs = $pairs;
15 | }
16 |
17 | public static function create(array $pairs): self
18 | {
19 | return new self($pairs);
20 | }
21 |
22 | /**
23 | * Convert the Query object to an array.
24 | *
25 | * @return array An array representation of the Query object.
26 | */
27 | public function toArray(): array
28 | {
29 | return ['pairs' => $this->pairs];
30 | }
31 |
32 | /**
33 | * Converts the Query instance to a JSON string.
34 | *
35 | * @return string The JSON representation of the Query instance.
36 | */
37 | public function toObject(): string
38 | {
39 | return \json_encode($this->toArray());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Types/TransactionMode.php:
--------------------------------------------------------------------------------
1 | getConstants();
25 | if (!in_array($mode, $constants)) {
26 | throw new LibsqlError("Transaction mode is not supported. The only avaibale mode is: write, read, and deferred", "INVALID_TRANSACTION_MODE");
27 | }
28 |
29 | return $mode;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Types/Uri.php:
--------------------------------------------------------------------------------
1 | scheme = $scheme;
20 | $this->authority = $authority;
21 | $this->path = $path;
22 | $this->query = $query;
23 | $this->fragment = $fragment;
24 | }
25 |
26 | public static function create(
27 | string $scheme,
28 | ?Authority $authority = null,
29 | string $path = '',
30 | ?Query $query = null,
31 | ?string $fragment = ''
32 | ): self
33 | {
34 | return new self(
35 | $scheme,
36 | $authority,
37 | $path,
38 | $query,
39 | $fragment
40 | );
41 | }
42 |
43 | /**
44 | * Convert the Uri object to an array.
45 | *
46 | * @return array An array representation of the Uri object.
47 | */
48 | public function toArray(): array
49 | {
50 | return [
51 | 'scheme' => $this->scheme,
52 | 'authority' => !empty($this->authority) ? $this->authority->toArray() : null,
53 | 'path' => $this->path,
54 | 'query' => !empty($this->query) ? $this->query->toArray() : null,
55 | 'fragment' => $this->fragment
56 | ];
57 | }
58 |
59 | /**
60 | * Converts the Uri instance to a JSON string.
61 | *
62 | * @return string The JSON representation of the Uri instance.
63 | */
64 | public function toObject(): string
65 | {
66 | return \json_encode($this->toArray());
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Types/UserInfo.php:
--------------------------------------------------------------------------------
1 | username = $username;
17 | $this->password = $password;
18 | }
19 |
20 | public static function create(
21 | string|null $username,
22 | ?string $password = ''
23 | ): self
24 | {
25 | return new self($username, $password);
26 | }
27 |
28 | /**
29 | * Convert the UserInfo object to an array.
30 | *
31 | * @return array An array representation of the UserInfo object.
32 | */
33 | public function toArray(): array
34 | {
35 | return [
36 | 'username' => $this->username,
37 | 'password' => !empty($this->password) ? $this->password : null
38 | ];
39 | }
40 |
41 | /**
42 | * Converts the UserInfo instance to a JSON string.
43 | *
44 | * @return string The JSON representation of the UserInfo instance.
45 | */
46 | public function toObject(): string
47 | {
48 | return \json_encode($this->toArray());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Utils/Exceptions/LibsqlError.php:
--------------------------------------------------------------------------------
1 | log($message);
33 | parent::__construct($message, 0, $cause);
34 | $this->code = $code;
35 | $this->rawCode = $rawCode;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Utils/Mods.php:
--------------------------------------------------------------------------------
1 | query->pairs)) {
102 | foreach ($uri->query->pairs as $pair) {
103 | $key = $pair->key;
104 | $value = $pair->value;
105 | if ($key === 'authToken') {
106 | $authToken = $value !== '' ? $value : null;
107 | } elseif ($key === 'tls') {
108 | // Parse the 'tls' parameter
109 | if ($value === '0') {
110 | $tls = false;
111 | } elseif ($value === '1') {
112 | $tls = true;
113 | } else {
114 | throw new LibsqlError('Unknown value for the "tls" query argument: ' . json_encode($value) . '. Supported values are "0" and "1"', "URL_INVALID");
115 | }
116 | } else {
117 | throw new LibsqlError('Unknown URL query parameter ' . json_encode($key), "URL_PARAM_NOT_SUPPORTED");
118 | }
119 | }
120 | }
121 |
122 | // Determine the scheme
123 | $uriScheme = strtolower($uri->scheme);
124 | if ($uriScheme === 'libsql') {
125 | // Handle 'libsql' scheme
126 | if ($tls === false) {
127 | if ($uri->authority->port === null) {
128 | throw new LibsqlError('A "libsql:" URL with ?tls=0 must specify an explicit port', "URL_INVALID");
129 | }
130 | $scheme = $preferHttp ? ExpandedScheme::http : ExpandedScheme::ws;
131 | } else {
132 | $scheme = $preferHttp ? ExpandedScheme::https : ExpandedScheme::wss;
133 | }
134 | } elseif (in_array($uriScheme, [ExpandedScheme::http, ExpandedScheme::ws])) {
135 | // Handle HTTP and WebSocket schemes
136 | $scheme = $uriScheme;
137 | $tls ??= false;
138 | } elseif (in_array($uriScheme, [ExpandedScheme::https, ExpandedScheme::wss, ExpandedScheme::file])) {
139 | // Handle HTTPS, WSS, and file schemes
140 | $scheme = $uriScheme;
141 | } else {
142 | // Unsupported scheme
143 | throw new LibsqlError(
144 | 'The client supports only "libsql:", "wss:", "ws:", "https:", "http:" and "file:" URLs, got ' . json_encode($uri->scheme . ":") . '. For more information, please read ' . LibSQL::SUPPORTED_URL_LINK,
145 | "URL_SCHEME_NOT_SUPPORTED"
146 | );
147 | }
148 |
149 | // Check for URL fragments
150 | if (!empty($uri->fragment)) {
151 | throw new LibsqlError('URL fragments are not supported: ' . json_encode("#" . $uri->fragment), "URL_INVALID");
152 | }
153 |
154 | // Create and return the ExpandedConfig object
155 | return new ExpandedConfig(
156 | scheme: $scheme,
157 | flags: $flags,
158 | encryptionKey: $encryptionKey,
159 | tls: $tls ?? true,
160 | authority: $uri->authority,
161 | path: $uri->path,
162 | authToken: $authToken,
163 | syncUrl: $syncUrl,
164 | syncInterval: $syncInterval,
165 | read_your_writes: $read_your_writes
166 | );
167 | }
168 |
169 | /**
170 | * Parse a URI string and return a Uri object.
171 | *
172 | * @param string $text The URI string to parse.
173 | * @return Uri An object containing the parsed components of the URI.
174 | * @throws LibsqlError If the URI is not in a valid format.
175 | */
176 | public static function parseUri(string $text): Uri
177 | {
178 | $match = [];
179 | preg_match(LibSQL::URI_RE, $text, $match);
180 | if (empty($match)) {
181 | throw new LibsqlError("The URL is not in a valid format", "URL_INVALID");
182 | }
183 |
184 | $groups = [
185 | 'scheme' => $match['scheme'] ?? '',
186 | 'authority' => $match['authority'] ?? '',
187 | 'path' => $match['path'] ?? '',
188 | 'query' => $match['query'] ?? '',
189 | 'fragment' => $match['fragment'] ?? ''
190 | ];
191 |
192 | $scheme = $groups['scheme'];
193 | $authority = !empty($groups['authority']) ? self::parseAuthority($groups['authority']) : null;
194 | $path = self::percentDecode($groups['path']);
195 | $query = !empty($groups['query']) ? self::parseQuery($groups['query']) : null;
196 | $fragment = self::percentDecode($groups['fragment']);
197 |
198 | return Uri::create($scheme, $authority, $path, $query, $fragment);
199 | }
200 |
201 | /**
202 | * Parse authority part of URL and return an Authority object.
203 | *
204 | * @param string $text The authority part of the URL.
205 | * @return Authority An object containing host, port, and userInfo components.
206 | * @throws LibsqlError If the authority part of the URL is not in a valid format.
207 | */
208 | public static function parseAuthority(string $text): Authority
209 | {
210 | $match = [];
211 | preg_match(LibSQL::AUTHORITY_RE, $text, $match);
212 | if (empty($match)) {
213 | throw new LibsqlError("The authority part of the URL is not in a valid format", "URL_INVALID");
214 | }
215 |
216 | $groups = [
217 | 'username' => $match['username'] ?? '',
218 | 'password' => $match['password'] ?? '',
219 | 'host' => $match['host'] ?? '',
220 | 'host_br' => $match['host_br'] ?? '',
221 | 'port' => $match['port'] ?? ''
222 | ];
223 |
224 | $host = self::percentDecode($groups['host_br'] !== '' ? $groups['host_br'] : $groups['host']);
225 | $port = !empty($groups['port']) ? (int)$groups['port'] : null;
226 | $username = !empty($groups['username']) ? self::percentDecode($groups['username']) : null;
227 | $password = !empty($groups['password']) ? self::percentDecode($groups['password']) : null;
228 | $userInfo = UserInfo::create($username, $password);
229 |
230 | return Authority::create($host, $port, $userInfo);
231 | }
232 |
233 | /**
234 | * Function parseQuery
235 | *
236 | * Parses the query string of a URI and returns a Query object.
237 | *
238 | * @param string $text The query string to parse.
239 | * @return Query The parsed query.
240 | */
241 | public static function parseQuery(string $text): Query
242 | {
243 | $sequences = explode("&", $text);
244 | $pairs = [];
245 | foreach ($sequences as $sequence) {
246 | if ($sequence === "") {
247 | continue;
248 | }
249 |
250 | $splitIdx = strpos($sequence, "=");
251 | if ($splitIdx === false) {
252 | $key = $sequence;
253 | $value = "";
254 | } else {
255 | $key = substr($sequence, 0, $splitIdx);
256 | $value = substr($sequence, $splitIdx + 1);
257 | }
258 |
259 | $pairs[] = KeyValue::create(self::percentDecode(str_replace("+", " ", $key)), self::percentDecode(str_replace("+", " ", $value)));
260 | }
261 | return Query::create($pairs);
262 | }
263 |
264 | /**
265 | * Function percentDecode
266 | *
267 | * Decodes a percent-encoded string.
268 | *
269 | * @param string $text The string to decode.
270 | * @return string The decoded string.
271 | * @throws LibsqlError If the URL component has invalid percent encoding.
272 | */
273 | public static function percentDecode(string $text): string
274 | {
275 | try {
276 | return rawurldecode($text);
277 | } catch (\Exception $e) {
278 | throw new LibsqlError("URL component has invalid percent encoding: " . $e->getMessage(), "URL_INVALID", null, $e);
279 | }
280 | }
281 |
282 | /**
283 | * Function encodeBaseUrl
284 | *
285 | * Encodes the components of a URI and returns a URL object.
286 | *
287 | * @param string $scheme The scheme of the URI.
288 | * @param Authority|null $authority The authority of the URI.
289 | * @param string $path The path of the URI.
290 | * @return string The encoded URL object.
291 | * @throws LibsqlError If the URL requires authority.
292 | */
293 | public static function encodeBaseUrl(string $scheme, ?Authority $authority, string $path): array|string|int|false|null
294 | {
295 | if ($authority === null) {
296 | throw new LibsqlError("URL with scheme $scheme: requires authority (the \"//\" part)", "URL_INVALID");
297 | }
298 |
299 | $schemeText = $scheme . ":";
300 |
301 | $hostText = self::encodeHost($authority->host);
302 | $portText = self::encodePort($authority->port);
303 | $userInfoText = self::encodeUserInfo($authority->userInfo);
304 | $authorityText = "//" . $userInfoText . $hostText . $portText;
305 |
306 | $pathText = $path !== "" && substr($path, 0, 1) !== "/" ? "/" . $path : $path;
307 | $pathText = implode("/", array_map("rawurlencode", explode("/", $pathText)));
308 |
309 | return urldecode($schemeText . $authorityText . $pathText);
310 | }
311 |
312 | /**
313 | * Function encodeHost
314 | *
315 | * Encodes the host component of a URI.
316 | *
317 | * @param string $host The host to encode.
318 | * @return string The encoded host.
319 | */
320 | public static function encodeHost(string $host): string
321 | {
322 | return strpos($host, ":") !== false ? "[" . rawurlencode($host) . "]" : rawurlencode($host);
323 | }
324 |
325 | /**
326 | * Function encodePort
327 | *
328 | * Encodes the port component of a URI.
329 | *
330 | * @param int|null $port The port to encode.
331 | * @return string The encoded port.
332 | */
333 | public static function encodePort(?int $port): string
334 | {
335 | return $port !== null ? ":" . $port : "";
336 | }
337 |
338 | /**
339 | * Function encodeUserInfo
340 | *
341 | * Encodes the userInfo component of a URI.
342 | *
343 | * @param UserInfo|null $userInfo The userInfo to encode.
344 | * @return string The encoded userInfo.
345 | */
346 | public static function encodeUserInfo(?UserInfo $userInfo): string
347 | {
348 | if ($userInfo === null) {
349 | return "";
350 | }
351 |
352 | $usernameText = !empty($userInfo->username) ? rawurlencode($userInfo->username) : "";
353 | $passwordText = !empty($userInfo->password) ? ":" . rawurlencode($userInfo->password) : "";
354 | if (!empty($usernameText) && !empty($passwordText)) {
355 | return $usernameText . $passwordText . "@";
356 | }
357 | return "";
358 | }
359 |
360 | /**
361 | * Check if a string is base64 encoded.
362 | * @link https://stackoverflow.com/a/38627879/12439522
363 | *
364 | * @param string $data The string to check.
365 | *
366 | * @return bool True if the string is base64 encoded, false otherwise.
367 | */
368 | public static function is_base64($string)
369 | {
370 | $decoded_data = base64_decode($string, true);
371 | $encoded_data = base64_encode($decoded_data);
372 | if ($encoded_data != $string) return false;
373 | else if (!ctype_print($decoded_data)) return false;
374 |
375 | return true;
376 | }
377 |
378 | /**
379 | * Determines the type of a given column value.
380 | *
381 | * @param mixed $column The column value to check.
382 | * @return string The type of the column value ('unknown', 'float', 'blob', 'integer', 'text', or 'null').
383 | */
384 | public static function checkColumnType(mixed $column): string
385 | {
386 | $type = 'unknown';
387 |
388 | if (is_float($column)) {
389 | $type = 'float';
390 | } else if (self::is_base64($column)) {
391 | $type = 'blob';
392 | } else if (is_int($column)) {
393 | $type = 'integer';
394 | } else if (is_string($column)) {
395 | $type = 'text';
396 | } else if (is_null($column)) {
397 | $type = 'null';
398 | }
399 |
400 | return $type;
401 | }
402 | }
403 |
--------------------------------------------------------------------------------
/src/Utils/helpers.php:
--------------------------------------------------------------------------------
1 | []
21 | ];
22 |
23 | // Extract baton and base_url from the data
24 | $mapped_results['baton'] = $data['baton'];
25 | $mapped_results['base_url'] = $data['base_url'];
26 |
27 | // Iterate through each result in the data
28 | foreach ($data['results'] as $result) {
29 | // Check if the result is successful and has a response
30 | if ($result['type'] === 'ok' && isset($result['response']['result'])) {
31 | $response = $result['response']['result'];
32 |
33 | // Create a mapped result array
34 | $mapped_result = [
35 | 'cols' => array_map(function ($col) {
36 | return [
37 | 'name' => $col['name'],
38 | 'decltype' => $col['decltype']
39 | ];
40 | }, $response['cols']),
41 | 'column_types' => array_column($response['cols'], 'decltype'),
42 | 'rows' => $response['rows'],
43 | 'affected_row_count' => $response['affected_row_count'],
44 | 'last_insert_rowid' => $response['last_insert_rowid'],
45 | 'replication_index' => $response['replication_index']
46 | ];
47 |
48 | // Create HttpResultSets object
49 | $resultSet = HttpResultSets::create(
50 | $mapped_result['cols'],
51 | $mapped_result['rows'],
52 | $mapped_result['affected_row_count'],
53 | $mapped_result['last_insert_rowid'],
54 | $mapped_result['replication_index']
55 | );
56 |
57 | // Add the resultSet to mapped results
58 | array_push($mapped_results['results'], $resultSet);
59 | }
60 |
61 | if ($result['type'] === 'error') {
62 | throw new LibsqlError($result['error']['message'], $result['error']['code']);
63 | }
64 | }
65 |
66 | // Return mapped results
67 | return $mapped_results;
68 | }
69 |
70 | function objectToArray($object)
71 | {
72 | if (!is_object($object) && !is_array($object))
73 | return $object;
74 |
75 | return array_map('objectToArray', (array) $object);
76 | }
77 |
--------------------------------------------------------------------------------