サンプル
doctrine/dbal 4.4.4: Query an in-memory SQLite through Doctrine DBAL 4 without the parameter binding, empty result and schema introspection traps
検証済みサンプル — composer doctrine/dbal 4.4.4: Query an in-memory SQLite through Doctrine DBAL 4 without the parameter binding, empty result and schema…
sha256:090b8a4df8ed4282fa66e190d2a7e4a2c1611b82a538304c73a2585e29fa9c7a
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
MIT-0
実行証拠
宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。
- 証拠の基準
- 署名済みコントラクト合格
- 検証レシート
- 1
- ビルドした署名鍵
- 1
宣言された環境
php 8 linux x64 php 8 php composer
検証実行環境
| 環境 | コントラクト | ステージ | 実行日 |
|---|---|---|---|
| php 8 · linux alpine/x64 · docker ed25519:a2ec939a4c60e243 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · composer@1 |
2026-08-14 |
ケース
HOW- ゴール
- Query an in-memory SQLite through Doctrine DBAL 4 without the parameter binding, empty result and schema introspection traps
- パッケージ
- シンボル
-
- Doctrine.DBAL.DriverManager
- Connection::executeQuery
- Result::fetchAssociative
- Doctrine.DBAL.ParameterType
- Doctrine.DBAL.ArrayParameterType
- QueryBuilder::createNamedParameter
- QueryBuilder::setParameter
- AbstractSchemaManager::introspectTable
- Type::lookupName
- 環境
- php 8
- 作成日
- 2026-08-14T20:22:50Z
コントラクト
- assert positional parameters are bound in the order the array was built and never by its keys, so two arrays that are == with the same keys give different answers and ksort alone changes the result
- assert named parameters are resolved by name so the order they were set in cannot matter, and that a 1-based or nonsense-keyed positional array still works because no key is ever read
- assert named and positional placeholders can be mixed in one statement despite the manual saying they cannot, and that whether the SQL parser runs at all is decided by is_string on the first key of the params array
- assert that same switch decides whether a bad parameter list raises MissingNamedParameter or MissingPositionalParameter or instead reaches the driver as SQLSTATE column index out of range, and that a surplus named value is silently unused
- assert fetchAssociative returns false rather than null when the result is exhausted so the ?? guard never fires, and that fetchOne returns false for no row but int 0 for a stored zero, which are == but not ===
- assert fetchAllAssociative spells the same emptiness as an empty array instead, and that rowCount reports 0 for a SELECT on pdo_sqlite so counting has to happen in SQL
- assert a wrong ParameterType rewrites the value instead of failing: '0012' bound as INTEGER is stored as '12', 'abc' becomes 0, 2.9 truncates to 2, and false bound as STRING becomes the empty string rather than '0'
- assert that mistake still matches on an INTEGER column because SQLite applies column affinity to the comparison, and matches nothing against a text column, which is why it survives the read path and only corrupts writes
- assert an IN clause needs createNamedParameter with an ArrayParameterType, that the single placeholder is expanded into one ? per element inside executeQuery rather than by the builder, and that an empty list becomes the literal NULL
- assert expr()->in with a raw array interpolates the values into the SQL and dies on 'no such column' for strings, that setParameter with an array and the default type only raises a PHP 'Array to string conversion' warning and matches nothing, and that a scalar ParameterType casts the array to 1 with no diagnostic at all
- assert setParameter binds a value without adding a placeholder, so a parameter whose placeholder is missing from the SQL is discarded without complaint
- assert schema introspection returns datetime for datetime_immutable, text for json and simple_array, and a fixed string(36) for guid, while length, precision, scale and autoincrement do survive the round trip
- assert the Comparator still calls the two schemas identical and emits no ALTER because it compares the generated DDL rather than the Doctrine type, so the loss surfaces only in convertToPHPValue handing back a mutable DateTime and an undecoded JSON string
- assert introspecting a declared type with no mapping raises InvalidArgumentException instead of falling back to string, and that Type::getName is gone in DBAL 4 in favour of the static Type::lookupName
ファイル
- composer.json
- composer.lock
- csx.json
- phpunit.xml
- src/Ledger.php
- test/LedgerTest.php