Skip to content

Commit 3beaa75

Browse files
committed
editors
1 parent 0f08853 commit 3beaa75

File tree

9 files changed

+731
-0
lines changed

9 files changed

+731
-0
lines changed

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ $posts = $driver->queryAll('SELECT * FROM posts WHERE author_id = ?', [12345]);
8888
- **Schema introspection** via `describeTable()` for table column metadata
8989
- **Query profiling** via `onQuery()` callback for logging and performance monitoring
9090
- **Connection tagging** via `setApplicationName()` and `setClientInfo()` for debugging
91+
- **IDE support** for VS Code and PHPStorm (syntax highlighting, live templates)
9192

9293
---
9394

@@ -1119,6 +1120,42 @@ See [fuzz/README.md](fuzz/README.md) for more details.
11191120

11201121
---
11211122

1123+
## IDE Support
1124+
1125+
Syntax highlighting for conditional blocks (`{{ }}`), type-safe placeholders (`?i`, `?s`), and named parameters.
1126+
1127+
### VS Code
1128+
1129+
Install the extension from `editors/vscode`:
1130+
1131+
```bash
1132+
cd editors/vscode
1133+
npx vsce package
1134+
# Then install the .vsix file in VS Code
1135+
```
1136+
1137+
Or manually copy/symlink to `~/.vscode/extensions/php-sqlx`.
1138+
1139+
Features:
1140+
- Highlights `{{ }}` conditional blocks
1141+
- Highlights typed placeholders (`?i`, `?ni`, `?ia`, `$name!s`)
1142+
- Auto-injects into PHP strings starting with SQL keywords
1143+
1144+
See [editors/vscode/README.md](editors/vscode/README.md) for details.
1145+
1146+
### PHPStorm / IntelliJ
1147+
1148+
Import the language injection configuration:
1149+
1150+
1. **Settings** > **Editor** > **Language Injections**
1151+
2. Click **Import** and select `editors/phpstorm/IntelliLang.xml`
1152+
1153+
Also includes live templates for common patterns (`sqlxq`, `sqlxcond`, `sqlxtx`).
1154+
1155+
See [editors/phpstorm/README.md](editors/phpstorm/README.md) for details.
1156+
1157+
---
1158+
11221159
## License
11231160

11241161
MIT

editors/phpstorm/IntelliLang.xml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
PHP-SQLx Language Injection Configuration for PHPStorm/IntelliJ
4+
5+
Import via: Settings > Editor > Language Injections > Import
6+
-->
7+
<LanguageInjectionConfiguration>
8+
<!-- Inject SQL into queryAll, queryRow, queryMaybeRow, queryValue, execute methods -->
9+
<injection language="SQL" injector-id="php">
10+
<display-name>PHP-SQLx Driver Query Methods</display-name>
11+
<single-file value="false"/>
12+
<place><![CDATA[
13+
phpLiteralExpression().withParent(
14+
psiElement().withParent(
15+
psiElement().methodCallMatcher(
16+
phpMethodMatcher()
17+
.withName(string().oneOf(
18+
"queryAll", "queryRow", "queryMaybeRow", "queryValue",
19+
"execute", "prepare", "describeTable"
20+
))
21+
)
22+
)
23+
).and(
24+
phpLiteralExpression().argumentIndex(0)
25+
)
26+
]]></place>
27+
</injection>
28+
29+
<!-- Inject SQL into WriteQueryBuilder methods -->
30+
<injection language="SQL" injector-id="php">
31+
<display-name>PHP-SQLx WriteQueryBuilder</display-name>
32+
<single-file value="false"/>
33+
<place><![CDATA[
34+
phpLiteralExpression().withParent(
35+
psiElement().withParent(
36+
psiElement().methodCallMatcher(
37+
phpMethodMatcher()
38+
.withName(string().oneOf(
39+
"insert", "insertAll", "upsert", "upsertAll",
40+
"update", "updateAll", "delete", "deleteAll"
41+
))
42+
)
43+
)
44+
)
45+
]]></place>
46+
</injection>
47+
48+
<!-- Detect SQL by SELECT/INSERT/UPDATE/DELETE keywords -->
49+
<injection language="SQL" injector-id="php">
50+
<display-name>PHP-SQLx SQL Detection by Keywords</display-name>
51+
<single-file value="false"/>
52+
<place><![CDATA[
53+
phpLiteralExpression().matches("(?is)^\\s*(SELECT|INSERT|UPDATE|DELETE|WITH|CREATE|ALTER|DROP|TRUNCATE)\\b.*")
54+
]]></place>
55+
</injection>
56+
</LanguageInjectionConfiguration>

