Skip to content
Open
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
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/.github export-ignore
/tests export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpunit.xml.dist export-ignore
148 changes: 148 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
name: Tests

on:
push:
branches:
- master
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
tests:
name: PHP ${{ matrix.php }} / ${{ matrix.dependencies }} dependencies
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
php: ['8.4', '8.5']
dependencies: ['highest']
include:
- php: '8.4'
dependencies: 'lowest'

steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pdo, pdo_sqlite, sqlite3, mbstring, tokenizer
coverage: none
ini-values: error_reporting=-1, display_errors=On, zend.assertions=1

- name: Install dependencies
uses: ramsey/composer-install@v3
with:
dependency-versions: ${{ matrix.dependencies }}

- name: Run tests
run: vendor/bin/phpunit

tests-mysql:
name: PHP ${{ matrix.php }} / MySQL ${{ matrix.mysql }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
- php: '8.4'
mysql: '8.0'
- php: '8.5'
mysql: '8.4'

services:
mysql:
image: mysql:${{ matrix.mysql }}
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: doctrine_components_test
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -uroot -proot"
--health-interval=10s
--health-timeout=5s
--health-retries=10

env:
DB_DRIVER: pdo_mysql
DB_HOST: 127.0.0.1
DB_PORT: 3306
DB_USER: root
DB_PASSWORD: root
DB_NAME: doctrine_components_test

steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pdo, pdo_mysql, pdo_sqlite, sqlite3, mbstring, tokenizer
coverage: none
ini-values: error_reporting=-1, display_errors=On, zend.assertions=1

- name: Install dependencies
uses: ramsey/composer-install@v3
with:
dependency-versions: highest

- name: Run tests
run: vendor/bin/phpunit

coverage:
name: Coverage
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: pdo, pdo_sqlite, sqlite3, mbstring, tokenizer
coverage: xdebug
ini-values: error_reporting=-1, display_errors=On

- name: Install dependencies
uses: ramsey/composer-install@v3
with:
dependency-versions: highest

- name: Run tests with coverage
run: vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml

- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage.xml
if-no-files-found: error

composer-validate:
name: Composer validate
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none

- name: Validate composer.json
run: composer validate --strict --no-check-publish
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
/vendor
/composer.lock

.idea
.idea

/.phpunit.cache
/phpunit.xml
/coverage.xml
/coverage
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ Method `by` is a shortcut for creating `filter` callbacks. It offers some useful

- When there are more columns, `orWhere` is used among them.

- Pass `$filterKey` as the fourth argument to register the filter under a name, so that it can be
turned off later with `disableFilter()`. Calling `by()` again with the same key replaces the filter
instead of adding a second condition.

- If a `$value` is type of 'string', `LIKE %$value%` is used. You can change it by parameter `filterType` with value `FilterTypeEnum::STRICT`.

- If you would like get all value in certain range, you can use parameter `filterType` with value `FilterTypeEnum::RANGE`.
Expand Down Expand Up @@ -247,6 +251,10 @@ public function byShowOnWeb(): static

Unlike `QueryBuilder::innerJoin` and `QueryBuilder::leftJoin`, this ensures that same joins are not used multiple times and don't throw an error.

Joins are deduplicated **by alias only**, the first join registered for an alias wins. A subclass can
use that to re-point an alias: register the join before calling `parent::init()` and every inherited
join and condition using that alias will refer to your relation instead.

### More columns

Don't use `addSelect` inside a `filter` callback. Use `initSelect` method instead:
Expand Down Expand Up @@ -357,6 +365,39 @@ foreach ($profiles as $_profile) {

You should always use new `EntityManager` instance, not the default one (because of `EntityManager::clear`).

## Tests

```
composer install
composer tests
```

By default the tests run against an in-memory SQLite database, so no external service is needed. The
test entities and query objects used by the suite live in `tests/Fixtures`.

To run the same suite against MySQL, set the connection via environment variables:

```
DB_DRIVER=pdo_mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_USER=root DB_PASSWORD=root \
DB_NAME=doctrine_components_test vendor/bin/phpunit
```

The MySQL database is created once per process and emptied before every entity manager is handed out,
so each test still starts from an empty database with auto increment reset. A handful of tests are
driver specific (named `...OnMysql` / `...OnSqlite`) and skip themselves on the other driver.

Because the suite drops the schema and truncates tables, two runs must never share one MySQL database
at the same time - give each parallel run its own `DB_NAME`. In CI every job gets its own service
container, so nothing is shared.

CI (`.github/workflows/tests.yml`) runs the suite on PHP 8.4 and 8.5 against SQLite, on PHP 8.4/MySQL 8.0
and PHP 8.5/MySQL 8.4, plus one job with the lowest allowed dependency versions.

`phpunit.xml.dist` is strict: risky tests, warnings, notices and deprecations coming from `src`
fail the build. There is no baseline, `src` is expected to stay free of deprecations.

`docs/fixes.md` documents the bugs the test suite uncovered and how they were fixed.

## Tips

- Always have all logic inside a `filter` or `order` callback. This will ensure that all dependencies (like a logged user etc.) are already set.
Expand Down
19 changes: 18 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,32 @@
},
"require": {
"php": ">=8.4",
"doctrine/orm": "^2.18|^3.0",
"doctrine/orm": "^3.3",
"doctrine/dbal": "^4.0",
"nette/utils": "^3.2|^4.0",
"tracy/tracy": "^2.10",
"psr/log": "^3.0",
"nettrine/dbal": "^0.9.0 | ^0.10.0"
},
"require-dev": {
"phpunit/phpunit": "^11.5 | ^12.0",
"symfony/cache": "^7.0",
"nette/di": "^3.1 | ^4.0"
},
"autoload": {
"psr-4": {
"ADT\\DoctrineComponents\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"ADT\\DoctrineComponents\\Tests\\": "tests/"
}
},
"scripts": {
"tests": "phpunit"
},
"config": {
"sort-packages": true
}
}
Loading
Loading