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..a58e3f1f1 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
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/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
* $arClass
+ * @psalm-return T
*/
public function createAR(
string $arClass,
diff --git a/src/BaseActiveRecord.php b/src/BaseActiveRecord.php
index 64e3406f5..bf6557933 100644
--- a/src/BaseActiveRecord.php
+++ b/src/BaseActiveRecord.php
@@ -302,6 +302,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
{
@@ -338,12 +340,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);
@@ -1085,6 +1092,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()}