From e32fa0dd6e27caf538d2181ff49e17ff0985b620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A1=8C=E9=A3=8E?= Date: Wed, 3 Jan 2024 15:19:43 +0800 Subject: [PATCH 1/3] Update the comments of the method createQueryTo in ActiveRecordFactory so that the IDE can automatically identify the specific class of ActiveRecord (#280) Co-authored-by: Sergei Tigrov --- src/ActiveQuery.php | 3 +++ src/ActiveRecordFactory.php | 5 +++++ src/BaseActiveRecord.php | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/src/ActiveQuery.php b/src/ActiveQuery.php index 4cb8160d7..23ea9ea53 100644 --- a/src/ActiveQuery.php +++ b/src/ActiveQuery.php @@ -107,6 +107,9 @@ class ActiveQuery extends Query implements ActiveQueryInterface private array $joinWith = []; private ActiveRecordInterface|null $arInstance = null; + /** + * @psalm-param class-string $arClass + */ final public function __construct( protected string $arClass, protected ConnectionInterface $db, diff --git a/src/ActiveRecordFactory.php b/src/ActiveRecordFactory.php index 3940fa741..876487e7a 100644 --- a/src/ActiveRecordFactory.php +++ b/src/ActiveRecordFactory.php @@ -29,6 +29,11 @@ public function __construct(private Factory $factory) * @throws InvalidConfigException * @throws NotFoundException * @throws NotInstantiableException + * @return ActiveRecordInterface + * + * @psalm-template T of ActiveRecordInterface + * @psalm-param class-string $arClass + * @psalm-return T */ public function createAR( string $arClass, diff --git a/src/BaseActiveRecord.php b/src/BaseActiveRecord.php index 2550d6179..9e34d15f5 100644 --- a/src/BaseActiveRecord.php +++ b/src/BaseActiveRecord.php @@ -324,6 +324,8 @@ public function hasAttribute($name): bool * **this** AR class. * * @return ActiveQueryInterface The relational query object. + * + * @psalm-param class-string $class */ public function hasMany(string $class, array $link): ActiveQueryInterface { @@ -360,12 +362,17 @@ public function hasMany(string $class, array $link): ActiveQueryInterface * **this** AR class. * * @return ActiveQueryInterface The relational query object. + * + * @psalm-param class-string $class */ public function hasOne(string $class, array $link): ActiveQueryInterface { return $this->createRelationQuery($class, $link, false); } + /** + * @psalm-param class-string $arClass + */ public function instantiateQuery(string $arClass): ActiveQueryInterface { return new ActiveQuery($arClass, $this->db, $this->arFactory); @@ -1117,6 +1124,8 @@ private function setRelationDependencies( * @param bool $multiple Whether this query represents a relation to more than one record. * * @return ActiveQueryInterface The relational query object. + * + * @psalm-param class-string $arClass * {@see hasOne()} * {@see hasMany()} From a9097f17330e1a0d649aafb21733a392d960773b Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Fri, 5 Jan 2024 08:06:40 -0300 Subject: [PATCH 2/3] Add docs for testing. (#288) Co-authored-by: Alexander Makarov --- .../workflows/composer-require-checker.yml | 6 +- .github/workflows/db-mssql.yml | 6 +- .github/workflows/db-mysql.yml | 6 +- .github/workflows/db-oracle.yml | 6 +- .github/workflows/db-pgsql.yml | 6 +- .github/workflows/db-sqlite.yml | 6 +- .github/workflows/mutation.yml | 47 ++----- .github/workflows/rector.yml | 6 +- .github/workflows/static.yml | 7 +- README.md | 120 +++--------------- composer.json | 9 +- docs/en/testing.md | 102 +++++++++++++++ phpunit.xml.dist | 3 - 13 files changed, 174 insertions(+), 156 deletions(-) create mode 100644 docs/en/testing.md diff --git a/.github/workflows/composer-require-checker.yml b/.github/workflows/composer-require-checker.yml index ae5893f54..7817057db 100644 --- a/.github/workflows/composer-require-checker.yml +++ b/.github/workflows/composer-require-checker.yml @@ -23,6 +23,10 @@ on: name: Composer require checker +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: composer-require-checker: uses: yiisoft/actions/.github/workflows/composer-require-checker.yml@master @@ -30,4 +34,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0', '8.1'] + ['8.1', '8.2', '8.3'] diff --git a/.github/workflows/db-mssql.yml b/.github/workflows/db-mssql.yml index e90bf347b..896560545 100644 --- a/.github/workflows/db-mssql.yml +++ b/.github/workflows/db-mssql.yml @@ -21,6 +21,10 @@ on: name: db-mssql +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: PHP ${{ matrix.php }} @@ -38,9 +42,9 @@ jobs: - ubuntu-latest php: - - 8.0 - 8.1 - 8.2 + - 8.3 services: mssql: diff --git a/.github/workflows/db-mysql.yml b/.github/workflows/db-mysql.yml index c6f6b17d5..739e37970 100644 --- a/.github/workflows/db-mysql.yml +++ b/.github/workflows/db-mysql.yml @@ -21,6 +21,10 @@ on: name: db-mysql +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: PHP ${{ matrix.php }} @@ -38,9 +42,9 @@ jobs: - ubuntu-latest php: - - 8.0 - 8.1 - 8.2 + - 8.3 services: mysql: diff --git a/.github/workflows/db-oracle.yml b/.github/workflows/db-oracle.yml index 7d2d6bdba..62bd30ec2 100644 --- a/.github/workflows/db-oracle.yml +++ b/.github/workflows/db-oracle.yml @@ -21,6 +21,10 @@ on: name: db-oracle +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: PHP ${{ matrix.php }} @@ -38,9 +42,9 @@ jobs: - ubuntu-latest php: - - 8.0 - 8.1 - 8.2 + - 8.3 services: oci: diff --git a/.github/workflows/db-pgsql.yml b/.github/workflows/db-pgsql.yml index 97b968df7..88921f407 100644 --- a/.github/workflows/db-pgsql.yml +++ b/.github/workflows/db-pgsql.yml @@ -21,6 +21,10 @@ on: name: db-pgsql +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: PHP ${{ matrix.php }} @@ -38,9 +42,9 @@ jobs: - ubuntu-latest php: - - 8.0 - 8.1 - 8.2 + - 8.3 services: postgres: diff --git a/.github/workflows/db-sqlite.yml b/.github/workflows/db-sqlite.yml index f01766d2e..6f49b5b33 100644 --- a/.github/workflows/db-sqlite.yml +++ b/.github/workflows/db-sqlite.yml @@ -21,6 +21,10 @@ on: name: db-sqlite +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: PHP ${{ matrix.php }}-sqlite-${{ matrix.os }} @@ -39,9 +43,9 @@ jobs: - windows-latest php: - - 8.0 - 8.1 - 8.2 + - 8.3 steps: - name: Checkout. diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index db5c7aafb..26f19e282 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -19,12 +19,16 @@ on: name: mutation +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: mutation: name: PHP ${{ matrix.php }}-${{ matrix.os }} env: - extensions: pdo, pdo_mysql, pdo_oci, pdo_pgsql, pdo_sqlite, pdo_sqlsrv-5.10.0-beta2, oci8 + extensions: pdo, pdo_pgsql runs-on: ${{ matrix.os }} @@ -34,39 +38,9 @@ jobs: - ubuntu-latest php: - - 8.0 + - 8.1 services: - mssql: - image: mcr.microsoft.com/mssql/server:2019-latest - env: - SA_PASSWORD: YourStrong!Passw0rd - ACCEPT_EULA: Y - MSSQL_PID: Developer - ports: - - 1433:1433 - options: --name=mssql --health-cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'YourStrong!Passw0rd' -Q 'SELECT 1'" --health-interval=10s --health-timeout=5s --health-retries=3 - mysql: - image: mysql:latest - env: - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_PASSWORD: '' - MYSQL_DATABASE: yiitest - ports: - - 3306:3306 - options: --name=mysql --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - oci: - image: gvenzl/oracle-xe:latest - ports: - - 1521:1521 - env: - ORACLE_PASSWORD : root - options: >- - --name=oci - --health-cmd healthcheck.sh - --health-interval 10s - --health-timeout 5s - --health-retries 10 postgres: image: postgres:14 env: @@ -81,9 +55,6 @@ jobs: - name: Checkout. uses: actions/checkout@v3 - - name: Create MS SQL Database. - run: docker exec -i mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'YourStrong!Passw0rd' -Q 'CREATE DATABASE yiitest' - - name: Install PHP with extensions. uses: shivammathur/setup-php@v2 with: @@ -96,11 +67,11 @@ jobs: - name: Update composer. run: composer self-update - - name: Install db drivers. - run: composer require 'yiisoft/db-mssql:dev-master' 'yiisoft/db-mysql:dev-master' 'yiisoft/db-oracle:dev-master' 'yiisoft/db-pgsql:dev-master' 'yiisoft/db-sqlite:dev-master' --no-interaction --no-progress --optimize-autoloader --ansi + - name: Install db-pgsql. + run: composer require yiisoft/db-pgsql --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - name: Run infection. run: | - vendor/bin/roave-infection-static-analysis-plugin -j2 --ignore-msi-with-no-mutations --only-covered + vendor/bin/roave-infection-static-analysis-plugin --threads=2 --ignore-msi-with-no-mutations --only-covered --test-framework-options="--testsuite=Pgsql" env: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index e21dd376a..21cb5b39f 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -21,6 +21,10 @@ on: name: rector +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: rector: uses: yiisoft/actions/.github/workflows/rector.yml@master @@ -28,4 +32,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0'] + ['8.1'] diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index d04a2f729..78374887d 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -21,6 +21,10 @@ on: name: static analysis +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: mutation: name: PHP ${{ matrix.php }}-${{ matrix.os }} @@ -33,8 +37,9 @@ jobs: - ubuntu-latest php: - - 8.0 - 8.1 + - 8.2 + - 8.3 steps: - name: Checkout diff --git a/README.md b/README.md index 1c400c4d6..c5ca2d965 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ It is used in [Yii Framework] but is supposed to be usable separately. [![Latest Stable Version](https://poser.pugx.org/yiisoft/active-record/v/stable.png)](https://packagist.org/packages/yiisoft/active-record) [![Total Downloads](https://poser.pugx.org/yiisoft/active-record/downloads.png)](https://packagist.org/packages/yiisoft/active-record) -[![build](https://github.com/yiisoft/active-record/actions/workflows/build.yml/badge.svg?branch=dev)](https://github.com/yiisoft/active-record/actions/workflows/build.yml) [![codecov](https://codecov.io/gh/yiisoft/active-record/branch/master/graph/badge.svg?token=w4KarhYyEF)](https://codecov.io/gh/yiisoft/active-record) [![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Factive-record%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/active-record/master) [![static analysis](https://github.com/yiisoft/active-record/actions/workflows/static.yml/badge.svg?branch=dev)](https://github.com/yiisoft/active-record/actions/workflows/static.yml) @@ -43,10 +42,10 @@ composer require yiisoft/active-record Example: ```php -composer require yiisoft/db-mysql +composer require yiisoft/db-sqlite ``` -## Configuration container di autowired +## Config container interface class web.php: ```php @@ -55,17 +54,18 @@ web.php: declare(strict_types=1); use Yiisoft\Db\Connection\ConnectionInterface; -use Yiisoft\Db\Sqlite\Connection as SqliteConnection; +use Yiisoft\Db\Sqlite\Connection; +use Yiisoft\Db\Sqlite\Driver; /** * config ConnectionInterface::class */ return [ ConnectionInterface::class => [ - 'class' => SqliteConnection::class, + 'class' => Connection::class, '__construct()' => [ - 'dsn' => $params['yiisoft/db-sqlite']['dsn'], - ] + 'driver' => new Driver($params['yiisoft/db-sqlite']['dsn']), + ], ] ]; ``` @@ -83,7 +83,8 @@ return [ ] ``` -defined your active record, example User.php: +## Defined your active record class + ```php [ - 'class' => SqliteConnection::class, - '__construct()' => [ - 'dsn' => $params['yiisoft/db-sqlite']['dsn'], - ] - ], - - ActiveRecordFactory::class => [ - 'class' => ActiveRecordFactory::class, - '__construct()' => [ - null, - [ConnectionInterface::class => Reference::to(SqliteConnection::class)], - ] - ] -]; -``` - -params.php -```php - [ - 'dsn' => 'sqlite:' . dirname(__DIR__) . '/runtime/yiitest.sq3', - ] -] -``` +## Usage in controler with Active Record factory -defined your active record, example User.php: -```php - Note: We recommend pull requesting in draft mode until all tests pass. + +## Docker images + +For greater ease we recommend to use Docker container for each DBMS. For this you can use the [docker-compose.yml](https://docs.docker.com/compose/compose-file/) file that's in the root directory of each package. + +- [MSSQL 2022](https://github.com/yiisoft/db-mssql/blob/master/docker-compose.yml) +- [MySQL 8](https://github.com/yiisoft/db-mysql/blob/master/docker-compose.yml) +- [MariaDB 10.11](https://github.com/yiisoft/db-mysql/blob/master/docker-compose-mariadb.yml) +- [Oracle 21](https://github.com/yiisoft/db-oracle/blob/master/docker-compose.yml) +- [PostgreSQL 15](https://github.com/yiisoft/db-pgsql/blob/master/docker-compose.yml) + +To run Docker containers you can use the following command: + +```shell +docker compose up -d +``` + +## Unit testing + +The package is tested with [PHPUnit](https://phpunit.de/). + +### Global testing + +The following steps are required to run tests. + +1. Install all DBMS dependencies with composer. + +```shell +composer require --dev yiisoft/db-mssql yiisoft/db-mysql yiisoft/db-oracle yiisoft/db-pgsql yiisoft/db-sqlite --ansi +``` + +2. Run all Docker containers for each DBMS. +3. Run the tests. + +```shell +vendor/bin/phpunit +``` + +### Individual testing + +The following steps are required to run the tests. + +1. Install DBMS dependencies with Composer. + +```shell +composer require --dev yiisoft/db-pgsql --ansi +``` + +2. Run the Docker container for the DBMS you want to test. +3. Run the tests. + +```shell +vendor/bin/phpunit --testsuite=Pgsql +``` + +Suites available: +- Mssql +- Mysql +- Oracle +- Pgsql +- Sqlite + +## Static analysis + +The code is statically analyzed with [Psalm](https://psalm.dev/). To run static analysis: + +```shell +./vendor/bin/psalm +``` + +## Rector + +Use [Rector](https://github.com/rectorphp/rector) to make codebase follow some specific rules or use either newest or any specific version of PHP: + +```shell +./vendor/bin/rector +``` + +## Composer require checker + +This package uses [composer-require-checker](https://github.com/maglnet/ComposerRequireChecker) to check if all dependencies are correctly defined in `composer.json`. + +To run the checker, execute the following command: + +```shell +./vendor/bin/composer-require-checker +``` diff --git a/phpunit.xml.dist b/phpunit.xml.dist index dafbc9b93..b92f0e1b3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -5,9 +5,6 @@ - - ./tests/Driver - ./tests/Driver/Mssql From 2ba318b4f7f82c69a0d7e4d639ba6f6ad45fe68b Mon Sep 17 00:00:00 2001 From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com> Date: Thu, 11 Jan 2024 13:26:49 -0300 Subject: [PATCH 3/3] Update docs (#292) --- README.md | 2 +- composer.json | 2 +- src/ActiveRecord.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c5ca2d965..a58e3f1f1 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ use Yiisoft\ActiveRecord\ActiveRecord; **/ final class User extends ActiveRecord { - public function tableName(): string + public function getTableName(): string { return '{{%user}}'; } diff --git a/composer.json b/composer.json index d30c4ab25..ed5c52249 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "require-dev": { "maglnet/composer-require-checker": "^4.2", "phpunit/phpunit": "^10.5", - "rector/rector": "^0.18", + "rector/rector": "^0.19", "roave/infection-static-analysis-plugin": "^1.34", "spatie/phpunit-watcher": "^1.23", "vimeo/psalm": "^5.8", diff --git a/src/ActiveRecord.php b/src/ActiveRecord.php index f636136a3..7b408a43d 100644 --- a/src/ActiveRecord.php +++ b/src/ActiveRecord.php @@ -40,21 +40,21 @@ * In this example, Active Record is providing an object-oriented interface for accessing data stored in the database. * But Active Record provides much more functionality than this. * - * To declare an ActiveRecord class you need to extend {@see ActiveRecord} and implement the `tableName` method: + * To declare an ActiveRecord class you need to extend {@see ActiveRecord} and implement the `getTableName` method: * * ```php *