Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/composer-validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Validate composer.json

on:
push:
paths:
- 'composer.json'
- 'composer.lock'
pull_request:
paths:
- 'composer.json'
- 'composer.lock'

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
tools: composer:v2

- name: Validate composer.json
run: composer validate --strict
62 changes: 62 additions & 0 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: PHPUnit

on:
push:
branches: [ "master", "main" ]
pull_request:
branches: [ "master", "main" ]

permissions:
contents: read

jobs:
test:
name: PHP ${{ matrix.php-version }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php-version: ["8.0", "8.1", "8.2", "8.3", "8.4"]
include:
- php-version: "8.3"
coverage: "true"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: pdo, pdo_sqlite
coverage: ${{ matrix.coverage == 'true' && 'xdebug' || 'none' }}
tools: composer:v2

- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: ~/.cache/composer
key: composer-${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('**/composer.json', '**/composer.lock') }}
restore-keys: |
composer-${{ runner.os }}-${{ matrix.php-version }}-

- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-interaction

- name: Run tests
if: matrix.coverage != 'true'
run: vendor/bin/phpunit --no-coverage

- name: Run tests with coverage
if: matrix.coverage == 'true'
run: vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml

- name: Upload coverage artifact
if: matrix.coverage == 'true'
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: build/coverage.xml
retention-days: 7
18 changes: 10 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/.idea/
/.vs/
/.vscode/
/vendor/
/composer.lock
/.phpunit.result.cache
/nbproject/private/
/*.log
/.idea/
/.vs/
/.vscode/
/vendor/
/build/
/composer.lock
/.phpunit.result.cache
/.phpunit.cache/
/nbproject/private/
/*.log
79 changes: 79 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Changelog

All notable changes to `initorm/dbal` will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased] — 2.0.0

This release focuses on correctness, standards compliance, testability, and
documentation. Several long-standing bugs in DSN building and query
preparation have been fixed; these fixes are technically breaking for any
caller that depended on the previous (incorrect) behaviour.

### Added
- PSR-4 `src/` layout. Autoload entries updated accordingly.
- Optional [PSR-3](https://www.php-fig.org/psr/psr-3/) `LoggerInterface`
support: any object implementing `Psr\Log\LoggerInterface` can be passed as
the `log` credential. PSR-3 `{placeholder}` format is honoured in
`createLog()`.
- `src/Connection/Support/DsnBuilder.php` — driver-aware DSN composer.
- `src/Connection/Support/QueryLogger.php` — encapsulates `addQueryLog` /
`getQueryLogs`.
- `src/Connection/Support/Logger.php` — encapsulates the `createLog` strategy
(PSR-3, callable, file path, duck-typed `critical`).
- `ConnectionAlreadyEstablishedException` (replaces the misnamed
`ValidConnectionAvailableException`, which is kept as a deprecated alias).
- Split interfaces (`ConfigurableConnectionInterface`,
`LoggableConnectionInterface`) to honour ISP; `ConnectionInterface` extends
both so existing consumers keep working.
- Full PHPUnit test suite (SQLite in-memory) with per-bug regression tests.
- GitHub Actions workflows: `phpunit.yml` (PHP 8.0–8.4 matrix) and
`composer-validate.yml`.
- `docs/` — full developer documentation with runnable examples.

### Changed
- **BREAKING** PHP requirement raised from `>=7.4` to `>=8.0`.
- **BREAKING** Top-level `Connection/` and `DataMapper/` directories moved to
`src/Connection/` and `src/DataMapper/`. Consumers using Composer autoload
are unaffected; only direct path references (rare) break.
- **BREAKING** `PDO::ATTR_PERSISTENT` default is now `false`. Persistent
connections leak transactions and prepared-statement caches across
requests; opt in explicitly via `['options' => [PDO::ATTR_PERSISTENT =>
true]]` if you need them.
- **BREAKING** `DataMapper::bind()` returns `PDO::PARAM_BOOL` for boolean
values (previously `PARAM_INT`). PostgreSQL boolean columns require this.
- **BREAKING** `DataMapper::rows()` returns `[]` (empty array) when no rows
match, instead of `null`. The return type is now `array` (non-nullable).
- `Connection::query()` now uses `$queryOptions + ($options ?? [])` instead of
`array_merge`, preserving the integer keys PDO requires for prepare
options.
- `Connection::connect()` only emits `SET NAMES / SET CHARACTER SET` for the
`mysql` driver, and rejects charset/collation values that contain non
`[A-Za-z0-9_]` characters (defence-in-depth against SQL injection through
configuration).
- The error message produced when a query fails no longer interpolates raw
parameter values into the SQL string via `strtr`. The parameter array is
serialised separately, avoiding `TypeError` when values contain `null`,
`bool`, or `int`.
- `createLog()` now formats messages with PSR-3 style `{key}` placeholders.

### Fixed
- `Connection::getDsn()` no longer ignores its own auto-build branch
(`!isset` against an always-present key) and no longer writes the charset
into the `dbname=` part of the DSN.
- `Connection::connect()` reads the actual PDO driver name into the
credentials even when the user did not explicitly provide a driver.
- `Connection::query()` removes the dead `errorCode()` branch that could
never run under `ERRMODE_EXCEPTION`.
- `DataMapper::__get` / `__isset` PHPDoc no longer claims to throw an
exception that the implementation cannot raise.

### Removed
- Unused `setDebug` / `getDebug` plumbing was wired into
`Connection::query()`: when enabled, error messages now include the SQL
and a JSON-encoded parameter dump. (Previously these methods set a flag
that nothing read.)
- `@version 1.0` tags from file-level docblocks — versioning is owned by
git tags.
Loading
Loading