Skip to content

Commit 8268bbe

Browse files
authored
overhaul docs (#351)
* note pgsql support * Create pgsql.md * Create mysql.md * Create record-and-replay.md * Create rules.md * Create configuration.md * Update pgsql.md * Update pgsql.md * Update mysql.md * Update mysql.md * Update pgsql.md * Update README.md * Create reflectors * Update README.md * Rename reflectors to reflectors.md * Update README.md * Update README.md * Update reflectors.md * Update README.md
1 parent 1f58c9a commit 8268bbe

File tree

7 files changed

+230
-133
lines changed

7 files changed

+230
-133
lines changed

README.md

Lines changed: 15 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
# PHPStan static analysis and type inference for the database access layer
1+
# `phpstandba`: PHPStan based SQL static analysis and type inference for the database access layer
22

33
`phpstan-dba` makes your phpstan static code analysis jobs aware of datatypes within your database.
4-
With this information at hand `phpstan-dba` is able to detect type inconsistencies between your domain model and database-schema.
4+
With this information at hand we are able to detect type inconsistencies between your domain model and database-schema.
55
Additionally errors in code handling the results of sql queries can be detected.
66

77
This extension provides the following features:
88

9-
* inspect sql queries, detect errors and placeholder/bound value mismatches
109
* result set type-inferrence
10+
* inspect sql queries, detect errors and placeholder/bound value mismatches
1111
* builtin support for `doctrine/dbal`, `mysqli`, and `PDO`
12-
* API to built the same features for your custom sql based database access layer
12+
* API to configure the same features for your custom sql based database access layer
1313

14-
In case you are using Doctrine ORM, you might use phpstan-dba in tandem with [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine).
14+
In case you are using Doctrine ORM, you might use `phpstan-dba` in tandem with [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine).
1515

1616
**Note:**
17-
At the moment only mysql/mariadb databases are supported. Technically it's not a big problem to support other databases though.
17+
At the moment only MySQL/MariaDB and PGSQL databases are supported. Technically it's not a big problem to support other databases though.
1818

1919
[see the unit-testsuite](https://github.com/staabm/phpstan-dba/tree/main/tests/default/data) to get a feeling about the current featureset.
2020

@@ -69,6 +69,8 @@ QueryReflection::setupReflector(
6969
);
7070
```
7171

72+
*Note*: [Configuration for PGSQL is pretty similar](https://github.com/staabm/phpstan-dba/blob/main/docs/pgsql.md)
73+
7274
**Third**, create or update your `phpstan.neon` file so [bootstrapFiles](https://phpstan.org/config-reference#bootstrap) includes `phpstan-dba-bootstrap.php`.
7375

7476
If you are **not** using [phpstan/extension-installer](https://github.com/phpstan/extension-installer), you will also need to include `dba.neon`.
@@ -93,131 +95,11 @@ includes:
9395
./vendor/bin/phpstan analyse -c phpstan.neon
9496
```
9597

96-
## Runtime configuration
97-
98-
Within your `phpstan-dba-bootstrap.php` file you can configure `phpstan-dba` so it knows about global runtime configuration state, which cannot be detect automatically.
99-
Use the [`RuntimeConfiguration`](https://github.com/staabm/phpstan-dba/tree/main/src/QueryReflection/RuntimeConfiguration.php) builder-object and pass it as a second argument to `QueryReflection::setupReflector()`.
100-
101-
If not configured otherwise, the following defaults are used:
102-
- type-inference works as precise as possible. In case your database access layer returns strings instead of integers and floats, use the [`stringifyTypes`](https://github.com/staabm/phpstan-dba/tree/main/src/QueryReflection/RuntimeConfiguration.php) option.
103-
- when analyzing a php8+ codebase, [`PDO::ERRMODE_EXCEPTION` error handling](https://www.php.net/manual/en/pdo.error-handling.php) is assumed.
104-
- when analyzing a php8.1+ codebase, [`mysqli_report(\MYSQLI_REPORT_ERROR | \MYSQLI_REPORT_STRICT);` error handling](https://www.php.net/mysqli_report) is assumed.
105-
- the fetch mode defaults to `QueryReflector::FETCH_TYPE_BOTH`, but can be configured using the [`defaultFetchMode`](https://github.com/staabm/phpstan-dba/tree/main/src/QueryReflection/RuntimeConfiguration.php) option.
106-
107-
### Record and Replay
108-
109-
In case you don't want to depend on a database at PHPStan analysis time, you can use one of the `*RecordingQueryReflector`-classes to record the reflection information.
110-
111-
With this cache file you can utilize [`ReplayQueryReflector`](https://github.com/staabm/phpstan-dba/blob/main/src/QueryReflection/ReplayQueryReflector.php) to replay the reflection information, without the need for a active database connection.
112-
113-
```php
114-
<?php // phpstan-dba-bootstrap.php
115-
116-
use staabm\PHPStanDba\QueryReflection\RuntimeConfiguration;
117-
use staabm\PHPStanDba\QueryReflection\MysqliQueryReflector;
118-
use staabm\PHPStanDba\QueryReflection\QueryReflection;
119-
use staabm\PHPStanDba\QueryReflection\RecordingQueryReflector;
120-
use staabm\PHPStanDba\QueryReflection\ReplayQueryReflector;
121-
use staabm\PHPStanDba\QueryReflection\ReflectionCache;
122-
123-
require_once __DIR__ . '/vendor/autoload.php';
124-
125-
$cacheFile = __DIR__.'/.phpstan-dba.cache';
126-
127-
$config = new RuntimeConfiguration();
128-
// $config->debugMode(true);
129-
// $config->stringifyTypes(true);
130-
131-
QueryReflection::setupReflector(
132-
new ReplayQueryReflector(
133-
ReflectionCache::create(
134-
$cacheFile
135-
)
136-
),
137-
$config
138-
);
139-
```
140-
141-
This might be usefull if your CI pipeline can't/shouldn't connect to your development database server for whatever reason.
142-
143-
**Note**: In case you commit the generated cache files into your repository, consider [marking them as generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github), so they don't show up in Pull Requests.
144-
145-
## Reflector Overview
146-
147-
### Backend Connecting Reflector
148-
149-
These reflectors connect to a real database, infer types based on result-set/schema metadata and are able to detect errors within a given sql query.
150-
It is **not** mandatory to use the same database driver for phpstan-dba, as you use within your application code.
151-
152-
| Reflector | Key Features |
153-
|----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
154-
| MysqliQueryReflector | - limited to mysql/mariadb databases<br/>- requires a active database connection<br/>- most feature complete reflector |
155-
| PdoQueryReflector | - connects to a mysql/mariadb database<br/>- requires a active database connection<br/>- can be used as a foundation for other database types in the future |
156-
157-
### Utility Reflectors
158-
159-
Utility reflectors will be used in combination with backend connecting reflectors to provide additional features.
160-
161-
| Reflector | Key Features |
162-
|----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
163-
| ReplayAndRecordingQueryReflector | - wraps a backend connecting reflector, caches the reflected information into a local file and utilizes the cached information<br/>- will re-validate the cached information<br/>- will update local cache file information, even on external changes<br/>- will reduce database interactions to a minimum, but still requires a active database connection |
164-
| ReplayQueryReflector | - utilizes the cached information of a `*RecordingQueryReflector`<br/>- will **not** validate the cached information, therefore might return stale results<br/> - does **not** require a active database connection |
165-
| ChainedReflector | - chain several backend connecting reflectors, so applications which use multiple database connections can be analyzed |
166-
167-
Legacy utility reflectors
168-
169-
| Reflector | Key Features |
170-
|----------------------------------|------------------------------------------------------------------------------------------------------|
171-
| RecordingQueryReflector | - wraps a backend connecting reflector and caches the reflected information into a local file<br/>-requires a active database connection |
172-
173-
## Advanced Usage
174-
175-
### use `SyntaxErrorInPreparedStatementMethodRule` for your custom classes
176-
177-
Reuse the `SyntaxErrorInPreparedStatementMethodRule` within your PHPStan configuration to detect syntax errors in prepared queries, by registering a service:
178-
179-
```
180-
services:
181-
-
182-
class: staabm\PHPStanDba\Rules\SyntaxErrorInPreparedStatementMethodRule
183-
tags: [phpstan.rules.rule]
184-
arguments:
185-
classMethods:
186-
- 'My\Connection::preparedQuery'
187-
- 'My\PreparedStatement::__construct'
188-
```
189-
190-
__the callable format is `class::method`. phpstan-dba assumes the method takes a query-string as a 1st and the parameter-values as a 2nd argument.__
191-
192-
### use `SyntaxErrorInQueryMethodRule` for your custom classes
193-
194-
Reuse the `SyntaxErrorInQueryMethodRule` within your PHPStan configuration to detect syntax errors in queries, by registering a service:
195-
196-
```
197-
services:
198-
-
199-
class: staabm\PHPStanDba\Rules\SyntaxErrorInQueryMethodRule
200-
tags: [phpstan.rules.rule]
201-
arguments:
202-
classMethods:
203-
- 'myClass::query#0'
204-
- 'anotherClass::takesAQuery#2'
205-
```
206-
207-
__the callable format is `class::method#parameterIndex`, while the parameter-index defines the position of the query-string argument.__
208-
209-
### use `SyntaxErrorInQueryFunctionRule` for your custom functions
210-
211-
Reuse the `SyntaxErrorInQueryFunctionRule` within your PHPStan configuration to detect syntax errors in queries, by registering a service:
212-
213-
```
214-
services:
215-
-
216-
class: staabm\PHPStanDba\Rules\SyntaxErrorInQueryFunctionRule
217-
tags: [phpstan.rules.rule]
218-
arguments:
219-
functionNames:
220-
- 'Deployer\runMysqlQuery#0'
221-
```
98+
## Read more
22299

223-
__the callable format is `funtionName#parameterIndex`, while the parameter-index defines the position of the query-string argument.__
100+
- [Runtime configuration](https://github.com/staabm/phpstan-dba/blob/main/docs/configuration.md)
101+
- [Record and Replay](https://github.com/staabm/phpstan-dba/blob/main/docs/record-and-replay.md)
102+
- [Custom Query APIs Support](https://github.com/staabm/phpstan-dba/blob/main/docs/rules.md)
103+
- [MySQL Support](https://github.com/staabm/phpstan-dba/blob/main/docs/mysql.md)
104+
- [PGSQL Support](https://github.com/staabm/phpstan-dba/blob/main/docs/pgsql.md)
105+
- [Reflector Overview](https://github.com/staabm/phpstan-dba/blob/main/docs/reflectors.md)

docs/configuration.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Runtime configuration
2+
3+
Within your `phpstan-dba-bootstrap.php` file you can configure `phpstan-dba` so it knows about global runtime configuration state, which cannot be detect automatically.
4+
Use the [`RuntimeConfiguration`](https://github.com/staabm/phpstan-dba/tree/main/src/QueryReflection/RuntimeConfiguration.php) builder-object and pass it as a second argument to `QueryReflection::setupReflector()`.
5+
6+
If not configured otherwise, the following defaults are used:
7+
- type-inference works as precise as possible. In case your database access layer returns strings instead of integers and floats, use the [`stringifyTypes`](https://github.com/staabm/phpstan-dba/tree/main/src/QueryReflection/RuntimeConfiguration.php) option.
8+
- when analyzing a php8+ codebase, [`PDO::ERRMODE_EXCEPTION` error handling](https://www.php.net/manual/en/pdo.error-handling.php) is assumed.
9+
- when analyzing a php8.1+ codebase, [`mysqli_report(\MYSQLI_REPORT_ERROR | \MYSQLI_REPORT_STRICT);` error handling](https://www.php.net/mysqli_report) is assumed.
10+
- the fetch mode defaults to `QueryReflector::FETCH_TYPE_BOTH`, but can be configured using the [`defaultFetchMode`](https://github.com/staabm/phpstan-dba/tree/main/src/QueryReflection/RuntimeConfiguration.php) option.

docs/mysql.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# MySQL
2+
3+
Analyzing MySQL based codebases is supported for Doctrine DBAL, PDO and mysqli.
4+
5+
At analysis time you can pick either `MysqliQueryReflector` or `PdoQueryReflector`.
6+
7+
## Configuration
8+
9+
```
10+
<?php // phpstan-dba-bootstrap.php
11+
12+
use staabm\PHPStanDba\DbSchema\SchemaHasherMysql;
13+
use staabm\PHPStanDba\QueryReflection\RuntimeConfiguration;
14+
use staabm\PHPStanDba\QueryReflection\MysqliQueryReflector;
15+
use staabm\PHPStanDba\QueryReflection\QueryReflection;
16+
use staabm\PHPStanDba\QueryReflection\ReplayAndRecordingQueryReflector;
17+
use staabm\PHPStanDba\QueryReflection\ReplayQueryReflector;
18+
use staabm\PHPStanDba\QueryReflection\ReflectionCache;
19+
20+
require_once __DIR__ . '/vendor/autoload.php';
21+
22+
$cacheFile = __DIR__.'/.phpstan-dba.cache';
23+
24+
$config = new RuntimeConfiguration();
25+
// $config->debugMode(true);
26+
// $config->stringifyTypes(true);
27+
28+
// TODO: Put your database credentials here
29+
$mysqli = new mysqli('hostname', 'username', 'password', 'database');
30+
31+
QueryReflection::setupReflector(
32+
new ReplayAndRecordingQueryReflector(
33+
ReflectionCache::create(
34+
$cacheFile
35+
),
36+
// XXX alternatively you can use PdoQueryReflector instead
37+
new MysqliQueryReflector($mysqli),
38+
new SchemaHasherMysql($mysqli)
39+
40+
),
41+
$config
42+
);
43+
```
44+
45+
## Advanced Usage
46+
47+
For custom/non-standard MySQL query APIs the [PHPStan rules shipped with `phpstandba` can be configured](https://github.com/staabm/phpstan-dba/blob/main/docs/rules.md).

docs/pgsql.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# PGSQL
2+
3+
PGSQL/PostgresSQL is supported since `phpstandba 0.2.26`.
4+
5+
While the `phpstandba` engine requires `pdo-pgsql` at analysis time, the codebase beeing analyzed can either use Doctrine DBAL or PDO.
6+
7+
**Note:** ["Record and Replay" is not yet supported on the PGSQL driver](https://github.com/staabm/phpstan-dba/issues/353)
8+
9+
## Configuration
10+
11+
```php
12+
<?php // phpstan-dba-bootstrap.php
13+
14+
use staabm\PHPStanDba\QueryReflection\RuntimeConfiguration;
15+
use staabm\PHPStanDba\QueryReflection\PdoPgSqlQueryReflector;
16+
use staabm\PHPStanDba\QueryReflection\QueryReflection;
17+
use staabm\PHPStanDba\QueryReflection\RecordingQueryReflector;
18+
use staabm\PHPStanDba\QueryReflection\ReflectionCache;
19+
20+
require_once __DIR__ . '/vendor/autoload.php';
21+
22+
$cacheFile = __DIR__.'/.phpstan-dba.cache';
23+
24+
$config = new RuntimeConfiguration();
25+
// $config->debugMode(true);
26+
// $config->stringifyTypes(true);
27+
28+
// TODO: Put your database credentials here
29+
$pdo = new PDO(..)
30+
31+
QueryReflection::setupReflector(
32+
new RecordingQueryReflector(
33+
ReflectionCache::create(
34+
$cacheFile
35+
),
36+
new PdoPgSqlQueryReflector($pdo)
37+
),
38+
$config
39+
);
40+
```
41+
42+
## Advanced Usage
43+
44+
For custom/non-standard PGSQL query APIs the [PHPStan rules shipped with `phpstandba` can be configured](https://github.com/staabm/phpstan-dba/blob/main/docs/rules.md).

docs/record-and-replay.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Record and Replay
2+
3+
In case you don't want to depend on a database at PHPStan analysis time, you can use one of the `*RecordingQueryReflector`-classes to record the reflection information.
4+
5+
With this cache file you can utilize [`ReplayQueryReflector`](https://github.com/staabm/phpstan-dba/blob/main/src/QueryReflection/ReplayQueryReflector.php) to replay the reflection information, without the need for a active database connection.
6+
7+
```php
8+
<?php // phpstan-dba-bootstrap.php
9+
10+
use staabm\PHPStanDba\QueryReflection\RuntimeConfiguration;
11+
use staabm\PHPStanDba\QueryReflection\MysqliQueryReflector;
12+
use staabm\PHPStanDba\QueryReflection\QueryReflection;
13+
use staabm\PHPStanDba\QueryReflection\RecordingQueryReflector;
14+
use staabm\PHPStanDba\QueryReflection\ReplayQueryReflector;
15+
use staabm\PHPStanDba\QueryReflection\ReflectionCache;
16+
17+
require_once __DIR__ . '/vendor/autoload.php';
18+
19+
$cacheFile = __DIR__.'/.phpstan-dba.cache';
20+
21+
$config = new RuntimeConfiguration();
22+
// $config->debugMode(true);
23+
// $config->stringifyTypes(true);
24+
25+
QueryReflection::setupReflector(
26+
new ReplayQueryReflector(
27+
ReflectionCache::create(
28+
$cacheFile
29+
)
30+
),
31+
$config
32+
);
33+
```
34+
35+
This might be usefull if your CI pipeline can't/shouldn't connect to your development database server for whatever reason.
36+
37+
**Note**: In case you commit the generated cache files into your repository, consider [marking them as generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github), so they don't show up in Pull Requests.

0 commit comments

Comments
 (0)