editors/phpstorm/README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# PHP-SQLx PHPStorm/IntelliJ Support
2+
3+
SQL syntax highlighting and language injection for PHP-SQLx in PHPStorm and other JetBrains IDEs.
4+
5+
## Language Injection
6+
7+
PHPStorm can automatically highlight SQL syntax inside PHP strings. Import the provided configuration:
8+
9+
1. Open **Settings** > **Editor** > **Language Injections**
10+
2. Click the **Import** button (arrow icon)
11+
3. Select `IntelliLang.xml` from this directory
12+
4. Click **OK**
13+
14+
This enables SQL highlighting in:
15+
16+
- `$driver->queryAll('SELECT ...')`
17+
- `$driver->execute('INSERT ...')`
18+
- Any string starting with `SELECT`, `INSERT`, `UPDATE`, `DELETE`, etc.
19+
20+
## Manual Injection (Alternative)
21+
22+
If the import doesn't work, add injections manually:
23+
24+
1. Open **Settings** > **Editor** > **Language Injections**
25+
2. Click **+** > **PHP Parameter**
26+
3. Configure:
27+
- **Language**: SQL
28+
- **Parameter index**: 0
29+
- **Method name regex**: `queryAll|queryRow|queryMaybeRow|queryValue|execute|prepare`
30+
31+
## Highlighting Conditional Blocks
32+
33+
PHPStorm's built-in SQL doesn't recognize `{{ }}` blocks. Options:
34+
35+
### Option 1: Custom Inspection Suppression
36+
37+
Add this comment before SQLx queries to suppress "unknown token" warnings:
38+
39+
```php
40+
/** @lang SQL */
41+
$sql = 'SELECT * FROM users WHERE 1=1 {{ AND status = $status }}';
42+
```
43+
44+
### Option 2: Use Heredoc with SQL Tag
45+
46+
```php
47+
$sql = <<<SQL
48+
SELECT * FROM users
49+
WHERE 1=1
50+
{{ AND status = $status }}
51+
{{ AND created_at > $since }}
52+
SQL;
53+
```
54+
55+
## Live Templates
56+
57+
Import `live-templates.xml` for useful snippets:
58+
59+
1. Open **Settings** > **Editor** > **Live Templates**
60+
2. Click **Import** (gear icon)
61+
3. Select `live-templates.xml`
62+
63+
Available templates:
64+
65+
- `sqlxq` - SQLx query with parameters
66+
- `sqlxcond` - Conditional block `{{ }}`
67+
- `sqlxin` - IN clause with typed array
68+
- `sqlxins` - INSERT statement
69+
- `sqlxupd` - UPDATE statement
70+
71+
## Type-Safe Placeholder Reference
72+
73+
PHPStorm won't validate these, but here's a quick reference:
74+
75+
| Positional | Named | Description |
76+
|------------|--------------|------------------|
77+
| `?i` | `$id!i` | Integer |
78+
| `?u` | `$age!u` | Unsigned integer |
79+
| `?d` | `$price!d` | Decimal |
80+
| `?ud` | `$amount!ud` | Unsigned decimal |
81+
| `?s` | `$name!s` | String |
82+
| `?ni` | `$id!ni` | Nullable integer |
83+
| `?ia` | `$ids!ia` | Integer array |
84+
| `?sa` | `$names!sa` | String array |
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
PHP-SQLx Live Templates for PHPStorm/IntelliJ
4+
5+
Import via: Settings > Editor > Live Templates > Import
6+
-->
7+
<templateSet group="PHP-SQLx">
8+
<template name="sqlxq" value="&#36;driver->queryAll('$SQL$', [$PARAMS$]);" description="SQLx query with parameters" toReformat="true" toShortenFQNames="true">
9+
<variable name="SQL" expression="" defaultValue="&quot;SELECT * FROM table WHERE id = ?i&quot;" alwaysStopAt="true"/>
10+
<variable name="PARAMS" expression="" defaultValue="&quot;&quot;" alwaysStopAt="true"/>
11+
<context>
12+
<option name="PHP" value="true"/>
13+
</context>
14+
</template>
15+
16+
<template name="sqlxrow" value="&#36;driver->queryRow('$SQL$', [$PARAMS$]);" description="SQLx query single row" toReformat="true" toShortenFQNames="true">
17+
<variable name="SQL" expression="" defaultValue="&quot;SELECT * FROM table WHERE id = ?i&quot;" alwaysStopAt="true"/>
18+
<variable name="PARAMS" expression="" defaultValue="&quot;&quot;" alwaysStopAt="true"/>
19+
<context>
20+
<option name="PHP" value="true"/>
21+
</context>
22+
</template>
23+
24+
<template name="sqlxval" value="&#36;driver->queryValue('$SQL$', [$PARAMS$]);" description="SQLx query single value" toReformat="true" toShortenFQNames="true">
25+
<variable name="SQL" expression="" defaultValue="&quot;SELECT COUNT(*) FROM table&quot;" alwaysStopAt="true"/>
26+
<variable name="PARAMS" expression="" defaultValue="" alwaysStopAt="true"/>
27+
<context>
28+
<option name="PHP" value="true"/>
29+
</context>
30+
</template>
31+
32+
<template name="sqlxexec" value="&#36;driver->execute('$SQL$', [$PARAMS$]);" description="SQLx execute statement" toReformat="true" toShortenFQNames="true">
33+
<variable name="SQL" expression="" defaultValue="&quot;UPDATE table SET col = ?s WHERE id = ?i&quot;" alwaysStopAt="true"/>
34+
<variable name="PARAMS" expression="" defaultValue="&quot;&quot;" alwaysStopAt="true"/>
35+
<context>
36+
<option name="PHP" value="true"/>
37+
</context>
38+
</template>
39+
40+
<template name="sqlxcond" value="{{ $CONDITION$ }}" description="SQLx conditional block" toReformat="false" toShortenFQNames="true">
41+
<variable name="CONDITION" expression="" defaultValue="&quot;AND column = &#36;param&quot;" alwaysStopAt="true"/>
42+
<context>
43+
<option name="PHP String" value="true"/>
44+
</context>
45+
</template>
46+
47+
<template name="sqlxin" value="&#36;$VAR$ IN :$PARAM$!$TYPE$a" description="SQLx IN clause with typed array" toReformat="false" toShortenFQNames="true">
48+
<variable name="VAR" expression="" defaultValue="&quot;id&quot;" alwaysStopAt="true"/>
49+
<variable name="PARAM" expression="" defaultValue="&quot;ids&quot;" alwaysStopAt="true"/>
50+
<variable name="TYPE" expression="" defaultValue="&quot;i&quot;" alwaysStopAt="true"/>
51+
<context>
52+
<option name="PHP String" value="true"/>
53+
</context>
54+
</template>
55+
56+
<template name="sqlxins" value="INSERT INTO $TABLE$ ($COLUMNS$) VALUES ($VALUES$)" description="SQLx INSERT statement" toReformat="false" toShortenFQNames="true">
57+
<variable name="TABLE" expression="" defaultValue="&quot;table_name&quot;" alwaysStopAt="true"/>
58+
<variable name="COLUMNS" expression="" defaultValue="&quot;col1, col2&quot;" alwaysStopAt="true"/>
59+
<variable name="VALUES" expression="" defaultValue="&quot;?s, ?i&quot;" alwaysStopAt="true"/>
60+
<context>
61+
<option name="PHP String" value="true"/>
62+
</context>
63+
</template>
64+
65+
<template name="sqlxupd" value="UPDATE $TABLE$ SET $SETS$ WHERE $WHERE$" description="SQLx UPDATE statement" toReformat="false" toShortenFQNames="true">
66+
<variable name="TABLE" expression="" defaultValue="&quot;table_name&quot;" alwaysStopAt="true"/>
67+
<variable name="SETS" expression="" defaultValue="&quot;col1 = ?s, col2 = ?i&quot;" alwaysStopAt="true"/>
68+
<variable name="WHERE" expression="" defaultValue="&quot;id = ?i&quot;" alwaysStopAt="true"/>
69+
<context>
70+
<option name="PHP String" value="true"/>
71+
</context>
72+
</template>
73+
74+
<template name="sqlxtx" value="&#36;driver->begin(function(&#36;driver) {&#10; $CODE$&#10;});" description="SQLx transaction with callback" toReformat="true" toShortenFQNames="true">
75+
<variable name="CODE" expression="" defaultValue="&quot;// transaction code&quot;" alwaysStopAt="true"/>
76+
<context>
77+
<option name="PHP" value="true"/>
78+
</context>
79+
</template>
80+
81+
<template name="sqlxhook" value="&#36;driver->onQuery(function(string &#36;sql, string &#36;sqlInline, float &#36;durationMs) {&#10; $CODE$&#10;});" description="SQLx query profiling hook" toReformat="true" toShortenFQNames="true">
82+
<variable name="CODE" expression="" defaultValue="&quot;Logger::debug(\&quot;Query took {\$durationMs}ms: {\$sqlInline}\&quot;);&quot;" alwaysStopAt="true"/>
83+
<context>
84+
<option name="PHP" value="true"/>
85+
</context>
86+
</template>
87+
</templateSet>

editors/vscode/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# PHP-SQLx VS Code Extension
2+
3+
Syntax highlighting for PHP-SQLx augmented SQL syntax.
4+
5+
## Features
6+
7+
- **Conditional blocks**: `{{ AND status = $status }}`
8+
- **Type-safe placeholders**: `?i`, `?s`, `?ni`, `?ia`, `?nuda`, etc.
9+
- **Named placeholders**: `$name`, `:name`, `$id!i`, `:status!ns`
10+
- **SQL injection into PHP strings**: Automatically highlights SQL in PHP string literals
11+
12+
## Installation
13+
14+
### From VSIX (local)
15+
16+
1. Package the extension:
17+
```bash
18+
cd editors/vscode
19+
npx vsce package
20+
```
21+
22+
2. Install in VS Code:
23+
- Press `Cmd+Shift+P` (Mac) or `Ctrl+Shift+P` (Windows/Linux)
24+
- Type "Install from VSIX"
25+
- Select the generated `.vsix` file
26+
27+
### Manual (development)
28+
29+
1. Copy or symlink this folder to your VS Code extensions directory:
30+
- **Mac**: `~/.vscode/extensions/php-sqlx`
31+
- **Windows**: `%USERPROFILE%\.vscode\extensions\php-sqlx`
32+
- **Linux**: `~/.vscode/extensions/php-sqlx`
33+
34+
2. Reload VS Code
35+
36+
## Highlighted Syntax
37+
38+
### Conditional Blocks
39+
40+
```sql
41+
SELECT *
42+
FROM users
43+
WHERE 1 = 1 {{ AND status = $status }}
44+
{{
45+
AND created_at
46+
> $since }}
47+
```
48+
49+
The `{{ }}` delimiters are highlighted as control keywords.
50+
51+
### Type-Safe Placeholders
52+
53+
| Syntax | Description |
54+
|-------------------------------|------------------|
55+
| `?i`, `?s`, `?d`, `?u`, `?ud` | Typed positional |
56+
| `?ni`, `?ns`, `?nd` | Nullable typed |
57+
| `?ia`, `?sa`, `?da` | Typed arrays |
58+
| `$name!i`, `:id!s` | Named with type |
59+
| `$name!ni`, `:id!ns` | Named nullable |
60+
61+
### Named Placeholders
62+
63+
```sql
64+
SELECT *
65+
FROM users
66+
WHERE id = $id
67+
AND name = :name
68+
```
69+
70+
## Color Customization
71+
72+
Add to your `settings.json` to customize colors:
73+
74+
```json
75+
{
76+
"editor.tokenColorCustomizations": {
77+
"textMateRules": [
78+
{
79+
"scope": "keyword.control.conditional.sqlx",
80+
"settings": {
81+
"foreground": "#C586C0",
82+
"fontStyle": "bold"
83+
}
84+
},
85+
{
86+
"scope": "variable.parameter.placeholder.typed.sqlx",
87+
"settings": {
88+
"foreground": "#4EC9B0",
89+
"fontStyle": "bold"
90+
}
91+
},
92+
{
93+
"scope": "variable.parameter.placeholder.sqlx",
94+
"settings": {
95+
"foreground": "#9CDCFE"
96+
}
97+
}
98+
]
99+
}
100+
}
101+
```

0 commit comments

Comments
 (0)