From 8dba1c4f472c50df7358732e4ed40bba4c6baac7 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 4 Jun 2020 18:18:18 +0300 Subject: [PATCH 01/69] patch laravel-clickhouse --- README.md | 10 +++--- composer.json | 18 +++++----- phpunit.xml | 2 +- src/ClickHouseServiceProvider.php | 6 ++-- src/Database/Connection.php | 4 +-- src/Database/Eloquent/Builder.php | 8 ++--- src/Database/Eloquent/Collection.php | 2 +- .../Eloquent/Concerns/HasAttributes.php | 2 +- src/Database/Eloquent/Model.php | 6 ++-- src/Database/Query/Builder.php | 4 +-- tests/EloquentModelCastingTest.php | 2 +- tests/EloquentModelTest.php | 4 +-- tests/EloquentModelWithTest.php | 4 +-- tests/Helpers.php | 2 +- tests/Unit/Database/ConnectionTest.php | 14 +++++--- tests/Unit/Database/Eloquent/BuilderTest.php | 34 +++++++++---------- .../Unit/Database/Eloquent/CollectionTest.php | 22 ++++++------ tests/Unit/Database/Eloquent/ModelTest.php | 22 ++++++------ tests/Unit/Database/Query/BuilderTest.php | 23 ++++++------- 19 files changed, 96 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 9194de7..53eb746 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # laravel-clickhouse -[![Build Status](https://travis-ci.org/esazykin/laravel-clickhouse.svg?branch=master)](https://travis-ci.org/esazykin/laravel-clickhouse) +[![Build Status](https://travis-ci.org/bavix/laravel-clickhouse.svg?branch=master)](https://travis-ci.org/bavix/laravel-clickhouse) [![StyleCI](https://styleci.io/repos/112756298/shield?branch=master)](https://styleci.io/repos/112756298) -[![Coverage Status](https://coveralls.io/repos/github/esazykin/laravel-clickhouse/badge.svg)](https://coveralls.io/github/esazykin/laravel-clickhouse) +[![Coverage Status](https://coveralls.io/repos/github/bavix/laravel-clickhouse/badge.svg)](https://coveralls.io/github/bavix/laravel-clickhouse) Eloquent model for ClickHouse @@ -11,12 +11,12 @@ Eloquent model for ClickHouse ## Installation ```sh -$ composer require esazykin/laravel-clickhouse +$ composer require bavix/laravel-clickhouse ``` Then add the code above into your config/app.php file providers section ```php -Esazykin\LaravelClickHouse\ClickHouseServiceProvider::class, +Bavix\LaravelClickHouse\ClickHouseServiceProvider::class, ``` And add new connection into your config/database.php file. Something like this: ```php @@ -72,7 +72,7 @@ Then create model ```php =7.1", - "laravel/framework": "5.5.*", - "esazykin/clickhouse-builder": "^1.1" + "php": ">=7.3", + "laravel/framework": "^6.0|^7.0", + "the-tinderbox/clickhouse-builder": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^6.5", - "mockery/mockery": "^1.0", - "fzaninotto/faker": "^1.7" + "phpunit/phpunit": "^9.1", + "mockery/mockery": "^1.4", + "fzaninotto/faker": "^1.9" }, "autoload": { "psr-4": { - "Esazykin\\LaravelClickHouse\\": "src/" + "Bavix\\LaravelClickHouse\\": "src/" } }, "autoload-dev": { "psr-4": { - "Esazykin\\LaravelClickHouse\\Tests\\": "tests/" + "Bavix\\LaravelClickHouse\\Tests\\": "tests/" } }, "scripts": { diff --git a/phpunit.xml b/phpunit.xml index 2dee96b..1431f13 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -19,6 +19,6 @@ - + diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index 16c3080..1daa17c 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Esazykin\LaravelClickHouse; +namespace Bavix\LaravelClickHouse; use Illuminate\Support\ServiceProvider; use Illuminate\Database\DatabaseManager; -use Esazykin\LaravelClickHouse\Database\Connection; -use Esazykin\LaravelClickHouse\Database\Eloquent\Model; +use Bavix\LaravelClickHouse\Database\Connection; +use Bavix\LaravelClickHouse\Database\Eloquent\Model; class ClickHouseServiceProvider extends ServiceProvider { diff --git a/src/Database/Connection.php b/src/Database/Connection.php index 5752d19..f6cfd08 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Esazykin\LaravelClickHouse\Database; +namespace Bavix\LaravelClickHouse\Database; use Tinderbox\ClickhouseBuilder\Query\Grammar; -use Esazykin\LaravelClickHouse\Database\Query\Builder; +use Bavix\LaravelClickHouse\Database\Query\Builder; class Connection extends \Tinderbox\ClickhouseBuilder\Integrations\Laravel\Connection { diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index 064975c..6ba4d05 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -1,6 +1,6 @@ 'localhost']); + $connection = new Connection([ + 'host' => 'localhost', + 'port' => '8123', + 'database' => 'default', + ]); $this->assertInstanceOf(Builder::class, $connection->query()); } diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index 462178b..9f76465 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -2,23 +2,23 @@ declare(strict_types=1); -namespace Esazykin\LaravelClickHouse\Tests\Unit\Database\Eloquent; +namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; use Mockery\Mock; use PHPUnit\Framework\TestCase; use Illuminate\Database\DatabaseManager; use Tinderbox\ClickhouseBuilder\Query\Tuple; -use Esazykin\LaravelClickHouse\Tests\Helpers; +use Bavix\LaravelClickHouse\Tests\Helpers; use Tinderbox\ClickhouseBuilder\Query\Grammar; use Tinderbox\ClickhouseBuilder\Query\Identifier; -use Esazykin\LaravelClickHouse\Database\Connection; +use Bavix\LaravelClickHouse\Database\Connection; use Tinderbox\ClickhouseBuilder\Query\Enums\Operator; use Illuminate\Database\Eloquent\ModelNotFoundException; -use Esazykin\LaravelClickHouse\Database\Eloquent\Builder; -use Esazykin\LaravelClickHouse\Database\Eloquent\Collection; -use Esazykin\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Database\Eloquent\Builder; +use Bavix\LaravelClickHouse\Database\Eloquent\Collection; +use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; use Tinderbox\ClickhouseBuilder\Query\TwoElementsLogicExpression; -use Esazykin\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; /** * @property Mock|Connection connection @@ -29,7 +29,7 @@ class BuilderTest extends TestCase { use Helpers; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -41,7 +41,7 @@ protected function setUp() ->setModel($this->model); } - public function testWhereKey() + public function testWhereKey(): void { $id = $this->faker()->numberBetween(1); @@ -63,7 +63,7 @@ public function testWhereKey() $this->assertSame('=', $operator->getValue()); } - public function testWhereKeyNot() + public function testWhereKeyNot(): void { $ids = range(1, 5); @@ -87,7 +87,7 @@ public function testWhereKeyNot() $this->assertSame('NOT IN', $operator->getValue()); } - public function testWhereSimple() + public function testWhereSimple(): void { $date = $this->faker()->date(); $this->builder->where('date_column', '>', $date); @@ -108,7 +108,7 @@ public function testWhereSimple() $this->assertSame('>', $operator->getValue()); } - public function testWhereClosure() + public function testWhereClosure(): void { /** @var Mock|DatabaseManager $resolver */ $resolver = $this->mock(DatabaseManager::class); @@ -128,7 +128,7 @@ public function testWhereClosure() $this->assertSame('SELECT * FROM `test_table` WHERE (`id` < 10 OR `id` = 15) AND `status` = 100', $sql); } - public function testOrWhere() + public function testOrWhere(): void { $id = $this->faker()->numberBetween(1); $date = $this->faker()->date(); @@ -142,7 +142,7 @@ public function testOrWhere() ); } - public function testFind() + public function testFind(): void { $id = $this->faker()->numberBetween(1); $stringAttribute = $this->faker()->word; @@ -164,7 +164,7 @@ public function testFind() $this->assertSame($stringAttribute, $model->stringAttribute); } - public function testFindMany() + public function testFindMany(): void { $ids = collect()->times(5); @@ -188,7 +188,7 @@ public function testFindMany() $this->assertCount($ids->count(), $models); } - public function testFindOrFail() + public function testFindOrFail(): void { $this->expectException(ModelNotFoundException::class); @@ -203,7 +203,7 @@ public function testFindOrFail() $this->builder->findOrFail($this->faker()->numberBetween()); } - public function testGet() + public function testGet(): void { $connectionResultRow = [ 'id' => $this->faker()->randomDigit, diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index 5af08b7..8318bc4 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -2,16 +2,16 @@ declare(strict_types=1); -namespace Esazykin\LaravelClickHouse\Tests\Unit\Database\Eloquent; +namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; use Mockery\Mock; use Carbon\Carbon; use PHPUnit\Framework\TestCase; use Illuminate\Database\DatabaseManager; -use Esazykin\LaravelClickHouse\Tests\Helpers; -use Esazykin\LaravelClickHouse\Database\Connection; -use Esazykin\LaravelClickHouse\Database\Eloquent\Collection; -use Esazykin\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\Helpers; +use Bavix\LaravelClickHouse\Database\Connection; +use Bavix\LaravelClickHouse\Database\Eloquent\Collection; +use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; /** * @property Mock|Connection connection @@ -20,7 +20,7 @@ class CollectionTest extends TestCase { use Helpers; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -38,7 +38,7 @@ protected function setUp() EloquentModelCastingTest::setConnectionResolver($resolver); } - public function testMapModelToModel() + public function testMapModelToModel(): void { $connectionResult = collect() ->times(5, function (int $id) { @@ -68,7 +68,7 @@ public function testMapModelToModel() }); } - public function testMapModelToArray() + public function testMapModelToArray(): void { $connectionResult = collect() ->times(5, function (int $id) { @@ -103,7 +103,7 @@ public function testMapModelToArray() * @dataProvider findDataProvider * @param $key */ - public function testFind($key) + public function testFind($key): void { $connectionResult = collect() ->times(5, function (int $id) { @@ -131,7 +131,7 @@ public function testFind($key) * @param null $operator * @param null $value */ - public function testContains(bool $expected, $key, $operator = null, $value = null) + public function testContains(bool $expected, $key, $operator = null, $value = null): void { $connectionResult = collect() ->times(5, function (int $id) { @@ -151,7 +151,7 @@ public function testContains(bool $expected, $key, $operator = null, $value = nu $this->assertSame($expected, $contains); } - public function testGet() + public function testGet(): void { $connectionResult = collect() ->times(5, function (int $id) { diff --git a/tests/Unit/Database/Eloquent/ModelTest.php b/tests/Unit/Database/Eloquent/ModelTest.php index bade4e8..3585025 100644 --- a/tests/Unit/Database/Eloquent/ModelTest.php +++ b/tests/Unit/Database/Eloquent/ModelTest.php @@ -2,21 +2,21 @@ declare(strict_types=1); -namespace Esazykin\LaravelClickHouse\Tests\Unit\Database\Eloquent; +namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; use Illuminate\Support\Carbon; use PHPUnit\Framework\TestCase; -use Esazykin\LaravelClickHouse\Tests\Helpers; -use Esazykin\LaravelClickHouse\Tests\EloquentModelTest; +use Bavix\LaravelClickHouse\Tests\Helpers; +use Bavix\LaravelClickHouse\Tests\EloquentModelTest; use Illuminate\Database\Eloquent\MassAssignmentException; -use Esazykin\LaravelClickHouse\Tests\EloquentModelWithTest; -use Esazykin\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\EloquentModelWithTest; +use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; class ModelTest extends TestCase { use Helpers; - public function testAttributeManipulation() + public function testAttributeManipulation(): void { $model = new EloquentModelTest(); $model->status = 'successful'; @@ -31,14 +31,14 @@ public function testAttributeManipulation() $this->assertEquals(json_encode(range(1, 5)), $attributes['list_items']); } - public function testDirtyAttributes() + public function testDirtyAttributes(): void { $this->expectException(MassAssignmentException::class); new EloquentModelTest(['foo' => '1', 'bar' => 2, 'baz' => 3]); } - public function testDirtyOnCastOrDateAttributes() + public function testDirtyOnCastOrDateAttributes(): void { $model = new EloquentModelCastingTest(); $model->setDateFormat('Y-m-d H:i:s'); @@ -61,7 +61,7 @@ public function testDirtyOnCastOrDateAttributes() $this->assertTrue($model->isDirty('datetimeAttribute')); } - public function testCalculatedAttributes() + public function testCalculatedAttributes(): void { $model = new EloquentModelTest(); $model->password = 'secret'; @@ -74,13 +74,13 @@ public function testCalculatedAttributes() $this->assertEquals($hash, $model->password_hash); } - public function testWithMethodCallsQueryBuilderCorrectly() + public function testWithMethodCallsQueryBuilderCorrectly(): void { $result = EloquentModelWithTest::with('foo', 'bar'); $this->assertEquals('foo', $result); } - public function testTimestampsAreReturnedAsObjectsFromPlainDatesAndTimestamps() + public function testTimestampsAreReturnedAsObjectsFromPlainDatesAndTimestamps(): void { $datetime = '2012-12-04'; $model = new EloquentModelCastingTest(); diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index cdc3ae7..4585f3b 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -2,14 +2,14 @@ declare(strict_types=1); -namespace Esazykin\LaravelClickHouse\Tests\Unit\Database\Query; +namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Query; use PHPUnit\Framework\TestCase; -use Esazykin\LaravelClickHouse\Tests\Helpers; +use Bavix\LaravelClickHouse\Tests\Helpers; use Tinderbox\ClickhouseBuilder\Query\Grammar; -use Esazykin\LaravelClickHouse\Database\Connection; +use Bavix\LaravelClickHouse\Database\Connection; use Tinderbox\ClickhouseBuilder\Query\Enums\Format; -use Esazykin\LaravelClickHouse\Database\Query\Builder; +use Bavix\LaravelClickHouse\Database\Query\Builder; /** * @property \Mockery\MockInterface|Connection connection @@ -19,7 +19,7 @@ class BuilderTest extends TestCase { use Helpers; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -96,9 +96,11 @@ public function testInsert(): void $this->faker()->numerify('column_#') => $this->faker()->randomLetter, ]; $inserted = [$insertedRow]; + ksort($insertedRow); + $values = collect($insertedRow)->values()->toArray(); $generatedSql = sprintf( - 'INSERT INTO `%s` (%s) FORMAT %s (?, ?, ?)', + 'INSERT INTO `%s` (%s) FORMAT %s (\'%s\', %d, %d)', $this->builder->getFrom()->getTable(), collect($insertedRow) ->keys() @@ -107,16 +109,13 @@ public function testInsert(): void return sprintf('`%s`', $columnName); }) ->implode(', '), - Format::VALUES + Format::VALUES, + ...$values ); - ksort($insertedRow); $this->connection ->shouldReceive('insert') - ->withArgs([ - $generatedSql, - collect($insertedRow)->values()->toArray(), - ]) + ->withArgs([$generatedSql, $values]) ->andReturn(true); $this->assertTrue($this->builder->insert($inserted)); From e4e740081394096bb3e9648ef97f76fca3eb6915 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 11 Jun 2020 12:41:50 +0300 Subject: [PATCH 02/69] fix travis config --- .travis.yml | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 82a7ddd..7db0943 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,30 @@ language: php - php: - - 7.1 + - '7.2' + - '7.3' + - '7.4' + - 'nightly' + +services: + - memcached -before_install: - - composer require php-coveralls/php-coveralls +matrix: + allow_failures: + - php: 'nightly' before_script: - - composer self-update - - composer install --prefer-source --dev + - pecl install pcov + - phpenv config-rm xdebug.ini || echo "xdebug not available" + - bash <(curl -s https://raw.githubusercontent.com/php-cache/cache/master/build/php/7.2/Memcached.sh) + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + - chmod +x ./cc-test-reporter + - if [ $(phpenv version-name) = "7.4" ]; then ./cc-test-reporter before-build; fi + - composer install -script: vendor/bin/phpunit --coverage-clover ./tests/logs/clover.xml +script: + - ./vendor/bin/phpunit --coverage-xml=build/coverage-xml --log-junit=build/junit.xml + - ./vendor/bin/infection --coverage=build --min-msi=60 -j$(nproc) -after_script: - - php vendor/bin/php-coveralls -v \ No newline at end of file +after_success: + - if [ $(phpenv version-name) = "7.4" ]; then ./cc-test-reporter after-build --coverage-input-type clover --exit-code $TRAVIS_TEST_RESULT; fi + - bash <(curl -s https://codecov.io/bash) From 407e60d6894650d1455b94e150fa658316ea1a76 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 11 Jun 2020 12:44:36 +0300 Subject: [PATCH 03/69] add support php 7.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 956b753..8763fad 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "the-tinderbox/clickhouse-builder": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^9.1", + "phpunit/phpunit": "^8.0|^9.1", "mockery/mockery": "^1.4", "fzaninotto/faker": "^1.9" }, From 485996627cbca76d35976d46023330b1b91d804e Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 11 Jun 2020 12:47:42 +0300 Subject: [PATCH 04/69] add infection --- composer.json | 3 ++- infection.json.dist | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 infection.json.dist diff --git a/composer.json b/composer.json index 8763fad..7f0cc66 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "the-tinderbox/clickhouse-builder": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^8.0|^9.1", + "infection/infection": "0.15.*|0.16.*", + "phpunit/phpunit": "^8.0|^9.0", "mockery/mockery": "^1.4", "fzaninotto/faker": "^1.9" }, diff --git a/infection.json.dist b/infection.json.dist new file mode 100644 index 0000000..14a49e9 --- /dev/null +++ b/infection.json.dist @@ -0,0 +1,17 @@ +{ + "timeout": 10, + "source": { + "directories": [ + "src" + ] + }, + "logs": { + "text": "build/infection.log", + "badge": { + "branch": "master" + } + }, + "mutators": { + "@default": true + } +} From 6bc6edac8ed1b9f85f561b32afe3b7251acb34b0 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 11 Jun 2020 12:49:45 +0300 Subject: [PATCH 05/69] fix php --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7f0cc66..6dd09c0 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "eloquent" ], "require": { - "php": ">=7.3", + "php": ">=7.2", "laravel/framework": "^6.0|^7.0", "the-tinderbox/clickhouse-builder": "^3.0" }, From 79ec6b8c2ef24df29007f08e6d3b6658a30c3e18 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 11 Jun 2020 12:51:15 +0300 Subject: [PATCH 06/69] fix msi --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7db0943..d9aefd3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_script: script: - ./vendor/bin/phpunit --coverage-xml=build/coverage-xml --log-junit=build/junit.xml - - ./vendor/bin/infection --coverage=build --min-msi=60 -j$(nproc) + - ./vendor/bin/infection --coverage=build --min-msi=20 -j$(nproc) after_success: - if [ $(phpenv version-name) = "7.4" ]; then ./cc-test-reporter after-build --coverage-input-type clover --exit-code $TRAVIS_TEST_RESULT; fi From 1921a7288a1b7bc54aed7df282e948d710ed3216 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 11 Jun 2020 12:53:23 +0300 Subject: [PATCH 07/69] fix mockery --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6dd09c0..4190998 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "require-dev": { "infection/infection": "0.15.*|0.16.*", "phpunit/phpunit": "^8.0|^9.0", - "mockery/mockery": "^1.4", + "mockery/mockery": "^1.3", "fzaninotto/faker": "^1.9" }, "autoload": { From 22510d01869c319719de5ab08754d386f8dd4e7b Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 28 Jun 2020 19:09:57 +0300 Subject: [PATCH 08/69] Update composer.json --- composer.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/composer.json b/composer.json index 4190998..1b494d7 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,13 @@ "Bavix\\LaravelClickHouse\\Tests\\": "tests/" } }, + "extra": { + "laravel": { + "providers": [ + "Bavix\\LaravelClickHouse\\ClickHouseServiceProvider" + ] + } + }, "scripts": { "test": "vendor/bin/phpunit --stop-on-failure tests/" } From 2649d638a2e2004a842e56121ab7eba64f648301 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 28 Jun 2020 21:27:41 +0300 Subject: [PATCH 09/69] Update ClickHouseServiceProvider.php --- src/ClickHouseServiceProvider.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index 1daa17c..cc61cf0 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -16,10 +16,14 @@ public function boot(): void /** @var DatabaseManager $db */ $db = $this->app->get('db'); - $db->extend('clickhouse', function ($config, $name) { + $db->extend('clickhouse-ext', function ($config, $name) { $config['name'] = $name; + $connection = new Connection($config); + if ($this->app->bound('events')) { + $connection->setEventDispatcher($this->app['events']); + } - return new Connection($config); + return $connection; }); Model::setConnectionResolver($db); From c4e7537be92528ebd3bec93918cc84574fd63eab Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 28 Jun 2020 21:28:19 +0300 Subject: [PATCH 10/69] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 53eb746..44374bd 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ And add new connection into your config/database.php file. Something like this: ```php 'connections' => [ 'clickhouse' => [ - 'driver' => 'clickhouse', + 'driver' => 'clickhouse-ext', 'host' => '', 'port' => '', 'database' => '', @@ -39,7 +39,7 @@ Or like this, if clickhouse runs in cluster ```php 'connections' => [ 'clickhouse' => [ - 'driver' => 'clickhouse', + 'driver' => 'clickhouse-ext', 'cluster' => [ 'server-1' => [ 'host' => '', From 2f1578b1c8bb927a4c1eb21e8a3faf1e6a3283d8 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 28 Jun 2020 22:06:43 +0300 Subject: [PATCH 11/69] Update ClickHouseServiceProvider.php --- src/ClickHouseServiceProvider.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index cc61cf0..4cbbf41 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -11,21 +11,23 @@ class ClickHouseServiceProvider extends ServiceProvider { + /** + * @return void + */ public function boot(): void { - /** @var DatabaseManager $db */ - $db = $this->app->get('db'); + $this->app->resolving('db', function ($db) { + $db->extend('clickhouse-ext', function ($config, $name) { + $config['name'] = $name; + $connection = new Connection($config); + if ($this->app->bound('events')) { + $connection->setEventDispatcher($this->app['events']); + } - $db->extend('clickhouse-ext', function ($config, $name) { - $config['name'] = $name; - $connection = new Connection($config); - if ($this->app->bound('events')) { - $connection->setEventDispatcher($this->app['events']); - } + return $connection; + }); - return $connection; + Model::setConnectionResolver($db); }); - - Model::setConnectionResolver($db); } } From 43bd2e8fff7ad2821dfe8fb3bd055f1e5c07de40 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 28 Jun 2020 22:06:58 +0300 Subject: [PATCH 12/69] Update ClickHouseServiceProvider.php From df0e98df0097dd8405c5dd823f7c6638f66b02fb Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 9 Jul 2020 20:32:34 +0300 Subject: [PATCH 13/69] first version --- README.md | 8 +- composer.json | 3 +- src/ClickHouseServiceProvider.php | 26 ++++--- src/Database/Eloquent/Concerns/Common.php | 19 +++++ src/Database/Eloquent/Model.php | 8 +- tests/Unit/Database/ConnectionTest.php | 2 +- tests/Unit/Database/Eloquent/BuilderTest.php | 78 +++++++++---------- .../Unit/Database/Eloquent/CollectionTest.php | 34 ++++---- tests/Unit/Database/Eloquent/ModelTest.php | 36 ++++----- tests/Unit/Database/Query/BuilderTest.php | 16 ++-- 10 files changed, 128 insertions(+), 102 deletions(-) create mode 100644 src/Database/Eloquent/Concerns/Common.php diff --git a/README.md b/README.md index 44374bd..008c528 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ Bavix\LaravelClickHouse\ClickHouseServiceProvider::class, And add new connection into your config/database.php file. Something like this: ```php 'connections' => [ - 'clickhouse' => [ - 'driver' => 'clickhouse-ext', + 'bavix::clickhouse' => [ + 'driver' => 'bavix::clickhouse', 'host' => '', 'port' => '', 'database' => '', @@ -38,8 +38,8 @@ And add new connection into your config/database.php file. Something like this: Or like this, if clickhouse runs in cluster ```php 'connections' => [ - 'clickhouse' => [ - 'driver' => 'clickhouse-ext', + 'bavix::clickhouse' => [ + 'driver' => 'bavix::clickhouse', 'cluster' => [ 'server-1' => [ 'host' => '', diff --git a/composer.json b/composer.json index 1b494d7..caf965c 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ "require": { "php": ">=7.2", "laravel/framework": "^6.0|^7.0", - "the-tinderbox/clickhouse-builder": "^3.0" + "the-tinderbox/clickhouse-builder": "^3.0", + "ext-json": "*" }, "require-dev": { "infection/infection": "0.15.*|0.16.*", diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index 4cbbf41..dd6e761 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -4,8 +4,8 @@ namespace Bavix\LaravelClickHouse; -use Illuminate\Support\ServiceProvider; use Illuminate\Database\DatabaseManager; +use Illuminate\Support\ServiceProvider; use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Eloquent\Model; @@ -13,21 +13,25 @@ class ClickHouseServiceProvider extends ServiceProvider { /** * @return void + * @throws */ public function boot(): void { - $this->app->resolving('db', function ($db) { - $db->extend('clickhouse-ext', function ($config, $name) { - $config['name'] = $name; - $connection = new Connection($config); - if ($this->app->bound('events')) { - $connection->setEventDispatcher($this->app['events']); - } + Model::setConnectionResolver($this->app['db']); + Model::setEventDispatcher($this->app['events']); + } - return $connection; + /** + * @return void + */ + public function register(): void + { + $this->app->resolving('db', static function (DatabaseManager $db) { + $db->extend('bavix::clickhouse', static function ($config, $name) { + return new Connection(\array_merge($config, [ + 'name' => $name, + ])); }); - - Model::setConnectionResolver($db); }); } } diff --git a/src/Database/Eloquent/Concerns/Common.php b/src/Database/Eloquent/Concerns/Common.php new file mode 100644 index 0000000..4ba18dc --- /dev/null +++ b/src/Database/Eloquent/Concerns/Common.php @@ -0,0 +1,19 @@ +toArray()); + } + +} diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index 340e024..2ab2855 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -22,11 +22,13 @@ use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; /** - * @mixin \Eloquent + * Class Model + * @package Bavix\LaravelClickHouse\Database\Eloquent */ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable { use Concerns\HasAttributes, + Concerns\Common, HasEvents, HasRelationships, HidesAttributes, @@ -37,7 +39,7 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab * * @var string */ - protected $connection = 'clickhouse'; + protected $connection = 'bavix::clickhouse'; /** * The table associated with the model. @@ -426,7 +428,7 @@ public function setConnection(string $name) */ public static function resolveConnection(string $connection = null) { - return static::$resolver->connection($connection); + return static::getConnectionResolver()->connection($connection); } /** diff --git a/tests/Unit/Database/ConnectionTest.php b/tests/Unit/Database/ConnectionTest.php index d51a406..3b28110 100644 --- a/tests/Unit/Database/ConnectionTest.php +++ b/tests/Unit/Database/ConnectionTest.php @@ -18,6 +18,6 @@ public function testQuery(): void 'database' => 'default', ]); - $this->assertInstanceOf(Builder::class, $connection->query()); + self::assertInstanceOf(Builder::class, $connection->query()); } } diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index 9f76465..be952a4 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -49,18 +49,18 @@ public function testWhereKey(): void $wheres = $this->builder->getQuery()->getWheres(); - $this->assertCount(1, $wheres); + self::assertCount(1, $wheres); /** @var TwoElementsLogicExpression $expression */ $expression = $wheres[0]; - $this->assertInstanceOf(TwoElementsLogicExpression::class, $expression); + self::assertInstanceOf(TwoElementsLogicExpression::class, $expression); /** @var Identifier $first */ $first = $expression->getFirstElement(); - $this->assertInstanceOf(Identifier::class, $first); - $this->assertSame($this->model->getTable().'.'.$this->model->getKeyName(), (string) $first); - $this->assertSame($id, $expression->getSecondElement()); + self::assertInstanceOf(Identifier::class, $first); + self::assertSame($this->model->getTable().'.'.$this->model->getKeyName(), (string) $first); + self::assertSame($id, $expression->getSecondElement()); $operator = $expression->getOperator(); - $this->assertInstanceOf(Operator::class, $operator); - $this->assertSame('=', $operator->getValue()); + self::assertInstanceOf(Operator::class, $operator); + self::assertSame('=', $operator->getValue()); } public function testWhereKeyNot(): void @@ -71,20 +71,20 @@ public function testWhereKeyNot(): void $wheres = $this->builder->getQuery()->getWheres(); - $this->assertCount(1, $wheres); + self::assertCount(1, $wheres); /** @var TwoElementsLogicExpression $expression */ $expression = $wheres[0]; - $this->assertInstanceOf(TwoElementsLogicExpression::class, $expression); + self::assertInstanceOf(TwoElementsLogicExpression::class, $expression); /** @var Identifier $first */ $first = $expression->getFirstElement(); - $this->assertInstanceOf(Identifier::class, $first); - $this->assertSame($this->model->getTable().'.'.$this->model->getKeyName(), (string) $first); + self::assertInstanceOf(Identifier::class, $first); + self::assertSame($this->model->getTable().'.'.$this->model->getKeyName(), (string) $first); /** @var Tuple $second */ $second = $expression->getSecondElement(); - $this->assertSame($ids, $second->getElements()); + self::assertSame($ids, $second->getElements()); $operator = $expression->getOperator(); - $this->assertInstanceOf(Operator::class, $operator); - $this->assertSame('NOT IN', $operator->getValue()); + self::assertInstanceOf(Operator::class, $operator); + self::assertSame('NOT IN', $operator->getValue()); } public function testWhereSimple(): void @@ -94,18 +94,18 @@ public function testWhereSimple(): void $wheres = $this->builder->getQuery()->getWheres(); - $this->assertCount(1, $wheres); + self::assertCount(1, $wheres); /** @var TwoElementsLogicExpression $expression */ $expression = $wheres[0]; - $this->assertInstanceOf(TwoElementsLogicExpression::class, $expression); + self::assertInstanceOf(TwoElementsLogicExpression::class, $expression); /** @var Identifier $first */ $first = $expression->getFirstElement(); - $this->assertInstanceOf(Identifier::class, $first); - $this->assertSame('date_column', (string) $first); - $this->assertSame($date, $expression->getSecondElement()); + self::assertInstanceOf(Identifier::class, $first); + self::assertSame('date_column', (string) $first); + self::assertSame($date, $expression->getSecondElement()); $operator = $expression->getOperator(); - $this->assertInstanceOf(Operator::class, $operator); - $this->assertSame('>', $operator->getValue()); + self::assertInstanceOf(Operator::class, $operator); + self::assertSame('>', $operator->getValue()); } public function testWhereClosure(): void @@ -125,7 +125,7 @@ public function testWhereClosure(): void $sql = $this->builder->toSql(); - $this->assertSame('SELECT * FROM `test_table` WHERE (`id` < 10 OR `id` = 15) AND `status` = 100', $sql); + self::assertSame('SELECT * FROM `test_table` WHERE (`id` < 10 OR `id` = 15) AND `status` = 100', $sql); } public function testOrWhere(): void @@ -136,7 +136,7 @@ public function testOrWhere(): void $this->builder->orWhere('date_column', '>', $date); $sql = $this->builder->toSql(); - $this->assertSame( + self::assertSame( 'SELECT * FROM `test_table` WHERE `id` = '.$id.' OR `date_column` > \''.$date.'\'', $sql ); @@ -159,9 +159,9 @@ public function testFind(): void $model = $this->builder->find($id); - $this->assertInstanceOf(EloquentModelCastingTest::class, $model); - $this->assertSame($id, $model->id); - $this->assertSame($stringAttribute, $model->stringAttribute); + self::assertInstanceOf(EloquentModelCastingTest::class, $model); + self::assertSame($id, $model->id); + self::assertSame($stringAttribute, $model->stringAttribute); } public function testFindMany(): void @@ -184,8 +184,8 @@ public function testFindMany(): void $models = $this->builder->findMany($ids->toArray()); - $this->assertInstanceOf(Collection::class, $models); - $this->assertCount($ids->count(), $models); + self::assertInstanceOf(Collection::class, $models); + self::assertCount($ids->count(), $models); } public function testFindOrFail(): void @@ -234,18 +234,18 @@ public function testGet(): void $collection = $this->builder->get(); - $this->assertInstanceOf(Collection::class, $collection); - $this->assertCount(1, $collection); + self::assertInstanceOf(Collection::class, $collection); + self::assertCount(1, $collection); $retrievedModel = $collection[0]; - $this->assertSame($connectionResultRow['id'], $retrievedModel->id); - $this->assertSame((int) $connectionResultRow['intAttribute'], $retrievedModel->intAttribute); - $this->assertSame((float) $connectionResultRow['floatAttribute'], $retrievedModel->floatAttribute); - $this->assertSame((string) $connectionResultRow['stringAttribute'], $retrievedModel->stringAttribute); - $this->assertTrue($retrievedModel->boolAttribute); - $this->assertTrue($retrievedModel->booleanAttribute); - $this->assertEquals(json_decode($connectionResultRow['objectAttribute']), $retrievedModel->objectAttribute); - $this->assertSame(json_decode($connectionResultRow['arrayAttribute'], true), $retrievedModel->arrayAttribute); - $this->assertSame($connectionResultRow['arrayAttribute'], $retrievedModel->jsonAttribute); + self::assertSame($connectionResultRow['id'], $retrievedModel->id); + self::assertSame((int) $connectionResultRow['intAttribute'], $retrievedModel->intAttribute); + self::assertSame((float) $connectionResultRow['floatAttribute'], $retrievedModel->floatAttribute); + self::assertSame((string) $connectionResultRow['stringAttribute'], $retrievedModel->stringAttribute); + self::assertTrue($retrievedModel->boolAttribute); + self::assertTrue($retrievedModel->booleanAttribute); + self::assertEquals(json_decode($connectionResultRow['objectAttribute']), $retrievedModel->objectAttribute); + self::assertSame(json_decode($connectionResultRow['arrayAttribute'], true), $retrievedModel->arrayAttribute); + self::assertSame($connectionResultRow['arrayAttribute'], $retrievedModel->jsonAttribute); } } diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index 8318bc4..f8de44c 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -58,13 +58,13 @@ public function testMapModelToModel(): void return $model; }); - $this->assertInstanceOf(Collection::class, $models); - $this->assertCount($connectionResult->count(), $models); + self::assertInstanceOf(Collection::class, $models); + self::assertCount($connectionResult->count(), $models); $models->each(function (EloquentModelCastingTest $model, int $key) use ($now) { - $this->assertSame($key + 1, $model->id); - $this->assertInstanceOf(Carbon::class, $model->datetimeAttribute); - $this->assertSame($now->toDateTimeString(), $model->datetimeAttribute->toDateTimeString()); + self::assertSame($key + 1, $model->id); + self::assertInstanceOf(Carbon::class, $model->datetimeAttribute); + self::assertSame($now->toDateTimeString(), $model->datetimeAttribute->toDateTimeString()); }); } @@ -89,13 +89,13 @@ public function testMapModelToArray(): void ]; }); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $collection); - $this->assertCount($connectionResult->count(), $collection); + self::assertInstanceOf(\Illuminate\Support\Collection::class, $collection); + self::assertCount($connectionResult->count(), $collection); $collection->each(function (array $row, int $key) use ($now) { - $this->assertSame($key + 1, $row['id']); - $this->assertInstanceOf(Carbon::class, $row['datetimeAttribute']); - $this->assertSame($now->toDateTimeString(), $row['datetimeAttribute']->toDateTimeString()); + self::assertSame($key + 1, $row['id']); + self::assertInstanceOf(Carbon::class, $row['datetimeAttribute']); + self::assertSame($now->toDateTimeString(), $row['datetimeAttribute']->toDateTimeString()); }); } @@ -117,10 +117,10 @@ public function testFind($key): void $found = EloquentModelCastingTest::all()->find($key); if (is_array($key)) { - $this->assertInstanceOf(Collection::class, $found); - $this->assertCount(count($key), $found); + self::assertInstanceOf(Collection::class, $found); + self::assertCount(count($key), $found); } else { - $this->assertInstanceOf(EloquentModelCastingTest::class, $found); + self::assertInstanceOf(EloquentModelCastingTest::class, $found); } } @@ -148,7 +148,7 @@ public function testContains(bool $expected, $key, $operator = null, $value = nu $contains = EloquentModelCastingTest::all()->contains($key); } - $this->assertSame($expected, $contains); + self::assertSame($expected, $contains); } public function testGet(): void @@ -167,13 +167,13 @@ public function testGet(): void $models = EloquentModelCastingTest::all(); - $this->assertInstanceOf(Collection::class, $models); - $this->assertCount($connectionResult->count(), $models); + self::assertInstanceOf(Collection::class, $models); + self::assertCount($connectionResult->count(), $models); $models = $models->map(function (EloquentModelCastingTest $model) { return $model->toArray(); }); - $this->assertSame( + self::assertSame( $connectionResult ->map(function (array $row) { $row['floatAttribute'] = (float) $row['floatAttribute']; diff --git a/tests/Unit/Database/Eloquent/ModelTest.php b/tests/Unit/Database/Eloquent/ModelTest.php index 3585025..6aa7d5b 100644 --- a/tests/Unit/Database/Eloquent/ModelTest.php +++ b/tests/Unit/Database/Eloquent/ModelTest.php @@ -20,15 +20,15 @@ public function testAttributeManipulation(): void { $model = new EloquentModelTest(); $model->status = 'successful'; - $this->assertEquals('successful', $model->status); - $this->assertTrue(isset($model->status)); + self::assertEquals('successful', $model->status); + self::assertTrue(isset($model->status)); unset($model->status); - $this->assertFalse(isset($model->status)); + self::assertFalse(isset($model->status)); // test mutation $model->list_items = range(1, 5); - $this->assertEquals(range(1, 5), $model->list_items); + self::assertEquals(range(1, 5), $model->list_items); $attributes = $model->getAttributes(); - $this->assertEquals(json_encode(range(1, 5)), $attributes['list_items']); + self::assertEquals(json_encode(range(1, 5)), $attributes['list_items']); } public function testDirtyAttributes(): void @@ -53,12 +53,12 @@ public function testDirtyOnCastOrDateAttributes(): void $model->bar = '2017-03-18 00:00:00'; $model->dateAttribute = '2017-03-18 00:00:00'; $model->datetimeAttribute = null; - $this->assertTrue($model->isDirty()); - $this->assertTrue($model->isDirty('foo')); - $this->assertTrue($model->isDirty('bar')); - $this->assertFalse($model->isDirty('boolAttribute')); - $this->assertFalse($model->isDirty('dateAttribute')); - $this->assertTrue($model->isDirty('datetimeAttribute')); + self::assertTrue($model->isDirty()); + self::assertTrue($model->isDirty('foo')); + self::assertTrue($model->isDirty('bar')); + self::assertFalse($model->isDirty('boolAttribute')); + self::assertFalse($model->isDirty('dateAttribute')); + self::assertTrue($model->isDirty('datetimeAttribute')); } public function testCalculatedAttributes(): void @@ -67,17 +67,17 @@ public function testCalculatedAttributes(): void $model->password = 'secret'; $attributes = $model->getAttributes(); // ensure password attribute was not set to null - $this->assertArrayNotHasKey('password', $attributes); - $this->assertSame('******', $model->password); + self::assertArrayNotHasKey('password', $attributes); + self::assertSame('******', $model->password); $hash = 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4'; - $this->assertEquals($hash, $attributes['password_hash']); - $this->assertEquals($hash, $model->password_hash); + self::assertEquals($hash, $attributes['password_hash']); + self::assertEquals($hash, $model->password_hash); } public function testWithMethodCallsQueryBuilderCorrectly(): void { $result = EloquentModelWithTest::with('foo', 'bar'); - $this->assertEquals('foo', $result); + self::assertEquals('foo', $result); } public function testTimestampsAreReturnedAsObjectsFromPlainDatesAndTimestamps(): void @@ -86,7 +86,7 @@ public function testTimestampsAreReturnedAsObjectsFromPlainDatesAndTimestamps(): $model = new EloquentModelCastingTest(); $model->payed_at = $datetime; - $this->assertInstanceOf(Carbon::class, $model->payed_at); - $this->assertSame($datetime.' 00:00:00', $model->payed_at->toDateTimeString()); + self::assertInstanceOf(Carbon::class, $model->payed_at); + self::assertSame($datetime.' 00:00:00', $model->payed_at->toDateTimeString()); } } diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index 4585f3b..c715dfe 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -41,8 +41,8 @@ public function testGet(): void $builderResult = $this->builder->get(); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $builderResult); - $this->assertSame($connectionResult, $builderResult->toArray()); + self::assertInstanceOf(\Illuminate\Support\Collection::class, $builderResult); + self::assertSame($connectionResult, $builderResult->toArray()); } public function testCount(): void @@ -55,7 +55,7 @@ public function testCount(): void $builderResult = $this->builder->count(); - $this->assertCount($builderResult, $connectionResult); + self::assertCount($builderResult, $connectionResult); } public function testFirst(): void @@ -68,12 +68,12 @@ public function testFirst(): void $builderResult = $this->builder->first(); - $this->assertSame($connectionResult[0], $builderResult); + self::assertSame($connectionResult[0], $builderResult); } public function testNewQuery(): void { - $this->assertInstanceOf(Builder::class, $this->builder->newQuery()); + self::assertInstanceOf(Builder::class, $this->builder->newQuery()); } public function testInsertFiles(): void @@ -83,12 +83,12 @@ public function testInsertFiles(): void ->andReturn([]); $builderResult = $this->builder->insertFiles(['column_1', 'column_2'], []); - $this->assertSame([], $builderResult); + self::assertSame([], $builderResult); } public function testInsert(): void { - $this->assertFalse($this->builder->insert([])); + self::assertFalse($this->builder->insert([])); $insertedRow = [ $this->faker()->word => $this->faker()->randomDigit, @@ -118,6 +118,6 @@ public function testInsert(): void ->withArgs([$generatedSql, $values]) ->andReturn(true); - $this->assertTrue($this->builder->insert($inserted)); + self::assertTrue($this->builder->insert($inserted)); } } From eb31b09194cad498aa5904a41714817c5441af15 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 9 Jul 2020 20:49:57 +0300 Subject: [PATCH 14/69] update docs --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 008c528..438c643 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,9 @@ Or like this, if clickhouse runs in cluster 'connections' => [ 'bavix::clickhouse' => [ 'driver' => 'bavix::clickhouse', - 'cluster' => [ - 'server-1' => [ - 'host' => '', + 'servers' => [ + [ + 'host' => 'ch-00.domain.com', 'port' => '', 'database' => '', 'username' => '', @@ -52,8 +52,8 @@ Or like this, if clickhouse runs in cluster 'protocol' => 'https' ] ], - 'server-2' => [ - 'host' => '', + [ + 'host' => 'ch-01.domain.com', 'port' => '', 'database' => '', 'username' => '', @@ -65,7 +65,7 @@ Or like this, if clickhouse runs in cluster ] ] ] -] +], ``` Then create model From f379ce078c9f8722658d5a26164c767e4fb10220 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 9 Jul 2020 22:25:58 +0300 Subject: [PATCH 15/69] fix telescope --- src/Database/Connection.php | 12 ++++++++++++ src/Database/Query/Pdo.php | 15 +++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/Database/Query/Pdo.php diff --git a/src/Database/Connection.php b/src/Database/Connection.php index f6cfd08..24b4e91 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -4,13 +4,25 @@ namespace Bavix\LaravelClickHouse\Database; +use Bavix\LaravelClickHouse\Database\Query\Pdo; use Tinderbox\ClickhouseBuilder\Query\Grammar; use Bavix\LaravelClickHouse\Database\Query\Builder; class Connection extends \Tinderbox\ClickhouseBuilder\Integrations\Laravel\Connection { + /** + * @return Builder|\Tinderbox\ClickhouseBuilder\Integrations\Laravel\Builder + */ public function query() { return new Builder($this, new Grammar()); } + + /** + * @inheritDoc + */ + public function getPdo() + { + return app(Pdo::class); + } } diff --git a/src/Database/Query/Pdo.php b/src/Database/Query/Pdo.php new file mode 100644 index 0000000..304f7fe --- /dev/null +++ b/src/Database/Query/Pdo.php @@ -0,0 +1,15 @@ + Date: Mon, 31 Aug 2020 13:14:44 +0300 Subject: [PATCH 16/69] Update composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index caf965c..a23665c 100644 --- a/composer.json +++ b/composer.json @@ -9,12 +9,12 @@ ], "require": { "php": ">=7.2", - "laravel/framework": "^6.0|^7.0", + "laravel/framework": "^6.0|^7.0|^8.0", "the-tinderbox/clickhouse-builder": "^3.0", "ext-json": "*" }, "require-dev": { - "infection/infection": "0.15.*|0.16.*", + "infection/infection": "0.15.*|0.16.*|0.17.*", "phpunit/phpunit": "^8.0|^9.0", "mockery/mockery": "^1.3", "fzaninotto/faker": "^1.9" From 073e5f43b55e749e793690dd9c6070d9c113ba92 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 24 Sep 2020 10:42:14 +0300 Subject: [PATCH 17/69] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a23665c..07fe877 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "require": { "php": ">=7.2", "laravel/framework": "^6.0|^7.0|^8.0", - "the-tinderbox/clickhouse-builder": "^3.0", + "the-tinderbox/clickhouse-builder": "^4.0", "ext-json": "*" }, "require-dev": { From 271ba0918b5a9dea37ebd5f03e5482a757f9f0bb Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 24 Sep 2020 22:43:01 +0300 Subject: [PATCH 18/69] update library... more strong typing and tests --- .travis.yml | 2 + composer.json | 1 + src/ClickHouseServiceProvider.php | 4 +- src/Database/Connection.php | 2 +- src/Database/Eloquent/Builder.php | 233 +++++++++++----------- src/Database/Eloquent/Collection.php | 2 +- src/Database/Eloquent/Concerns/Common.php | 2 + src/Database/Query/Builder.php | 11 +- src/Database/Query/Pdo.php | 2 + tests/Unit/Database/ConnectionTest.php | 81 +++++++- tests/Unit/Database/Query/BuilderTest.php | 23 ++- 11 files changed, 228 insertions(+), 135 deletions(-) diff --git a/.travis.yml b/.travis.yml index d9aefd3..26b8c8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ php: - 'nightly' services: + - docker - memcached matrix: @@ -13,6 +14,7 @@ matrix: - php: 'nightly' before_script: + - docker run -p 9000:9000 -p 8123:8123 -d --name clickhouse --ulimit nofile=262144:262144 yandex/clickhouse-server - pecl install pcov - phpenv config-rm xdebug.ini || echo "xdebug not available" - bash <(curl -s https://raw.githubusercontent.com/php-cache/cache/master/build/php/7.2/Memcached.sh) diff --git a/composer.json b/composer.json index 07fe877..6096902 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "bavix/laravel-clickhouse", + "description": "Eloquent model for ClickHouse", "type": "library", "license": "MIT", "keywords": [ diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index dd6e761..12eadbc 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -28,9 +28,7 @@ public function register(): void { $this->app->resolving('db', static function (DatabaseManager $db) { $db->extend('bavix::clickhouse', static function ($config, $name) { - return new Connection(\array_merge($config, [ - 'name' => $name, - ])); + return new Connection(\array_merge($config, \compact('name'))); }); }); } diff --git a/src/Database/Connection.php b/src/Database/Connection.php index 24b4e91..9002aac 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -19,7 +19,7 @@ public function query() } /** - * @inheritDoc + * @return Pdo */ public function getPdo() { diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index 6ba4d05..a38774a 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -1,9 +1,13 @@ query->whereIn($this->model->getQualifiedKeyName(), $id); - return $this; } @@ -106,14 +110,13 @@ public function whereKey($id) /** * Add a where clause on the primary key to the query. * - * @param mixed $id + * @param mixed $id * @return $this */ - public function whereKeyNot($id) + public function whereKeyNot($id): self { if (is_array($id) || $id instanceof Arrayable) { $this->query->whereNotIn($this->model->getQualifiedKeyName(), $id); - return $this; } @@ -123,10 +126,10 @@ public function whereKeyNot($id) /** * Add a basic where clause to the query. * - * @param string|array|\Closure $column - * @param string $operator - * @param mixed $value - * @param string $boolean + * @param string|array|\Closure $column + * @param string $operator + * @param mixed $value + * @param string $boolean * @return $this */ public function where($column, $operator = null, $value = null, string $boolean = 'AND'): self @@ -146,12 +149,12 @@ public function where($column, $operator = null, $value = null, string $boolean /** * Add an "or where" clause to the query. * - * @param \Closure|array|string $column - * @param string $operator - * @param mixed $value - * @return Builder|static + * @param \Closure|array|string $column + * @param string $operator + * @param mixed $value + * @return $this */ - public function orWhere($column, $operator = null, $value = null) + public function orWhere($column, $operator = null, $value = null): self { return $this->where($column, $operator, $value, 'OR'); } @@ -159,26 +162,28 @@ public function orWhere($column, $operator = null, $value = null) /** * Create a collection of models from plain arrays. * - * @param array $items + * @param iterable $items * @return Collection */ - public function hydrate(array $items) + public function hydrate(iterable $items): Collection { $instance = $this->newModelInstance(); + $elements = []; + foreach ($items as $item) { + $elements[] = $instance->newFromBuilder($item); + } - return $instance->newCollection(array_map(function ($item) use ($instance) { - return $instance->newFromBuilder($item); - }, $items)); + return $instance->newCollection($elements); } /** * Create a collection of models from a raw query. * - * @param string $query - * @param array $bindings + * @param string $query + * @param array $bindings * @return Collection */ - public function fromQuery($query, $bindings = []) + public function fromQuery($query, $bindings = []): Collection { return $this->hydrate( $this->query->getConnection()->select($query, $bindings) @@ -188,7 +193,7 @@ public function fromQuery($query, $bindings = []) /** * Find a model by its primary key. * - * @param mixed $id + * @param mixed $id * @return Model|Collection|static[]|static|null */ public function find($id) @@ -203,7 +208,7 @@ public function find($id) /** * Find multiple models by their primary keys. * - * @param \Illuminate\Contracts\Support\Arrayable|array $ids + * @param \Illuminate\Contracts\Support\Arrayable|array $ids * @return Collection */ public function findMany($ids): Collection @@ -218,13 +223,14 @@ public function findMany($ids): Collection /** * Find a model by its primary key or throw an exception. * - * @param mixed $id + * @param mixed $id * @return Model|Collection * * @throws ModelNotFoundException */ public function findOrFail($id) { + // fixme Arrayable::class $result = $this->find($id); if (is_array($id)) { @@ -243,27 +249,32 @@ public function findOrFail($id) /** * Execute the query and get the first result or throw an exception. * - * @return Model|static + * @return Model|null * * @throws ModelNotFoundException */ - public function firstOrFail() + public function firstOrFail(): ?Model { + /** + * @var Model $model + */ $model = $this->first(); - if ($model !== null) { - return $model; + if ($model === null) { + throw (new ModelNotFoundException) + ->setModel(get_class($this->model)) + ; } - throw (new ModelNotFoundException)->setModel(get_class($this->model)); + return $model; } /** * Execute the query as a "select" statement. * - * @return Collection|static[] - * @throws \Tinderbox\Clickhouse\Exceptions\ClientException + * @return Collection + * @throws ClientException */ - public function get() + public function get(): Collection { $builder = $this->applyScopes(); @@ -281,7 +292,7 @@ public function get() * Get the hydrated models without eager loading. * * @return Model[] - * @throws \Tinderbox\Clickhouse\Exceptions\ClientException + * @throws ClientException */ public function getModels(): array { @@ -293,10 +304,10 @@ public function getModels(): array /** * Eager load the relationships for the models. * - * @param array $models + * @param array $models * @return array */ - public function eagerLoadRelations(array $models) + public function eagerLoadRelations(array $models): array { foreach ($this->eagerLoad as $name => $constraints) { // For nested eager loads we'll skip loading them here and they will be set as an @@ -313,12 +324,12 @@ public function eagerLoadRelations(array $models) /** * Eagerly load the relationship on a set of models. * - * @param array $models - * @param string $name - * @param \Closure $constraints + * @param array $models + * @param string $name + * @param \Closure $constraints * @return array */ - protected function eagerLoadRelation(array $models, $name, Closure $constraints) + protected function eagerLoadRelation(array $models, string $name, Closure $constraints): array { // First we will "back up" the existing where conditions on the query so we can // add our eager constraints. Then we will merge the wheres that were on the @@ -334,17 +345,18 @@ protected function eagerLoadRelation(array $models, $name, Closure $constraints) // of models which have been eagerly hydrated and are readied for return. return $relation->match( $relation->initRelation($models, $name), - $relation->getEager(), $name + $relation->getEager(), + $name ); } /** * Get the relation instance for the given relation name. * - * @param string $name - * @return Relations\Relation + * @param string $name + * @return Relation */ - public function getRelation($name) + public function getRelation(string $name): Relation { // We want to run a relationship query without any constrains so that we will // not have to remove these where clauses manually which gets really hacky @@ -372,10 +384,10 @@ public function getRelation($name) /** * Get the deeply nested relations for a given top-level relation. * - * @param string $relation + * @param string $relation * @return array */ - protected function relationsNestedUnder($relation) + protected function relationsNestedUnder(string $relation): array { $nested = []; @@ -384,7 +396,7 @@ protected function relationsNestedUnder($relation) // that start with the given top relations and adds them to our arrays. foreach ($this->eagerLoad as $name => $constraints) { if ($this->isNestedUnder($relation, $name)) { - $nested[substr($name, strlen($relation.'.'))] = $constraints; + $nested[substr($name, strlen($relation . '.'))] = $constraints; } } @@ -394,30 +406,28 @@ protected function relationsNestedUnder($relation) /** * Determine if the relationship is nested. * - * @param string $relation - * @param string $name + * @param string $relation + * @param string $name * @return bool */ - protected function isNestedUnder($relation, $name) + protected function isNestedUnder(string $relation, string $name): bool { - return Str::contains($name, '.') && Str::startsWith($name, $relation.'.'); + return Str::contains($name, '.') && Str::startsWith($name, $relation . '.'); } /** * Chunk the results of a query by comparing numeric IDs. * - * @param int $count - * @param callable $callback - * @param string $column - * @param string|null $alias + * @param int $count + * @param callable $callback + * @param null $column + * @param string|null $alias * @return bool */ - public function chunkById($count, callable $callback, $column = null, $alias = null) + public function chunkById(int $count, callable $callback, $column = null, $alias = null): bool { $column = is_null($column) ? $this->getModel()->getKeyName() : $column; - $alias = is_null($alias) ? $column : $alias; - $lastId = 0; do { @@ -428,9 +438,9 @@ public function chunkById($count, callable $callback, $column = null, $alias = n // we will call the callback with the current chunk of these results here. $results = $clone->forPageAfterId($count, $lastId, $column)->get(); - $countResults = $results->count(); + $countResults = (int)$results->count(); - if ($countResults == 0) { + if (!$countResults) { break; } @@ -444,7 +454,7 @@ public function chunkById($count, callable $callback, $column = null, $alias = n $lastId = $results->last()->{$alias}; unset($results); - } while ($countResults == $count); + } while ($countResults === $count); return true; } @@ -452,11 +462,11 @@ public function chunkById($count, callable $callback, $column = null, $alias = n /** * Get an array with the values of a given column. * - * @param string $column - * @param string|null $key + * @param string $column + * @param string|null $key * @return \Illuminate\Support\Collection */ - public function pluck($column, $key = null) + public function pluck(string $column, $key = null): \Illuminate\Support\Collection { $results = $this->toBase()->pluck($column, $key); @@ -465,7 +475,7 @@ public function pluck($column, $key = null) // columns are returned as you would expect from these Eloquent models. if (!$this->model->hasGetMutator($column) && !$this->model->hasCast($column) && - !in_array($column, $this->model->getDates())) { + !in_array($column, $this->model->getDates(), true)) { return $results; } @@ -477,20 +487,17 @@ public function pluck($column, $key = null) /** * Paginate the given query. * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator + * @param int|null $perPage + * @param array $columns + * @param string $pageName + * @param int|null $page + * @return LengthAwarePaginator * - * @throws \InvalidArgumentException */ - public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null) + public function paginate(?int $perPage = null, $columns = ['*'], $pageName = 'page', $page = null): LengthAwarePaginator { $page = $page ?: Paginator::resolveCurrentPage($pageName); - $perPage = $perPage ?: $this->model->getPerPage(); - $results = ($total = $this->toBase()->getCountForPagination()) ? $this->forPage($page, $perPage)->get($columns) : $this->model->newCollection(); @@ -504,13 +511,14 @@ public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', /** * Paginate the given query into a simple paginator. * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page + * @param int|null $perPage + * @param array $columns + * @param string $pageName + * @param int|null $page * @return \Illuminate\Contracts\Pagination\Paginator + * @throws ClientException */ - public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null) + public function simplePaginate(?int $perPage = null, $columns = ['*'], $pageName = 'page', $page = null): \Illuminate\Contracts\Pagination\Paginator { $page = $page ?: Paginator::resolveCurrentPage($pageName); @@ -530,7 +538,7 @@ public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'p /** * Call the given local model scopes. * - * @param array $scopes + * @param array $scopes * @return mixed */ public function scopes(array $scopes) @@ -549,8 +557,8 @@ public function scopes(array $scopes) // care of grouping the "wheres" properly so the logical order doesn't get // messed up when adding scopes. Then we'll return back out the builder. $builder = $builder->callScope( - [$this->model, 'scope'.ucfirst($scope)], - (array) $parameters + [$this->model, 'scope' . ucfirst($scope)], + (array)$parameters ); } @@ -598,8 +606,8 @@ public function applyScopes() /** * Apply the given scope on the current builder instance. * - * @param callable $scope - * @param array $parameters + * @param callable $scope + * @param array $parameters * @return mixed */ protected function callScope(callable $scope, $parameters = []) @@ -616,7 +624,7 @@ protected function callScope(callable $scope, $parameters = []) $result = $scope(...array_values($parameters)) ?? $this; - if (count((array) $query->getWheres()) > $originalWhereCount) { + if (count((array)$query->getWheres()) > $originalWhereCount) { $this->addNewWheresWithinGroup($query, $originalWhereCount); } @@ -626,8 +634,8 @@ protected function callScope(callable $scope, $parameters = []) /** * Nest where conditions by slicing them at the given where count. * - * @param \Illuminate\Database\Query\Builder $query - * @param int $originalWhereCount + * @param \Illuminate\Database\Query\Builder $query + * @param int $originalWhereCount * @return void */ protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCount) @@ -651,8 +659,8 @@ protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCo /** * Slice where conditions at the given offset and add them to the query as a nested condition. * - * @param \Illuminate\Database\Query\Builder $query - * @param array $whereSlice + * @param \Illuminate\Database\Query\Builder $query + * @param array $whereSlice * @return void */ protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) @@ -674,8 +682,8 @@ protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) /** * Create a where array with nested where conditions. * - * @param array $whereSlice - * @param string $boolean + * @param array $whereSlice + * @param string $boolean * @return array */ protected function createNestedWhere($whereSlice, $boolean = 'and') @@ -690,7 +698,7 @@ protected function createNestedWhere($whereSlice, $boolean = 'and') /** * Set the relationships that should be eager loaded. * - * @param mixed $relations + * @param mixed $relations * @return $this */ public function with($relations) @@ -705,7 +713,7 @@ public function with($relations) /** * Prevent the specified relations from being eager loaded. * - * @param mixed $relations + * @param mixed $relations * @return $this */ public function without($relations) @@ -720,7 +728,7 @@ public function without($relations) /** * Create a new instance of the model being queried. * - * @param array $attributes + * @param array $attributes * @return Model */ public function newModelInstance($attributes = []) @@ -733,7 +741,7 @@ public function newModelInstance($attributes = []) /** * Parse a list of relations into individuals. * - * @param array $relations + * @param array $relations * @return array */ protected function parseWithRelations(array $relations) @@ -771,7 +779,7 @@ function () { /** * Create a constraint to select the given columns for the relation. * - * @param string $name + * @param string $name * @return array */ protected function createSelectWithConstraint($name) @@ -787,8 +795,8 @@ function ($query) use ($name) { /** * Parse the nested relationships in a relation. * - * @param string $name - * @param array $results + * @param string $name + * @param array $results * @return array */ protected function addNestedWiths($name, $results) @@ -846,7 +854,7 @@ public function getEagerLoads() /** * Set the relationships being eagerly loaded. * - * @param array $eagerLoad + * @param array $eagerLoad * @return $this */ public function setEagerLoads(array $eagerLoad) @@ -873,7 +881,7 @@ public function setModel(Model $model) /** * Get the given macro by name. * - * @param string $name + * @param string $name * @return \Closure */ public function getMacro($name) @@ -884,21 +892,19 @@ public function getMacro($name) /** * Dynamically handle calls into the query instance. * - * @param string $method - * @param array $parameters + * @param string $method + * @param array $parameters * @return mixed */ public function __call($method, $parameters) { if ($method === 'macro') { $this->localMacros[$parameters[0]] = $parameters[1]; - - return; + return null; } if (isset($this->localMacros[$method])) { array_unshift($parameters, $this); - return $this->localMacros[$method](...$parameters); } @@ -910,11 +916,11 @@ public function __call($method, $parameters) return call_user_func_array(static::$macros[$method], $parameters); } - if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { + if (method_exists($this->model, $scope = 'scope' . ucfirst($method))) { return $this->callScope([$this->model, $scope], $parameters); } - if (in_array($method, $this->passthru)) { + if (in_array($method, $this->passthru, true)) { return $this->toBase()->{$method}(...$parameters); } @@ -926,8 +932,8 @@ public function __call($method, $parameters) /** * Dynamically handle calls into the query instance. * - * @param string $method - * @param array $parameters + * @param string $method + * @param array $parameters * @return mixed * * @throws \BadMethodCallException @@ -936,8 +942,7 @@ public static function __callStatic($method, $parameters) { if ($method === 'macro') { static::$macros[$parameters[0]] = $parameters[1]; - - return; + return null; } if (!isset(static::$macros[$method])) { diff --git a/src/Database/Eloquent/Collection.php b/src/Database/Eloquent/Collection.php index 7ad4f2b..49a3e89 100644 --- a/src/Database/Eloquent/Collection.php +++ b/src/Database/Eloquent/Collection.php @@ -14,7 +14,7 @@ class Collection extends \Illuminate\Database\Eloquent\Collection * * @param mixed $key * @param mixed $default - * @return \Illuminate\Database\Eloquent\Model|static + * @return Model|static */ public function find($key, $default = null) { diff --git a/src/Database/Eloquent/Concerns/Common.php b/src/Database/Eloquent/Concerns/Common.php index 4ba18dc..70d93d6 100644 --- a/src/Database/Eloquent/Concerns/Common.php +++ b/src/Database/Eloquent/Concerns/Common.php @@ -1,5 +1,7 @@ $value) { - ksort($value); - $values[$key] = $value; - } + foreach ($values as $key => &$value) { + ksort($value); } return $this->connection->insert( @@ -146,6 +144,9 @@ public function insert(array $values): bool ); } + /** + * @return Connection + */ public function getConnection(): Connection { return $this->connection; diff --git a/src/Database/Query/Pdo.php b/src/Database/Query/Pdo.php index 304f7fe..d23b8aa 100644 --- a/src/Database/Query/Pdo.php +++ b/src/Database/Query/Pdo.php @@ -1,5 +1,7 @@ connection = new Connection([ 'host' => 'localhost', 'port' => '8123', 'database' => 'default', ]); + } + + /** + * @return void + */ + public function testQuery(): void + { + self::assertInstanceOf(Builder::class, $this->connection->query()); + } + + /** + * @return void + * @throws ClientException + */ + public function testSystemEvents(): void + { + self::assertIsNumeric( + $this->connection->query() + ->table('system.events') + ->count() + ); + } + + /** + * @return void + * @throws ClientException + */ + public function testMyDatabase(): void + { + $result = $this->connection->statement('CREATE DATABASE IF NOT EXISTS tests'); + self::assertTrue($result); + + $result = $this->connection->statement('CREATE TABLE IF NOT EXISTS tests.dt +( + `timestamp` DateTime(\'Europe/Moscow\'), + `event_id` UInt8 +) +ENGINE = TinyLog;'); + + self::assertTrue($result); + + $result = $this->connection->statement('CREATE DATABASE IF NOT EXISTS tests'); + self::assertTrue($result); + + $result = $this->connection->statement('TRUNCATE tests.dt'); + self::assertTrue($result); + + $values = [ + ['timestamp' => '2019-01-01 00:00:00', 'event_id' => 1], + ['event_id' => 2, 'timestamp' => '2020-01-01 00:00:00'], + ['event_id' => 3, 'timestamp' => 1546300800], + ]; + $this->connection->query() + ->table('tests.dt') + ->insert($values) + ; + + self::assertEquals(3, $this->connection->query()->table('tests.dt')->count()); + + $result = $this->connection->statement('DROP TABLE IF EXISTS tests.dt'); + self::assertTrue($result); - self::assertInstanceOf(Builder::class, $connection->query()); + $result = $this->connection->statement('DROP DATABASE IF EXISTS tests'); + self::assertTrue($result); } } diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index c715dfe..dbc149e 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -95,28 +95,37 @@ public function testInsert(): void $this->faker()->randomLetter => $this->faker()->randomDigit, $this->faker()->numerify('column_#') => $this->faker()->randomLetter, ]; - $inserted = [$insertedRow]; - ksort($insertedRow); - $values = collect($insertedRow)->values()->toArray(); + \ksort($insertedRow); + $inserted = [$insertedRow]; $generatedSql = sprintf( - 'INSERT INTO `%s` (%s) FORMAT %s (\'%s\', %d, %d)', + 'INSERT INTO `%s` (%s) FORMAT %s (%s)', $this->builder->getFrom()->getTable(), collect($insertedRow) ->keys() - ->sort() ->map(function (string $columnName) { return sprintf('`%s`', $columnName); }) ->implode(', '), Format::VALUES, - ...$values + collect($insertedRow) + ->values() + ->map(function ($value) { + if (is_numeric($value)) { + return $value; + } + + return sprintf('\'%s\'', $value); + }) + ->implode(', ') ); + $values = collect($insertedRow)->values()->toArray(); $this->connection ->shouldReceive('insert') ->withArgs([$generatedSql, $values]) - ->andReturn(true); + ->andReturn(true) + ; self::assertTrue($this->builder->insert($inserted)); } From e4765ef3924dbb950496aba031a15bfc0d1f81c9 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 24 Sep 2020 22:48:40 +0300 Subject: [PATCH 19/69] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 438c643..14153aa 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Eloquent model for ClickHouse ## Prerequisites -- php 7.1 +- php 7.2 - clickhouse server ## Installation @@ -97,3 +97,9 @@ Payment::select(raw('count() AS cnt'), 'payment_system') - Model::with() method - relations + + +--- +Supported by + +[![Supported by JetBrains](https://cdn.rawgit.com/bavix/development-through/46475b4b/jetbrains.svg)](https://www.jetbrains.com/) From ab45775e684aab04042033c52625b88ebdb7a155 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 24 Sep 2020 22:57:14 +0300 Subject: [PATCH 20/69] Update README.md --- README.md | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 14153aa..768e02d 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,30 @@ -# laravel-clickhouse +# Laravel Clickhouse + [![Build Status](https://travis-ci.org/bavix/laravel-clickhouse.svg?branch=master)](https://travis-ci.org/bavix/laravel-clickhouse) -[![StyleCI](https://styleci.io/repos/112756298/shield?branch=master)](https://styleci.io/repos/112756298) +[![StyleCI](https://styleci.io/repos/269384604/shield?branch=master)](https://styleci.io/repos/269384604) [![Coverage Status](https://coveralls.io/repos/github/bavix/laravel-clickhouse/badge.svg)](https://coveralls.io/github/bavix/laravel-clickhouse) -Eloquent model for ClickHouse +[![Package Rank](https://phppackages.org/p/bavix/laravel-clickhouse/badge/rank.svg)](https://packagist.org/packages/bavix/laravel-clickhouse) +[![Latest Stable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/stable)](https://packagist.org/packages/bavix/laravel-clickhouse) +[![Latest Unstable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/unstable)](https://packagist.org/packages/bavix/laravel-clickhouse) +[![License](https://poser.pugx.org/bavix/laravel-clickhouse/license)](https://packagist.org/packages/bavix/laravel-clickhouse) +[![composer.lock](https://poser.pugx.org/bavix/laravel-clickhouse/composerlock)](https://packagist.org/packages/bavix/laravel-clickhouse) + +Laravel Clickhouse - Eloquent model for ClickHouse. + +* **Vendor**: bavix +* **Package**: Laravel Clickhouse +* **Version**: [![Latest Stable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/stable)](https://packagist.org/packages/bavix/laravel-clickhouse) +* **Laravel Version**: `6.x`, `7.x`, `8.x` +* **PHP Version**: 7.2+ +* **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-clickhouse` -## Prerequisites + +## System requirements - php 7.2 - clickhouse server -## Installation +## Get started ```sh $ composer require bavix/laravel-clickhouse ``` @@ -18,6 +33,7 @@ Then add the code above into your config/app.php file providers section ```php Bavix\LaravelClickHouse\ClickHouseServiceProvider::class, ``` + And add new connection into your config/database.php file. Something like this: ```php 'connections' => [ @@ -35,6 +51,7 @@ And add new connection into your config/database.php file. Something like this: ] ] ``` + Or like this, if clickhouse runs in cluster ```php 'connections' => [ @@ -92,13 +109,6 @@ Payment::select(raw('count() AS cnt'), 'payment_system') ``` -## Roadmap -- more tests -- Model::with() method -- relations - - - --- Supported by From 596378a8ff245cc5e23119a5af796024470ec2ea Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 24 Sep 2020 19:57:45 +0000 Subject: [PATCH 21/69] Apply fixes from StyleCI --- src/ClickHouseServiceProvider.php | 7 +- src/Database/Connection.php | 2 +- src/Database/Eloquent/Builder.php | 153 +++++++++++------- src/Database/Eloquent/Collection.php | 17 +- src/Database/Eloquent/Concerns/Common.php | 3 +- src/Database/Eloquent/Model.php | 141 +++++++++------- src/Database/Query/Builder.php | 13 +- src/Database/Query/Pdo.php | 1 + tests/EloquentModelCastingTest.php | 20 +-- tests/EloquentModelWithTest.php | 2 +- tests/Helpers.php | 2 +- tests/Unit/Database/ConnectionTest.php | 16 +- tests/Unit/Database/Eloquent/BuilderTest.php | 38 ++--- .../Unit/Database/Eloquent/CollectionTest.php | 18 ++- tests/Unit/Database/Eloquent/ModelTest.php | 10 +- tests/Unit/Database/Query/BuilderTest.php | 15 +- 16 files changed, 266 insertions(+), 192 deletions(-) diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index 12eadbc..25bdbac 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -4,16 +4,17 @@ namespace Bavix\LaravelClickHouse; -use Illuminate\Database\DatabaseManager; -use Illuminate\Support\ServiceProvider; use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Eloquent\Model; +use Illuminate\Database\DatabaseManager; +use Illuminate\Support\ServiceProvider; class ClickHouseServiceProvider extends ServiceProvider { /** - * @return void * @throws + * + * @return void */ public function boot(): void { diff --git a/src/Database/Connection.php b/src/Database/Connection.php index 9002aac..91c793b 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -4,9 +4,9 @@ namespace Bavix\LaravelClickHouse\Database; +use Bavix\LaravelClickHouse\Database\Query\Builder; use Bavix\LaravelClickHouse\Database\Query\Pdo; use Tinderbox\ClickhouseBuilder\Query\Grammar; -use Bavix\LaravelClickHouse\Database\Query\Builder; class Connection extends \Tinderbox\ClickhouseBuilder\Integrations\Laravel\Connection { diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index a38774a..a0d7620 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -4,19 +4,19 @@ namespace Bavix\LaravelClickHouse\Database\Eloquent; -use Closure; use BadMethodCallException; +use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Closure; use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Database\Eloquent\Scope; -use Illuminate\Support\Arr; -use Illuminate\Support\Str; -use Illuminate\Pagination\Paginator; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\Concerns\BuildsQueries; -use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\RelationNotFoundException; -use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Database\Eloquent\Scope; +use Illuminate\Pagination\Paginator; +use Illuminate\Support\Arr; +use Illuminate\Support\Str; use Tinderbox\Clickhouse\Exceptions\ClientException; /** @@ -95,12 +95,14 @@ public function __construct(QueryBuilder $query) * Add a where clause on the primary key to the query. * * @param mixed $id + * * @return $this */ public function whereKey($id): self { if (is_array($id) || $id instanceof Arrayable) { $this->query->whereIn($this->model->getQualifiedKeyName(), $id); + return $this; } @@ -111,12 +113,14 @@ public function whereKey($id): self * Add a where clause on the primary key to the query. * * @param mixed $id + * * @return $this */ public function whereKeyNot($id): self { if (is_array($id) || $id instanceof Arrayable) { $this->query->whereNotIn($this->model->getQualifiedKeyName(), $id); + return $this; } @@ -127,9 +131,10 @@ public function whereKeyNot($id): self * Add a basic where clause to the query. * * @param string|array|\Closure $column - * @param string $operator - * @param mixed $value - * @param string $boolean + * @param string $operator + * @param mixed $value + * @param string $boolean + * * @return $this */ public function where($column, $operator = null, $value = null, string $boolean = 'AND'): self @@ -150,8 +155,9 @@ public function where($column, $operator = null, $value = null, string $boolean * Add an "or where" clause to the query. * * @param \Closure|array|string $column - * @param string $operator - * @param mixed $value + * @param string $operator + * @param mixed $value + * * @return $this */ public function orWhere($column, $operator = null, $value = null): self @@ -163,6 +169,7 @@ public function orWhere($column, $operator = null, $value = null): self * Create a collection of models from plain arrays. * * @param iterable $items + * * @return Collection */ public function hydrate(iterable $items): Collection @@ -180,7 +187,8 @@ public function hydrate(iterable $items): Collection * Create a collection of models from a raw query. * * @param string $query - * @param array $bindings + * @param array $bindings + * * @return Collection */ public function fromQuery($query, $bindings = []): Collection @@ -194,6 +202,7 @@ public function fromQuery($query, $bindings = []): Collection * Find a model by its primary key. * * @param mixed $id + * * @return Model|Collection|static[]|static|null */ public function find($id) @@ -209,6 +218,7 @@ public function find($id) * Find multiple models by their primary keys. * * @param \Illuminate\Contracts\Support\Arrayable|array $ids + * * @return Collection */ public function findMany($ids): Collection @@ -224,9 +234,10 @@ public function findMany($ids): Collection * Find a model by its primary key or throw an exception. * * @param mixed $id - * @return Model|Collection * * @throws ModelNotFoundException + * + * @return Model|Collection */ public function findOrFail($id) { @@ -241,17 +252,18 @@ public function findOrFail($id) return $result; } - throw (new ModelNotFoundException)->setModel( - get_class($this->model), $id + throw (new ModelNotFoundException())->setModel( + get_class($this->model), + $id ); } /** * Execute the query and get the first result or throw an exception. * - * @return Model|null - * * @throws ModelNotFoundException + * + * @return Model|null */ public function firstOrFail(): ?Model { @@ -260,9 +272,8 @@ public function firstOrFail(): ?Model */ $model = $this->first(); if ($model === null) { - throw (new ModelNotFoundException) - ->setModel(get_class($this->model)) - ; + throw (new ModelNotFoundException()) + ->setModel(get_class($this->model)); } return $model; @@ -271,8 +282,9 @@ public function firstOrFail(): ?Model /** * Execute the query as a "select" statement. * - * @return Collection * @throws ClientException + * + * @return Collection */ public function get(): Collection { @@ -291,8 +303,9 @@ public function get(): Collection /** * Get the hydrated models without eager loading. * - * @return Model[] * @throws ClientException + * + * @return Model[] */ public function getModels(): array { @@ -305,6 +318,7 @@ public function getModels(): array * Eager load the relationships for the models. * * @param array $models + * * @return array */ public function eagerLoadRelations(array $models): array @@ -324,9 +338,10 @@ public function eagerLoadRelations(array $models): array /** * Eagerly load the relationship on a set of models. * - * @param array $models - * @param string $name + * @param array $models + * @param string $name * @param \Closure $constraints + * * @return array */ protected function eagerLoadRelation(array $models, string $name, Closure $constraints): array @@ -354,6 +369,7 @@ protected function eagerLoadRelation(array $models, string $name, Closure $const * Get the relation instance for the given relation name. * * @param string $name + * * @return Relation */ public function getRelation(string $name): Relation @@ -385,6 +401,7 @@ public function getRelation(string $name): Relation * Get the deeply nested relations for a given top-level relation. * * @param string $relation + * * @return array */ protected function relationsNestedUnder(string $relation): array @@ -396,7 +413,7 @@ protected function relationsNestedUnder(string $relation): array // that start with the given top relations and adds them to our arrays. foreach ($this->eagerLoad as $name => $constraints) { if ($this->isNestedUnder($relation, $name)) { - $nested[substr($name, strlen($relation . '.'))] = $constraints; + $nested[substr($name, strlen($relation.'.'))] = $constraints; } } @@ -408,20 +425,22 @@ protected function relationsNestedUnder(string $relation): array * * @param string $relation * @param string $name + * * @return bool */ protected function isNestedUnder(string $relation, string $name): bool { - return Str::contains($name, '.') && Str::startsWith($name, $relation . '.'); + return Str::contains($name, '.') && Str::startsWith($name, $relation.'.'); } /** * Chunk the results of a query by comparing numeric IDs. * - * @param int $count - * @param callable $callback - * @param null $column + * @param int $count + * @param callable $callback + * @param null $column * @param string|null $alias + * * @return bool */ public function chunkById(int $count, callable $callback, $column = null, $alias = null): bool @@ -438,7 +457,7 @@ public function chunkById(int $count, callable $callback, $column = null, $alias // we will call the callback with the current chunk of these results here. $results = $clone->forPageAfterId($count, $lastId, $column)->get(); - $countResults = (int)$results->count(); + $countResults = (int) $results->count(); if (!$countResults) { break; @@ -462,8 +481,9 @@ public function chunkById(int $count, callable $callback, $column = null, $alias /** * Get an array with the values of a given column. * - * @param string $column + * @param string $column * @param string|null $key + * * @return \Illuminate\Support\Collection */ public function pluck(string $column, $key = null): \Illuminate\Support\Collection @@ -488,11 +508,11 @@ public function pluck(string $column, $key = null): \Illuminate\Support\Collecti * Paginate the given query. * * @param int|null $perPage - * @param array $columns - * @param string $pageName + * @param array $columns + * @param string $pageName * @param int|null $page - * @return LengthAwarePaginator * + * @return LengthAwarePaginator */ public function paginate(?int $perPage = null, $columns = ['*'], $pageName = 'page', $page = null): LengthAwarePaginator { @@ -503,7 +523,7 @@ public function paginate(?int $perPage = null, $columns = ['*'], $pageName = 'pa : $this->model->newCollection(); return $this->paginator($results, $total, $perPage, $page, [ - 'path' => Paginator::resolveCurrentPath(), + 'path' => Paginator::resolveCurrentPath(), 'pageName' => $pageName, ]); } @@ -512,11 +532,13 @@ public function paginate(?int $perPage = null, $columns = ['*'], $pageName = 'pa * Paginate the given query into a simple paginator. * * @param int|null $perPage - * @param array $columns - * @param string $pageName + * @param array $columns + * @param string $pageName * @param int|null $page - * @return \Illuminate\Contracts\Pagination\Paginator + * * @throws ClientException + * + * @return \Illuminate\Contracts\Pagination\Paginator */ public function simplePaginate(?int $perPage = null, $columns = ['*'], $pageName = 'page', $page = null): \Illuminate\Contracts\Pagination\Paginator { @@ -530,7 +552,7 @@ public function simplePaginate(?int $perPage = null, $columns = ['*'], $pageName $this->skip(($page - 1) * $perPage)->take($perPage + 1); return $this->simplePaginator($this->get($columns), $perPage, $page, [ - 'path' => Paginator::resolveCurrentPath(), + 'path' => Paginator::resolveCurrentPath(), 'pageName' => $pageName, ]); } @@ -539,6 +561,7 @@ public function simplePaginate(?int $perPage = null, $columns = ['*'], $pageName * Call the given local model scopes. * * @param array $scopes + * * @return mixed */ public function scopes(array $scopes) @@ -557,8 +580,8 @@ public function scopes(array $scopes) // care of grouping the "wheres" properly so the logical order doesn't get // messed up when adding scopes. Then we'll return back out the builder. $builder = $builder->callScope( - [$this->model, 'scope' . ucfirst($scope)], - (array)$parameters + [$this->model, 'scope'.ucfirst($scope)], + (array) $parameters ); } @@ -607,7 +630,8 @@ public function applyScopes() * Apply the given scope on the current builder instance. * * @param callable $scope - * @param array $parameters + * @param array $parameters + * * @return mixed */ protected function callScope(callable $scope, $parameters = []) @@ -624,7 +648,7 @@ protected function callScope(callable $scope, $parameters = []) $result = $scope(...array_values($parameters)) ?? $this; - if (count((array)$query->getWheres()) > $originalWhereCount) { + if (count((array) $query->getWheres()) > $originalWhereCount) { $this->addNewWheresWithinGroup($query, $originalWhereCount); } @@ -635,7 +659,8 @@ protected function callScope(callable $scope, $parameters = []) * Nest where conditions by slicing them at the given where count. * * @param \Illuminate\Database\Query\Builder $query - * @param int $originalWhereCount + * @param int $originalWhereCount + * * @return void */ protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCount) @@ -648,11 +673,13 @@ protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCo $query->wheres = []; $this->groupWhereSliceForScope( - $query, array_slice($allWheres, 0, $originalWhereCount) + $query, + array_slice($allWheres, 0, $originalWhereCount) ); $this->groupWhereSliceForScope( - $query, array_slice($allWheres, $originalWhereCount) + $query, + array_slice($allWheres, $originalWhereCount) ); } @@ -660,7 +687,8 @@ protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCo * Slice where conditions at the given offset and add them to the query as a nested condition. * * @param \Illuminate\Database\Query\Builder $query - * @param array $whereSlice + * @param array $whereSlice + * * @return void */ protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) @@ -672,7 +700,8 @@ protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) // we don't add any unnecessary nesting thus keeping the query clean. if ($whereBooleans->contains('or')) { $query->wheres[] = $this->createNestedWhere( - $whereSlice, $whereBooleans->first() + $whereSlice, + $whereBooleans->first() ); } else { $query->wheres = array_merge($query->wheres, $whereSlice); @@ -682,8 +711,9 @@ protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) /** * Create a where array with nested where conditions. * - * @param array $whereSlice + * @param array $whereSlice * @param string $boolean + * * @return array */ protected function createNestedWhere($whereSlice, $boolean = 'and') @@ -699,6 +729,7 @@ protected function createNestedWhere($whereSlice, $boolean = 'and') * Set the relationships that should be eager loaded. * * @param mixed $relations + * * @return $this */ public function with($relations) @@ -714,6 +745,7 @@ public function with($relations) * Prevent the specified relations from being eager loaded. * * @param mixed $relations + * * @return $this */ public function without($relations) @@ -729,6 +761,7 @@ public function without($relations) * Create a new instance of the model being queried. * * @param array $attributes + * * @return Model */ public function newModelInstance($attributes = []) @@ -742,6 +775,7 @@ public function newModelInstance($attributes = []) * Parse a list of relations into individuals. * * @param array $relations + * * @return array */ protected function parseWithRelations(array $relations) @@ -780,6 +814,7 @@ function () { * Create a constraint to select the given columns for the relation. * * @param string $name + * * @return array */ protected function createSelectWithConstraint($name) @@ -796,7 +831,8 @@ function ($query) use ($name) { * Parse the nested relationships in a relation. * * @param string $name - * @param array $results + * @param array $results + * * @return array */ protected function addNestedWiths($name, $results) @@ -855,6 +891,7 @@ public function getEagerLoads() * Set the relationships being eagerly loaded. * * @param array $eagerLoad + * * @return $this */ public function setEagerLoads(array $eagerLoad) @@ -882,6 +919,7 @@ public function setModel(Model $model) * Get the given macro by name. * * @param string $name + * * @return \Closure */ public function getMacro($name) @@ -893,18 +931,21 @@ public function getMacro($name) * Dynamically handle calls into the query instance. * * @param string $method - * @param array $parameters + * @param array $parameters + * * @return mixed */ public function __call($method, $parameters) { if ($method === 'macro') { $this->localMacros[$parameters[0]] = $parameters[1]; + return null; } if (isset($this->localMacros[$method])) { array_unshift($parameters, $this); + return $this->localMacros[$method](...$parameters); } @@ -916,7 +957,7 @@ public function __call($method, $parameters) return call_user_func_array(static::$macros[$method], $parameters); } - if (method_exists($this->model, $scope = 'scope' . ucfirst($method))) { + if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { return $this->callScope([$this->model, $scope], $parameters); } @@ -933,15 +974,17 @@ public function __call($method, $parameters) * Dynamically handle calls into the query instance. * * @param string $method - * @param array $parameters - * @return mixed + * @param array $parameters * * @throws \BadMethodCallException + * + * @return mixed */ public static function __callStatic($method, $parameters) { if ($method === 'macro') { static::$macros[$parameters[0]] = $parameters[1]; + return null; } diff --git a/src/Database/Eloquent/Collection.php b/src/Database/Eloquent/Collection.php index 49a3e89..96a303d 100644 --- a/src/Database/Eloquent/Collection.php +++ b/src/Database/Eloquent/Collection.php @@ -12,8 +12,9 @@ class Collection extends \Illuminate\Database\Eloquent\Collection /** * Find a model in the collection by key. * - * @param mixed $key - * @param mixed $default + * @param mixed $key + * @param mixed $default + * * @return Model|static */ public function find($key, $default = null) @@ -24,7 +25,7 @@ public function find($key, $default = null) if (is_array($key)) { if ($this->isEmpty()) { - return new static; + return new static(); } return $this->whereIn($this->first()->getKeyName(), $key); @@ -38,9 +39,10 @@ public function find($key, $default = null) /** * Determine if a key exists in the collection. * - * @param mixed $key - * @param mixed $operator - * @param mixed $value + * @param mixed $key + * @param mixed $operator + * @param mixed $value + * * @return bool */ public function contains($key, $operator = null, $value = null): bool @@ -57,7 +59,8 @@ public function contains($key, $operator = null, $value = null): bool /** * Run a map over each of the items. * - * @param callable $callback + * @param callable $callback + * * @return SupportCollection|static */ public function map(callable $callback) diff --git a/src/Database/Eloquent/Concerns/Common.php b/src/Database/Eloquent/Concerns/Common.php index 70d93d6..20a2dd8 100644 --- a/src/Database/Eloquent/Concerns/Common.php +++ b/src/Database/Eloquent/Concerns/Common.php @@ -6,16 +6,15 @@ trait Common { - /** * Save the model to the database. * * @param array $options + * * @return bool */ public function save(array $options = []): bool { return static::insert($this->toArray()); } - } diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index 2ab2855..afe22b3 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -5,34 +5,33 @@ namespace Bavix\LaravelClickHouse\Database\Eloquent; use ArrayAccess; -use JsonSerializable; -use Illuminate\Support\Str; -use Illuminate\Contracts\Support\Jsonable; -use Illuminate\Contracts\Support\Arrayable; -use Tinderbox\ClickhouseBuilder\Query\Grammar; use Bavix\LaravelClickHouse\Database\Connection; +use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Illuminate\Contracts\Support\Arrayable; +use Illuminate\Contracts\Support\Jsonable; use Illuminate\Database\ConnectionResolverInterface; +use Illuminate\Database\ConnectionResolverInterface as Resolver; +use Illuminate\Database\Eloquent\Concerns\GuardsAttributes; use Illuminate\Database\Eloquent\Concerns\HasEvents; +use Illuminate\Database\Eloquent\Concerns\HasRelationships; +use Illuminate\Database\Eloquent\Concerns\HidesAttributes; use Illuminate\Database\Eloquent\JsonEncodingException; use Illuminate\Database\Eloquent\MassAssignmentException; -use Illuminate\Database\Eloquent\Concerns\HidesAttributes; -use Illuminate\Database\Eloquent\Concerns\GuardsAttributes; -use Illuminate\Database\Eloquent\Concerns\HasRelationships; -use Illuminate\Database\ConnectionResolverInterface as Resolver; -use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Illuminate\Support\Str; +use JsonSerializable; +use Tinderbox\ClickhouseBuilder\Query\Grammar; /** - * Class Model - * @package Bavix\LaravelClickHouse\Database\Eloquent + * Class Model. */ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable { - use Concerns\HasAttributes, - Concerns\Common, - HasEvents, - HasRelationships, - HidesAttributes, - GuardsAttributes; + use Concerns\HasAttributes; + use Concerns\Common; + use HasEvents; + use HasRelationships; + use HidesAttributes; + use GuardsAttributes; /** * The connection name for the model. @@ -114,7 +113,8 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab /** * Create a new Eloquent model instance. * - * @param array $attributes + * @param array $attributes + * * @return void */ public function __construct(array $attributes = []) @@ -183,10 +183,11 @@ public static function clearBootedModels() /** * Fill the model with an array of attributes. * - * @param array $attributes - * @return $this + * @param array $attributes * * @throws \Illuminate\Database\Eloquent\MassAssignmentException + * + * @return $this */ public function fill(array $attributes) { @@ -211,7 +212,8 @@ public function fill(array $attributes) /** * Fill the model with an array of attributes. Force mass assignment. * - * @param array $attributes + * @param array $attributes + * * @return $this */ public function forceFill(array $attributes) @@ -224,7 +226,8 @@ public function forceFill(array $attributes) /** * Remove the table name from a given key. * - * @param string $key + * @param string $key + * * @return string */ protected function removeTableFromKey($key) @@ -235,8 +238,9 @@ protected function removeTableFromKey($key) /** * Create a new instance of the given model. * - * @param array $attributes - * @param bool $exists + * @param array $attributes + * @param bool $exists + * * @return static */ public function newInstance($attributes = [], $exists = false) @@ -258,8 +262,9 @@ public function newInstance($attributes = [], $exists = false) /** * Create a new model instance that is existing. * - * @param array $attributes - * @param string|null $connection + * @param array $attributes + * @param string|null $connection + * * @return static */ public function newFromBuilder(array $attributes = [], string $connection = null) @@ -282,25 +287,26 @@ public function newFromBuilder(array $attributes = [], string $connection = null */ public static function all() { - return (new static)->newQuery()->get(); + return (new static())->newQuery()->get(); } /** * Begin querying a model with eager loading. * - * @param array|string $relations + * @param array|string $relations + * * @return Builder|static */ public static function with($relations) { - return (new static)->newQuery()->with( + return (new static())->newQuery()->with( is_string($relations) ? func_get_args() : $relations ); } public static function query(): Builder { - return (new static)->newQuery(); + return (new static())->newQuery(); } public function newQuery(): Builder @@ -340,7 +346,8 @@ protected function newBaseQueryBuilder(): QueryBuilder /** * Create a new Eloquent Collection instance. * - * @param array $models + * @param array $models + * * @return Collection */ public function newCollection(array $models = []): Collection @@ -361,10 +368,11 @@ public function toArray(): array /** * Convert the model instance to JSON. * - * @param int $options - * @return string + * @param int $options * * @throws \Illuminate\Database\Eloquent\JsonEncodingException + * + * @return string */ public function toJson($options = 0): string { @@ -410,7 +418,8 @@ public function getConnectionName(): string /** * Set the connection associated with the model. * - * @param string $name + * @param string $name + * * @return $this */ public function setConnection(string $name) @@ -423,7 +432,8 @@ public function setConnection(string $name) /** * Resolve a connection instance. * - * @param string|null $connection + * @param string|null $connection + * * @return Connection|\Illuminate\Database\ConnectionInterface */ public static function resolveConnection(string $connection = null) @@ -444,7 +454,8 @@ public static function getConnectionResolver(): ConnectionResolverInterface /** * Set the connection resolver instance. * - * @param \Illuminate\Database\ConnectionResolverInterface $resolver + * @param \Illuminate\Database\ConnectionResolverInterface $resolver + * * @return void */ public static function setConnectionResolver(Resolver $resolver): void @@ -461,7 +472,9 @@ public function getTable(): string { if (!isset($this->table)) { $this->setTable(str_replace( - '\\', '', Str::snake(Str::plural(class_basename($this))) + '\\', + '', + Str::snake(Str::plural(class_basename($this))) )); } @@ -471,7 +484,8 @@ public function getTable(): string /** * Set the table associated with the model. * - * @param string $table + * @param string $table + * * @return $this */ public function setTable(string $table): self @@ -494,7 +508,8 @@ public function getKeyName(): string /** * Set the primary key for the model. * - * @param string $key + * @param string $key + * * @return $this */ public function setKeyName(string $key): self @@ -527,7 +542,8 @@ public function getKeyType(): string /** * Set the data type for the primary key. * - * @param string $type + * @param string $type + * * @return $this */ public function setKeyType(string $type) @@ -570,7 +586,8 @@ public function getPerPage(): int /** * Set the number of models to return per page. * - * @param int $perPage + * @param int $perPage + * * @return $this */ public function setPerPage(int $perPage): self @@ -583,7 +600,8 @@ public function setPerPage(int $perPage): self /** * Dynamically retrieve attributes on the model. * - * @param string $key + * @param string $key + * * @return mixed */ public function __get($key) @@ -594,8 +612,9 @@ public function __get($key) /** * Dynamically set attributes on the model. * - * @param string $key - * @param mixed $value + * @param string $key + * @param mixed $value + * * @return void */ public function __set($key, $value) @@ -606,7 +625,8 @@ public function __set($key, $value) /** * Determine if the given attribute exists. * - * @param mixed $offset + * @param mixed $offset + * * @return bool */ public function offsetExists($offset): bool @@ -617,7 +637,8 @@ public function offsetExists($offset): bool /** * Get the value for a given offset. * - * @param mixed $offset + * @param mixed $offset + * * @return mixed */ public function offsetGet($offset) @@ -628,8 +649,9 @@ public function offsetGet($offset) /** * Set the value for a given offset. * - * @param mixed $offset - * @param mixed $value + * @param mixed $offset + * @param mixed $value + * * @return void */ public function offsetSet($offset, $value): void @@ -640,7 +662,8 @@ public function offsetSet($offset, $value): void /** * Unset the value for a given offset. * - * @param mixed $offset + * @param mixed $offset + * * @return void */ public function offsetUnset($offset): void @@ -651,7 +674,8 @@ public function offsetUnset($offset): void /** * Determine if an attribute or relation exists on the model. * - * @param string $key + * @param string $key + * * @return bool */ public function __isset($key) @@ -662,7 +686,8 @@ public function __isset($key) /** * Unset an attribute on the model. * - * @param string $key + * @param string $key + * * @return void */ public function __unset($key) @@ -673,8 +698,9 @@ public function __unset($key) /** * Handle dynamic method calls into the model. * - * @param string $method - * @param array $parameters + * @param string $method + * @param array $parameters + * * @return mixed */ public function __call($method, $parameters) @@ -685,12 +711,13 @@ public function __call($method, $parameters) /** * Handle dynamic static method calls into the method. * - * @param string $method - * @param array $parameters + * @param string $method + * @param array $parameters + * * @return mixed */ public static function __callStatic($method, $parameters) { - return (new static)->$method(...$parameters); + return (new static())->$method(...$parameters); } } diff --git a/src/Database/Query/Builder.php b/src/Database/Query/Builder.php index 9a6f185..b2645bb 100644 --- a/src/Database/Query/Builder.php +++ b/src/Database/Query/Builder.php @@ -4,14 +4,13 @@ namespace Bavix\LaravelClickHouse\Database\Query; +use Bavix\LaravelClickHouse\Database\Connection; use Illuminate\Support\Arr; use Illuminate\Support\Collection; -use Tinderbox\Clickhouse\Common\Format; use Illuminate\Support\Traits\Macroable; -use Tinderbox\ClickhouseBuilder\Exceptions\GrammarException; -use Tinderbox\ClickhouseBuilder\Query\Grammar; +use Tinderbox\Clickhouse\Common\Format; use Tinderbox\ClickhouseBuilder\Query\BaseBuilder; -use Bavix\LaravelClickHouse\Database\Connection; +use Tinderbox\ClickhouseBuilder\Query\Grammar; class Builder extends BaseBuilder { @@ -94,10 +93,10 @@ public function newQuery(): self /** * Insert in table data from files. * - * @param array $columns - * @param array $files + * @param array $columns + * @param array $files * @param string $format - * @param int $concurrency + * @param int $concurrency * * @throws \Tinderbox\Clickhouse\Exceptions\ClientException * diff --git a/src/Database/Query/Pdo.php b/src/Database/Query/Pdo.php index d23b8aa..417dfd0 100644 --- a/src/Database/Query/Pdo.php +++ b/src/Database/Query/Pdo.php @@ -8,6 +8,7 @@ class Pdo { /** * @param mixed $binding + * * @return mixed */ public function quote($binding) diff --git a/tests/EloquentModelCastingTest.php b/tests/EloquentModelCastingTest.php index 30845ee..3cd65af 100644 --- a/tests/EloquentModelCastingTest.php +++ b/tests/EloquentModelCastingTest.php @@ -9,16 +9,16 @@ class EloquentModelCastingTest extends EloquentModelTest use Helpers; protected $casts = [ - 'intAttribute' => 'int', - 'floatAttribute' => 'float', - 'stringAttribute' => 'string', - 'boolAttribute' => 'bool', - 'booleanAttribute' => 'boolean', - 'objectAttribute' => 'object', - 'arrayAttribute' => 'array', - 'jsonAttribute' => 'json', - 'dateAttribute' => 'date', - 'datetimeAttribute' => 'datetime', + 'intAttribute' => 'int', + 'floatAttribute' => 'float', + 'stringAttribute' => 'string', + 'boolAttribute' => 'bool', + 'booleanAttribute' => 'boolean', + 'objectAttribute' => 'object', + 'arrayAttribute' => 'array', + 'jsonAttribute' => 'json', + 'dateAttribute' => 'date', + 'datetimeAttribute' => 'datetime', 'timestampAttribute' => 'timestamp', ]; diff --git a/tests/EloquentModelWithTest.php b/tests/EloquentModelWithTest.php index e073e63..7cc8ba8 100644 --- a/tests/EloquentModelWithTest.php +++ b/tests/EloquentModelWithTest.php @@ -4,8 +4,8 @@ namespace Bavix\LaravelClickHouse\Tests; -use Mockery\MockInterface; use Bavix\LaravelClickHouse\Database\Eloquent\Builder; +use Mockery\MockInterface; class EloquentModelWithTest extends EloquentModelTest { diff --git a/tests/Helpers.php b/tests/Helpers.php index 9ebbbca..7273653 100644 --- a/tests/Helpers.php +++ b/tests/Helpers.php @@ -4,9 +4,9 @@ namespace Bavix\LaravelClickHouse\Tests; -use Mockery; use Faker\Factory; use Faker\Generator; +use Mockery; trait Helpers { diff --git a/tests/Unit/Database/ConnectionTest.php b/tests/Unit/Database/ConnectionTest.php index 60ca9dd..225665c 100644 --- a/tests/Unit/Database/ConnectionTest.php +++ b/tests/Unit/Database/ConnectionTest.php @@ -4,14 +4,13 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database; -use PHPUnit\Framework\TestCase; use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Query\Builder; +use PHPUnit\Framework\TestCase; use Tinderbox\Clickhouse\Exceptions\ClientException; class ConnectionTest extends TestCase { - /** * @var Connection */ @@ -24,8 +23,8 @@ public function setUp(): void { parent::setUp(); $this->connection = new Connection([ - 'host' => 'localhost', - 'port' => '8123', + 'host' => 'localhost', + 'port' => '8123', 'database' => 'default', ]); } @@ -39,8 +38,9 @@ public function testQuery(): void } /** - * @return void * @throws ClientException + * + * @return void */ public function testSystemEvents(): void { @@ -52,8 +52,9 @@ public function testSystemEvents(): void } /** - * @return void * @throws ClientException + * + * @return void */ public function testMyDatabase(): void { @@ -82,8 +83,7 @@ public function testMyDatabase(): void ]; $this->connection->query() ->table('tests.dt') - ->insert($values) - ; + ->insert($values); self::assertEquals(3, $this->connection->query()->table('tests.dt')->count()); diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index be952a4..976db31 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -4,21 +4,21 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; -use Mockery\Mock; -use PHPUnit\Framework\TestCase; -use Illuminate\Database\DatabaseManager; -use Tinderbox\ClickhouseBuilder\Query\Tuple; -use Bavix\LaravelClickHouse\Tests\Helpers; -use Tinderbox\ClickhouseBuilder\Query\Grammar; -use Tinderbox\ClickhouseBuilder\Query\Identifier; use Bavix\LaravelClickHouse\Database\Connection; -use Tinderbox\ClickhouseBuilder\Query\Enums\Operator; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Bavix\LaravelClickHouse\Database\Eloquent\Builder; use Bavix\LaravelClickHouse\Database\Eloquent\Collection; +use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\Helpers; +use Illuminate\Database\DatabaseManager; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use Mockery\Mock; +use PHPUnit\Framework\TestCase; +use Tinderbox\ClickhouseBuilder\Query\Enums\Operator; +use Tinderbox\ClickhouseBuilder\Query\Grammar; +use Tinderbox\ClickhouseBuilder\Query\Identifier; +use Tinderbox\ClickhouseBuilder\Query\Tuple; use Tinderbox\ClickhouseBuilder\Query\TwoElementsLogicExpression; -use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; /** * @property Mock|Connection connection @@ -206,18 +206,18 @@ public function testFindOrFail(): void public function testGet(): void { $connectionResultRow = [ - 'id' => $this->faker()->randomDigit, - 'intAttribute' => (string) $this->faker()->randomDigit, - 'floatAttribute' => (string) $this->faker()->randomFloat(2), - 'stringAttribute' => $this->faker()->randomDigit, - 'boolAttribute' => 1, + 'id' => $this->faker()->randomDigit, + 'intAttribute' => (string) $this->faker()->randomDigit, + 'floatAttribute' => (string) $this->faker()->randomFloat(2), + 'stringAttribute' => $this->faker()->randomDigit, + 'boolAttribute' => 1, 'booleanAttribute' => 1, - 'objectAttribute' => json_encode([ + 'objectAttribute' => json_encode([ $this->faker()->word => $this->faker()->randomLetter, ]), - 'arrayAttribute' => json_encode(range(1, 5)), - 'dateAttribute' => now()->toDateTimeString(), - 'datetimeAttribute' => now()->toDateString(), + 'arrayAttribute' => json_encode(range(1, 5)), + 'dateAttribute' => now()->toDateTimeString(), + 'datetimeAttribute' => now()->toDateString(), 'timestampAttribute' => now()->toDateString(), ]; $connectionResultRow['jsonAttribute'] = json_encode($connectionResultRow['arrayAttribute']); diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index f8de44c..bdc4030 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -4,14 +4,14 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; -use Mockery\Mock; -use Carbon\Carbon; -use PHPUnit\Framework\TestCase; -use Illuminate\Database\DatabaseManager; -use Bavix\LaravelClickHouse\Tests\Helpers; use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Eloquent\Collection; use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\Helpers; +use Carbon\Carbon; +use Illuminate\Database\DatabaseManager; +use Mockery\Mock; +use PHPUnit\Framework\TestCase; /** * @property Mock|Connection connection @@ -84,7 +84,7 @@ public function testMapModelToArray(): void $collection = EloquentModelCastingTest::all() ->map(function (EloquentModelCastingTest $model) use ($now) { return [ - 'id' => $model->id, + 'id' => $model->id, 'datetimeAttribute' => $now, ]; }); @@ -101,6 +101,7 @@ public function testMapModelToArray(): void /** * @dataProvider findDataProvider + * * @param $key */ public function testFind($key): void @@ -126,6 +127,7 @@ public function testFind($key): void /** * @dataProvider containsDataProvider + * * @param bool $expected * @param $key * @param null $operator @@ -156,7 +158,7 @@ public function testGet(): void $connectionResult = collect() ->times(5, function (int $id) { return [ - 'id' => $id, + 'id' => $id, 'floatAttribute' => (string) $this->faker()->randomFloat(2), ]; }); @@ -190,7 +192,7 @@ public function findDataProvider(): array return [ [5], [ - tap(new EloquentModelCastingTest, function (EloquentModelCastingTest $model) { + tap(new EloquentModelCastingTest(), function (EloquentModelCastingTest $model) { $model->id = 5; }), ], diff --git a/tests/Unit/Database/Eloquent/ModelTest.php b/tests/Unit/Database/Eloquent/ModelTest.php index 6aa7d5b..2194663 100644 --- a/tests/Unit/Database/Eloquent/ModelTest.php +++ b/tests/Unit/Database/Eloquent/ModelTest.php @@ -4,13 +4,13 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; -use Illuminate\Support\Carbon; -use PHPUnit\Framework\TestCase; -use Bavix\LaravelClickHouse\Tests\Helpers; +use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; use Bavix\LaravelClickHouse\Tests\EloquentModelTest; -use Illuminate\Database\Eloquent\MassAssignmentException; use Bavix\LaravelClickHouse\Tests\EloquentModelWithTest; -use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\Helpers; +use Illuminate\Database\Eloquent\MassAssignmentException; +use Illuminate\Support\Carbon; +use PHPUnit\Framework\TestCase; class ModelTest extends TestCase { diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index dbc149e..3b9e0e4 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -4,12 +4,12 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Query; -use PHPUnit\Framework\TestCase; -use Bavix\LaravelClickHouse\Tests\Helpers; -use Tinderbox\ClickhouseBuilder\Query\Grammar; use Bavix\LaravelClickHouse\Database\Connection; -use Tinderbox\ClickhouseBuilder\Query\Enums\Format; use Bavix\LaravelClickHouse\Database\Query\Builder; +use Bavix\LaravelClickHouse\Tests\Helpers; +use PHPUnit\Framework\TestCase; +use Tinderbox\ClickhouseBuilder\Query\Enums\Format; +use Tinderbox\ClickhouseBuilder\Query\Grammar; /** * @property \Mockery\MockInterface|Connection connection @@ -91,8 +91,8 @@ public function testInsert(): void self::assertFalse($this->builder->insert([])); $insertedRow = [ - $this->faker()->word => $this->faker()->randomDigit, - $this->faker()->randomLetter => $this->faker()->randomDigit, + $this->faker()->word => $this->faker()->randomDigit, + $this->faker()->randomLetter => $this->faker()->randomDigit, $this->faker()->numerify('column_#') => $this->faker()->randomLetter, ]; @@ -124,8 +124,7 @@ public function testInsert(): void $this->connection ->shouldReceive('insert') ->withArgs([$generatedSql, $values]) - ->andReturn(true) - ; + ->andReturn(true); self::assertTrue($this->builder->insert($inserted)); } From fc48a3f2055d24e3d230da706883b543414e725d Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 24 Sep 2020 23:04:51 +0300 Subject: [PATCH 22/69] Update README.md --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 768e02d..39b9efc 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,6 @@ Laravel Clickhouse - Eloquent model for ClickHouse. * **PHP Version**: 7.2+ * **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-clickhouse` - -## System requirements -- php 7.2 -- clickhouse server - ## Get started ```sh $ composer require bavix/laravel-clickhouse From 2fd7b4b3f3d57665228af06d09d3043d4a723cbf Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Mon, 15 Mar 2021 19:47:19 +0300 Subject: [PATCH 23/69] add support php 8 & update readme --- README.md | 8 +++++++- composer.json | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 438c643..38c74b2 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,14 @@ Eloquent model for ClickHouse +> :warning:If you are using php 8 and `the-tinderbox/clickhouse-*` author hasn't added support yet, then connect mine. +> +> composer req bavix/clickhouse-php-client +> +> composer req bavix/clickhouse-builder + ## Prerequisites -- php 7.1 +- php 7.2 - clickhouse server ## Installation diff --git a/composer.json b/composer.json index 6096902..e39d031 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "eloquent" ], "require": { - "php": ">=7.2", + "php": "^7.2|^8.0", "laravel/framework": "^6.0|^7.0|^8.0", "the-tinderbox/clickhouse-builder": "^4.0", "ext-json": "*" From e08b8d070862f4b041e9420e286b23380cbc9a7f Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Mon, 15 Mar 2021 19:49:02 +0300 Subject: [PATCH 24/69] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 19297a0..ca6719b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Laravel Clickhouse - Eloquent model for ClickHouse. * **PHP Version**: 7.2+ * **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-clickhouse` -> :warning:If you are using php 8 and `the-tinderbox/clickhouse-*` author hasn't added support yet, then connect mine. +> :warning: If you are using php 8 and `the-tinderbox/clickhouse-*` author hasn't added support yet, then connect mine. > > composer req bavix/clickhouse-php-client > From 075434b3c817d503f2b14b7459186fab541daf19 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Mon, 15 Mar 2021 19:57:16 +0300 Subject: [PATCH 25/69] add support php8 --- composer.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e39d031..85cc000 100644 --- a/composer.json +++ b/composer.json @@ -15,10 +15,12 @@ "ext-json": "*" }, "require-dev": { - "infection/infection": "0.15.*|0.16.*|0.17.*", + "infection/infection": "~0.15", "phpunit/phpunit": "^8.0|^9.0", "mockery/mockery": "^1.3", - "fzaninotto/faker": "^1.9" + "fakerphp/faker": "^1.9", + "bavix/clickhouse-php-client": "^3.0", + "bavix/clickhouse-builder": "^4.0" }, "autoload": { "psr-4": { From e6739188b0de69e5eb27bc4c76974488bea3140b Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Sun, 16 Oct 2022 22:14:06 +0300 Subject: [PATCH 26/69] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 85cc000..658f634 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ ], "require": { "php": "^7.2|^8.0", - "laravel/framework": "^6.0|^7.0|^8.0", + "laravel/framework": "^6.0|^7.0|^8.0|^9.0", "the-tinderbox/clickhouse-builder": "^4.0", "ext-json": "*" }, From 3761cce80e6294a6e0072185395ee0ef4605a1c3 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Sun, 16 Oct 2022 22:14:56 +0300 Subject: [PATCH 27/69] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca6719b..5a006ce 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Laravel Clickhouse - Eloquent model for ClickHouse. * **Vendor**: bavix * **Package**: Laravel Clickhouse * **Version**: [![Latest Stable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/stable)](https://packagist.org/packages/bavix/laravel-clickhouse) -* **Laravel Version**: `6.x`, `7.x`, `8.x` +* **Laravel Version**: `6.x`, `7.x`, `8.x`, `9.x` * **PHP Version**: 7.2+ * **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-clickhouse` From c86a3a83bc6826b8e4f5ca5038a43eef551e6467 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 27 Oct 2022 21:08:33 +0300 Subject: [PATCH 28/69] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 658f634..b2f0e5f 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "require": { "php": "^7.2|^8.0", "laravel/framework": "^6.0|^7.0|^8.0|^9.0", - "the-tinderbox/clickhouse-builder": "^4.0", + "the-tinderbox/clickhouse-builder": "^4.0|^5.0", "ext-json": "*" }, "require-dev": { From 2154f6ddab75dc374e4a3a8afd4f3e93a598a07a Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 27 Oct 2022 21:10:27 +0300 Subject: [PATCH 29/69] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index 5a006ce..bc4188e 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,6 @@ Laravel Clickhouse - Eloquent model for ClickHouse. * **PHP Version**: 7.2+ * **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-clickhouse` -> :warning: If you are using php 8 and `the-tinderbox/clickhouse-*` author hasn't added support yet, then connect mine. -> -> composer req bavix/clickhouse-php-client -> -> composer req bavix/clickhouse-builder - ## Get started ```sh $ composer require bavix/laravel-clickhouse From 69eb0137e9920e9c58473e93cbb93708e454c192 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 23 Jan 2023 18:52:08 +0300 Subject: [PATCH 30/69] Update composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b2f0e5f..ae53154 100644 --- a/composer.json +++ b/composer.json @@ -10,8 +10,8 @@ ], "require": { "php": "^7.2|^8.0", - "laravel/framework": "^6.0|^7.0|^8.0|^9.0", - "the-tinderbox/clickhouse-builder": "^4.0|^5.0", + "laravel/framework": "^6.0|^7.0|^8.0|^9.0|^10.0", + "the-tinderbox/clickhouse-builder": "^4.0|^5.0|^6.0", "ext-json": "*" }, "require-dev": { From 23836c3e028cf0b19b9058d7eea408462a614540 Mon Sep 17 00:00:00 2001 From: Garrett Mills Date: Tue, 31 Jan 2023 12:53:47 -0600 Subject: [PATCH 31/69] Fix Eloquent\Builder::where to pass along AND/OR When using `Eloquent\Builder::orWhere` with a `Closure`, the generated query would connect the clauses with `AND`. Fix this by passing the `$boolean` connective through to the base query builder. --- src/Database/Eloquent/Builder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index a0d7620..d6df1b2 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -143,7 +143,7 @@ public function where($column, $operator = null, $value = null, string $boolean $this->query->where(function (QueryBuilder $queryBuilder) use ($column) { $eloquentBuilder = $this->model->newEloquentBuilder($queryBuilder); $column($eloquentBuilder); - }); + }, null, null, $boolean); } else { $this->query->where(...func_get_args()); } From aded561c9020c3cccc5e9a9b4b92d465bd782484 Mon Sep 17 00:00:00 2001 From: Eugene Ivanov <93479789+evgeek@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:36:47 +0300 Subject: [PATCH 32/69] Suppress deprecation warning WARNING: Return type of Bavix\LaravelClickHouse\Database\Eloquent\Model::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice --- src/Database/Eloquent/Model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index afe22b3..ad90929 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -641,6 +641,7 @@ public function offsetExists($offset): bool * * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->getAttribute($offset); From 6ee5fd8cba70eb9f7611b49c7775d21b37b0dedc Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Wed, 17 Jan 2024 22:41:03 +0300 Subject: [PATCH 33/69] Create dependabot.yml Signed-off-by: Maxim Babichev --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..fdea7e2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: +- package-ecosystem: composer + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 From 200c0a43747663d06cb49c5f1875cb6a789e8cfd Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Wed, 17 Jan 2024 22:41:49 +0300 Subject: [PATCH 34/69] Create changelog.yml Signed-off-by: Maxim Babichev --- .github/workflows/changelog.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/changelog.yml diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000..80d91e6 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,14 @@ +name: update changelog + +on: + release: + types: [released] + +permissions: {} + +jobs: + changelog: + permissions: + contents: write + secrets: inherit + uses: bavix/.github/.github/workflows/changelog.yml@0.1.6 From a2ed9d221e66dbb160767af194104dc7178a0c33 Mon Sep 17 00:00:00 2001 From: Github bot Date: Wed, 17 Jan 2024 19:42:46 +0000 Subject: [PATCH 35/69] Update changelog.md --- changelog.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..bb0aa30 --- /dev/null +++ b/changelog.md @@ -0,0 +1,62 @@ +# Changelog + +## 2.3.4 - 2024-01-17 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.3...2.3.4 + +## 2.3.3 - 2023-02-21 + +## What's Changed +* Suppress deprecation warning by @evgeek in https://github.com/bavix/laravel-clickhouse/pull/5 +* Fix Eloquent\Builder::where to pass along AND/OR by @glmdev in https://github.com/bavix/laravel-clickhouse/pull/4 + +## New Contributors +* @evgeek made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/5 +* @glmdev made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/4 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.2...2.3.3 + +## 2.3.2 - 2023-01-23 + +Add support laravel 10 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.1...2.3.2 + +## 2.3.1 - 2022-10-27 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.0...2.3.1 + +## 2.3.0 - 2022-10-16 + +add support laravel 9 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.2.0...2.3.0 + +## 2.2.0 - 2021-03-15 + + + +## 2.1.1 - 2021-03-15 + + + +## 2.1.0 - 2020-09-24 + + + +## 2.0.0 - 2020-09-24 + + + +## 1.1.0 - 2020-08-31 + + + +## 1.0.1 - 2020-07-09 + +Add support `laravel/telescope` + +## 1.0.0 - 2020-07-09 + +First version + From 41cc8c089db332b5bdb23c296c27915b958122cf Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 29 Jan 2024 20:38:20 +0300 Subject: [PATCH 36/69] Update README.md Signed-off-by: Maxim Babichev --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index bc4188e..838d9a1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +We switched to the standard mysql/postgres interface from clickhouse. More details here: https://clickhouse.com/docs/en/interfaces/mysql + +--- + # Laravel Clickhouse [![Build Status](https://travis-ci.org/bavix/laravel-clickhouse.svg?branch=master)](https://travis-ci.org/bavix/laravel-clickhouse) From 4cd17c52ace124113dbfbbf1c94f5fdb543b96c4 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 22:21:42 +0300 Subject: [PATCH 37/69] Add support laravel ^11.0 --- .github/workflows/changelog.yml | 2 +- .github/workflows/fixer.yaml | 89 +++++++++++ .github/workflows/phpstan.yaml | 38 +++++ .github/workflows/phpunits.yaml | 146 ++++++++++++++++++ .github/workflows/stale.yml | 14 ++ .gitignore | 10 +- .travis.yml | 32 ---- composer.json | 39 +++-- ecs.php | 31 ++++ phpstan.common.neon | 8 + phpstan.neon | 22 +++ phpunit.xml | 47 +++--- rector.php | 28 ++++ src/ClickHouseServiceProvider.php | 3 + src/Database/Connection.php | 8 +- .../Eloquent/Concerns/HasAttributes.php | 4 +- src/Database/Eloquent/Model.php | 12 ++ src/Database/Query/Pdo.php | 9 +- src/Database/Query/PdoInterface.php | 10 ++ tests/Unit/Database/Eloquent/BuilderTest.php | 8 + .../Unit/Database/Eloquent/CollectionTest.php | 8 + tests/Unit/Database/Query/BuilderTest.php | 10 +- 22 files changed, 496 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/fixer.yaml create mode 100644 .github/workflows/phpstan.yaml create mode 100644 .github/workflows/phpunits.yaml create mode 100644 .github/workflows/stale.yml delete mode 100644 .travis.yml create mode 100644 ecs.php create mode 100644 phpstan.common.neon create mode 100644 phpstan.neon create mode 100644 rector.php create mode 100644 src/Database/Query/PdoInterface.php diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 80d91e6..df3dfd1 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -11,4 +11,4 @@ jobs: permissions: contents: write secrets: inherit - uses: bavix/.github/.github/workflows/changelog.yml@0.1.6 + uses: bavix/.github/.github/workflows/changelog.yml@0.2.4 diff --git a/.github/workflows/fixer.yaml b/.github/workflows/fixer.yaml new file mode 100644 index 0000000..ae0e76b --- /dev/null +++ b/.github/workflows/fixer.yaml @@ -0,0 +1,89 @@ +name: fixer + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + autofix: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + extensions: mbstring, pgsql, mysql, sqlite, redis, memcached, bcmath + coverage: pcov + env: + runner: self-hosted + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run rector-fix + run: composer rector-fix + + - name: Run ecs-fix + run: composer ecs-fix + + - name: Run rector + run: composer rector + + - name: Run ecs + run: composer ecs + + - name: Run parabench + run: composer parabench + + - name: "Check if build has changed" + if: success() + id: has-changes + run: | + echo "stdout<> $GITHUB_OUTPUT + echo "$(git diff --stat)" >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT + + - name: Import GPG key + if: ${{ steps.has-changes.outputs.stdout }} + uses: crazy-max/ghaction-import-gpg@v6 + with: + gpg_private_key: ${{ secrets.GPG_BOT }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + fingerprint: ${{ secrets.GPG_FINGERPRINT }} + git_config_global: true + git_user_signingkey: true + git_commit_gpgsign: true + git_committer_name: Github bot + git_committer_email: bot@babichev.net + + - name: "Commit files" + if: ${{ steps.has-changes.outputs.stdout }} + env: + GH_TOKEN: ${{ secrets.BOT_TOKEN }} + run: | + gh pr checkout ${{ github.event.pull_request.number }} + git commit -S -m "autofix" -a + + - name: "Push changes" + if: ${{ steps.has-changes.outputs.stdout }} + env: + GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }} + run: git push -u origin HEAD \ No newline at end of file diff --git a/.github/workflows/phpstan.yaml b/.github/workflows/phpstan.yaml new file mode 100644 index 0000000..5673e51 --- /dev/null +++ b/.github/workflows/phpstan.yaml @@ -0,0 +1,38 @@ +name: phpstan + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + phpstan: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run phpstan + run: composer phpstan diff --git a/.github/workflows/phpunits.yaml b/.github/workflows/phpunits.yaml new file mode 100644 index 0000000..dcd34eb --- /dev/null +++ b/.github/workflows/phpunits.yaml @@ -0,0 +1,146 @@ +name: phpunits + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + units: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: [8.2, 8.3] + databases: [testing, pgsql, mysql, mariadb] + caches: [array, redis, memcached] + locks: [array, redis, memcached] + + services: + redis: + image: redis + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + ports: + - 6379:6379 + + memcached: + image: memcached + options: >- + --health-cmd "timeout 5 bash -c 'cat < /dev/null > /dev/udp/127.0.0.1/11211'" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + ports: + - 11211:11211 + + pgsql: + image: postgres + env: + POSTGRES_USER: root + POSTGRES_PASSWORD: wallet + POSTGRES_DB: wallet + POSTGRES_INITDB_ARGS: '--encoding=UTF-8 --lc-collate=C --lc-ctype=C' + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 10 + ports: + - 5432:5432 + + mysql: + image: bitnami/mysql:8.0 + env: + MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password + MYSQL_ROOT_PASSWORD: wallet + MYSQL_DATABASE: wallet + options: >- + --health-cmd="mysqladmin ping" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + ports: + - 3306:3306 + + mariadb: + image: mariadb:10.10 + env: + MYSQL_ROOT_PASSWORD: wallet + MYSQL_DATABASE: wallet + options: >- + --health-cmd="mysqladmin ping" + --health-interval 10s + --health-timeout 5s + --health-retries 10 + ports: + - 3307:3306 + + steps: + - name: Checkout + id: git-checkout + uses: actions/checkout@v4 + + - name: Setup PHP + id: php-install + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, pgsql, mysql, sqlite, redis, memcached + coverage: pcov + + - name: Validate composer.json and composer.lock + id: composer-validate + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + id: composer-dependencies + run: composer install --prefer-dist --no-progress + + - name: Check codeclimate + id: codeclimate-check + run: echo "execute=${{ matrix.php-versions == '8.2' && matrix.caches == 'array' && matrix.databases == 'testing' }}" >> $GITHUB_OUTPUT + + - name: Prepare codeclimate + id: codeclimate-prepare + run: | + curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + chmod +x ./cc-test-reporter + ./cc-test-reporter before-build + if: ${{ steps.codeclimate-check.outputs.execute == 'true' }} + + - name: Prepare run test suite + id: unit-prepare + run: | + mkdir build + + - name: Run test suite + id: unit-run + run: composer parabench + env: + WALLET_CACHE_DRIVER: ${{ matrix.caches }} + WALLET_LOCK_DRIVER: ${{ matrix.locks }} + DB_CONNECTION: ${{ matrix.databases }} + + - name: Send coverage + id: codeclimate-send + run: | + ./cc-test-reporter after-build --coverage-input-type clover --exit-code 0 + bash <(curl -s https://codecov.io/bash) + env: + CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + if: ${{ steps.codeclimate-check.outputs.execute == 'true' }} \ No newline at end of file diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..5a1a09f --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,14 @@ +name: Mark stale issues +on: + schedule: + - cron: "0 0 * * *" +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue is stale because it has been open 21 days with no activity.' + days-before-stale: 21 + days-before-close: 3 diff --git a/.gitignore b/.gitignore index cf13d71..2525d15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ -/vendor -/.idea +composer.phar +/vendor/ composer.lock -tests/coverage +.idea/ +build/ +.phpunit.result.cache +.php_cs_cache +.phpunit.cache/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 26b8c8e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: php -php: - - '7.2' - - '7.3' - - '7.4' - - 'nightly' - -services: - - docker - - memcached - -matrix: - allow_failures: - - php: 'nightly' - -before_script: - - docker run -p 9000:9000 -p 8123:8123 -d --name clickhouse --ulimit nofile=262144:262144 yandex/clickhouse-server - - pecl install pcov - - phpenv config-rm xdebug.ini || echo "xdebug not available" - - bash <(curl -s https://raw.githubusercontent.com/php-cache/cache/master/build/php/7.2/Memcached.sh) - - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - - chmod +x ./cc-test-reporter - - if [ $(phpenv version-name) = "7.4" ]; then ./cc-test-reporter before-build; fi - - composer install - -script: - - ./vendor/bin/phpunit --coverage-xml=build/coverage-xml --log-junit=build/junit.xml - - ./vendor/bin/infection --coverage=build --min-msi=20 -j$(nproc) - -after_success: - - if [ $(phpenv version-name) = "7.4" ]; then ./cc-test-reporter after-build --coverage-input-type clover --exit-code $TRAVIS_TEST_RESULT; fi - - bash <(curl -s https://codecov.io/bash) diff --git a/composer.json b/composer.json index ae53154..c8ecf3d 100644 --- a/composer.json +++ b/composer.json @@ -9,18 +9,24 @@ "eloquent" ], "require": { - "php": "^7.2|^8.0", - "laravel/framework": "^6.0|^7.0|^8.0|^9.0|^10.0", - "the-tinderbox/clickhouse-builder": "^4.0|^5.0|^6.0", + "php": "^8.2", + "laravel/framework": "^10.0|^11.0", + "the-tinderbox/clickhouse-builder": "^6.1", "ext-json": "*" }, "require-dev": { - "infection/infection": "~0.15", - "phpunit/phpunit": "^8.0|^9.0", - "mockery/mockery": "^1.3", - "fakerphp/faker": "^1.9", - "bavix/clickhouse-php-client": "^3.0", - "bavix/clickhouse-builder": "^4.0" + "driftingly/rector-laravel": "^1.0", + "ergebnis/phpstan-rules": "^2.1", + "infection/infection": "~0.27", + "larastan/larastan": "^2.8", + "nunomaduro/collision": "^8.0", + "orchestra/testbench": "^9.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "rector/rector": "^1.0", + "symplify/easy-coding-standard": "^12.1", + "mockery/mockery": "^1.6", + "fakerphp/faker": "^1.23" }, "autoload": { "psr-4": { @@ -40,6 +46,19 @@ } }, "scripts": { - "test": "vendor/bin/phpunit --stop-on-failure tests/" + "parabench":"@php ./vendor/bin/testbench package:test --coverage-xml=build/coverage-xml --log-junit=build/junit.xml", + "infect": "@php vendor/bin/infection --coverage=build --min-msi=50 -j$(nproc) --only-covering-test-cases", + "phpstan": "@php vendor/bin/phpstan analyse -vvv --memory-limit 2G -c phpstan.neon", + "phpstan-baseline": "@php vendor/bin/phpstan analyse -vvv --memory-limit 2G -c phpstan.neon --generate-baseline phpstan.baseline.neon", + "ecs": "@php vendor/bin/ecs check", + "ecs-fix": "@php vendor/bin/ecs check --fix", + "ecs-cc": "@php vendor/bin/ecs --clear-cache", + "rector": "@php vendor/bin/rector process --dry-run", + "rector-fix": "@php vendor/bin/rector process" + }, + "config": { + "allow-plugins": { + "infection/extension-installer": true + } } } diff --git a/ecs.php b/ecs.php new file mode 100644 index 0000000..c6f339c --- /dev/null +++ b/ecs.php @@ -0,0 +1,31 @@ +paths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + + $config->skip([ + GeneralPhpdocAnnotationRemoveFixer::class, + ]); + + $config->sets([ + SetList::CLEAN_CODE, + SetList::SYMPLIFY, + SetList::ARRAY, + SetList::COMMON, + SetList::PSR_12, + SetList::CONTROL_STRUCTURES, + SetList::NAMESPACES, + SetList::STRICT, + SetList::PHPUNIT, + SetList::LARAVEL, + ]); +}; \ No newline at end of file diff --git a/phpstan.common.neon b/phpstan.common.neon new file mode 100644 index 0000000..5e64751 --- /dev/null +++ b/phpstan.common.neon @@ -0,0 +1,8 @@ +includes: + - vendor/larastan/larastan/extension.neon + - vendor/ergebnis/phpstan-rules/rules.neon + +parameters: + level: 9 + fileExtensions: + - php \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..8da6d34 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,22 @@ +includes: + - phpstan.common.neon + +parameters: + level: 9 + fileExtensions: + - php + ergebnis: + noParameterWithNullableTypeDeclaration: + enabled: false + noNullableReturnTypeDeclaration: + enabled: false + noParameterWithNullDefaultValue: + enabled: false + final: + allowAbstractClasses: true + noExtends: + classesAllowedToBeExtended: + # laravel + - Illuminate\Support\ServiceProvider + paths: + - src/ \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index 1431f13..4b8b29f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,24 +1,27 @@ - - - - ./tests/Unit - - - - - src/Database/ - - - - - + + + + + + + + + + tests + + + + + + + + + + + + + src/ + + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..6c5c7ee --- /dev/null +++ b/rector.php @@ -0,0 +1,28 @@ +parallel(); + $config->paths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + + // Define what rule sets will be applied + $config->import(PHPUnitSetList::ANNOTATIONS_TO_ATTRIBUTES); + $config->import(LaravelLevelSetList::UP_TO_LARAVEL_110); + $config->import(PHPUnitSetList::PHPUNIT_100); + $config->import(SetList::STRICT_BOOLEANS); + $config->import(SetList::PRIVATIZATION); + $config->import(SetList::EARLY_RETURN); + $config->import(SetList::INSTANCEOF); + $config->import(SetList::CODE_QUALITY); + $config->import(SetList::DEAD_CODE); + $config->import(SetList::PHP_82); +}; diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index 25bdbac..b00b8e3 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -6,6 +6,8 @@ use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Eloquent\Model; +use Bavix\LaravelClickHouse\Database\Query\Pdo; +use Bavix\LaravelClickHouse\Database\Query\PdoInterface; use Illuminate\Database\DatabaseManager; use Illuminate\Support\ServiceProvider; @@ -27,6 +29,7 @@ public function boot(): void */ public function register(): void { + $this->app->singleton(PdoInterface::class, Pdo::class); $this->app->resolving('db', static function (DatabaseManager $db) { $db->extend('bavix::clickhouse', static function ($config, $name) { return new Connection(\array_merge($config, \compact('name'))); diff --git a/src/Database/Connection.php b/src/Database/Connection.php index 91c793b..7cd5eb3 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -6,6 +6,7 @@ use Bavix\LaravelClickHouse\Database\Query\Builder; use Bavix\LaravelClickHouse\Database\Query\Pdo; +use Bavix\LaravelClickHouse\Database\Query\PdoInterface; use Tinderbox\ClickhouseBuilder\Query\Grammar; class Connection extends \Tinderbox\ClickhouseBuilder\Integrations\Laravel\Connection @@ -18,11 +19,8 @@ public function query() return new Builder($this, new Grammar()); } - /** - * @return Pdo - */ - public function getPdo() + public function getPdo(): PdoInterface { - return app(Pdo::class); + return app(PdoInterface::class); } } diff --git a/src/Database/Eloquent/Concerns/HasAttributes.php b/src/Database/Eloquent/Concerns/HasAttributes.php index ce0698d..7813588 100644 --- a/src/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Database/Eloquent/Concerns/HasAttributes.php @@ -12,7 +12,9 @@ trait HasAttributes public function getDates(): array { - return $this->dates; + return property_exists($this, 'dates') && is_array($this->dates) + ? $this->dates + : []; } public function getCasts(): array diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index ad90929..c69b1d1 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -33,6 +33,13 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab use HidesAttributes; use GuardsAttributes; + /** + * Indicates if an exception should be thrown when trying to access a missing attribute on a retrieved model. + * + * @var bool + */ + protected static $modelsShouldPreventAccessingMissingAttributes = false; + /** * The connection name for the model. * @@ -721,4 +728,9 @@ public static function __callStatic($method, $parameters) { return (new static())->$method(...$parameters); } + + public static function preventsAccessingMissingAttributes(): bool + { + return static::$modelsShouldPreventAccessingMissingAttributes; + } } diff --git a/src/Database/Query/Pdo.php b/src/Database/Query/Pdo.php index 417dfd0..f256834 100644 --- a/src/Database/Query/Pdo.php +++ b/src/Database/Query/Pdo.php @@ -4,14 +4,9 @@ namespace Bavix\LaravelClickHouse\Database\Query; -class Pdo +final class Pdo implements PdoInterface { - /** - * @param mixed $binding - * - * @return mixed - */ - public function quote($binding) + public function quote(mixed $binding): mixed { return $binding; } diff --git a/src/Database/Query/PdoInterface.php b/src/Database/Query/PdoInterface.php new file mode 100644 index 0000000..259ea73 --- /dev/null +++ b/src/Database/Query/PdoInterface.php @@ -0,0 +1,10 @@ +builder->get(); - self::assertInstanceOf(\Illuminate\Support\Collection::class, $builderResult); + self::assertInstanceOf(Collection::class, $builderResult); self::assertSame($connectionResult, $builderResult->toArray()); } From 38985c09bd94b4d27f9a0b8a2c73f51497c54ac7 Mon Sep 17 00:00:00 2001 From: "mend-bolt-for-github[bot]" <42819689+mend-bolt-for-github[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 19:21:54 +0000 Subject: [PATCH 38/69] Add .whitesource configuration file --- .whitesource | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .whitesource diff --git a/.whitesource b/.whitesource new file mode 100644 index 0000000..9c7ae90 --- /dev/null +++ b/.whitesource @@ -0,0 +1,14 @@ +{ + "scanSettings": { + "baseBranches": [] + }, + "checkRunSettings": { + "vulnerableCheckRunConclusionLevel": "failure", + "displayMode": "diff", + "useMendCheckNames": true + }, + "issueSettings": { + "minSeverityLevel": "LOW", + "issueType": "DEPENDENCY" + } +} \ No newline at end of file From 56432d022a5beb31a5f67da6b752f270869b3e75 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 22:51:31 +0300 Subject: [PATCH 39/69] fix --- tests/Unit/Database/Eloquent/CollectionTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index 9833a2a..3ae1c94 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -195,7 +195,7 @@ public function testGet(): void ); } - public function findDataProvider(): array + public static function findDataProvider(): array { return [ [5], @@ -208,7 +208,7 @@ public function findDataProvider(): array ]; } - public function containsDataProvider() + public static function containsDataProvider() { return [ [true, 5], From 8fbc0320021278837874e4d9b6cbded2cb6fbe9d Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 22:56:41 +0300 Subject: [PATCH 40/69] fix --- .github/workflows/phpunits.yaml | 63 +++------------------------------ 1 file changed, 4 insertions(+), 59 deletions(-) diff --git a/.github/workflows/phpunits.yaml b/.github/workflows/phpunits.yaml index dcd34eb..2c2aeba 100644 --- a/.github/workflows/phpunits.yaml +++ b/.github/workflows/phpunits.yaml @@ -18,67 +18,12 @@ jobs: locks: [array, redis, memcached] services: - redis: - image: redis - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 10 - ports: - - 6379:6379 - - memcached: - image: memcached - options: >- - --health-cmd "timeout 5 bash -c 'cat < /dev/null > /dev/udp/127.0.0.1/11211'" - --health-interval 10s - --health-timeout 5s - --health-retries 10 - ports: - - 11211:11211 - - pgsql: - image: postgres - env: - POSTGRES_USER: root - POSTGRES_PASSWORD: wallet - POSTGRES_DB: wallet - POSTGRES_INITDB_ARGS: '--encoding=UTF-8 --lc-collate=C --lc-ctype=C' - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 10 - ports: - - 5432:5432 - - mysql: - image: bitnami/mysql:8.0 - env: - MYSQL_AUTHENTICATION_PLUGIN: mysql_native_password - MYSQL_ROOT_PASSWORD: wallet - MYSQL_DATABASE: wallet - options: >- - --health-cmd="mysqladmin ping" - --health-interval 10s - --health-timeout 5s - --health-retries 10 - ports: - - 3306:3306 - - mariadb: - image: mariadb:10.10 + clickhouse: + image: clickhouse/clickhouse-server env: - MYSQL_ROOT_PASSWORD: wallet - MYSQL_DATABASE: wallet - options: >- - --health-cmd="mysqladmin ping" - --health-interval 10s - --health-timeout 5s - --health-retries 10 + CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 ports: - - 3307:3306 + - 8123:8123 steps: - name: Checkout From 4d6ff74aa2856d07f55c75441ec93138fcf85849 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 22:58:28 +0300 Subject: [PATCH 41/69] fix --- .github/workflows/phpunits.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/phpunits.yaml b/.github/workflows/phpunits.yaml index 2c2aeba..5db2a8a 100644 --- a/.github/workflows/phpunits.yaml +++ b/.github/workflows/phpunits.yaml @@ -13,9 +13,6 @@ jobs: strategy: matrix: php-versions: [8.2, 8.3] - databases: [testing, pgsql, mysql, mariadb] - caches: [array, redis, memcached] - locks: [array, redis, memcached] services: clickhouse: @@ -75,10 +72,6 @@ jobs: - name: Run test suite id: unit-run run: composer parabench - env: - WALLET_CACHE_DRIVER: ${{ matrix.caches }} - WALLET_LOCK_DRIVER: ${{ matrix.locks }} - DB_CONNECTION: ${{ matrix.databases }} - name: Send coverage id: codeclimate-send From ce0b67ed955d53c3728eb4f16a22985fabfa40f7 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 23:00:49 +0300 Subject: [PATCH 42/69] fix --- tests/Unit/Database/Eloquent/BuilderTest.php | 2 +- tests/Unit/Database/Query/BuilderTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index 825be01..18ceefb 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -221,7 +221,7 @@ public function testGet(): void 'boolAttribute' => 1, 'booleanAttribute' => 1, 'objectAttribute' => json_encode([ - $this->faker()->word => $this->faker()->randomLetter, + $this->faker()->word() => $this->faker()->randomLetter, ]), 'arrayAttribute' => json_encode(range(1, 5)), 'dateAttribute' => now()->toDateTimeString(), diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index aa3c09c..528227f 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -36,7 +36,7 @@ protected function setUp(): void $this->connection, new Grammar() ); - $this->builder->from($this->faker()->word); + $this->builder->from($this->faker()->word()); } public function testGet(): void @@ -99,7 +99,7 @@ public function testInsert(): void self::assertFalse($this->builder->insert([])); $insertedRow = [ - $this->faker()->word => $this->faker()->randomDigit, + $this->faker()->word() => $this->faker()->randomDigit, $this->faker()->randomLetter => $this->faker()->randomDigit, $this->faker()->numerify('column_#') => $this->faker()->randomLetter, ]; From 649ea18d3bdf083d869ba0ed5ca92f8365142e49 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 23:02:03 +0300 Subject: [PATCH 43/69] fix --- tests/Unit/Database/Eloquent/BuilderTest.php | 6 +++--- tests/Unit/Database/Query/BuilderTest.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index 18ceefb..d9f8611 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -214,10 +214,10 @@ public function testFindOrFail(): void public function testGet(): void { $connectionResultRow = [ - 'id' => $this->faker()->randomDigit, - 'intAttribute' => (string) $this->faker()->randomDigit, + 'id' => $this->faker()->randomDigit(), + 'intAttribute' => (string) $this->faker()->randomDigit(), 'floatAttribute' => (string) $this->faker()->randomFloat(2), - 'stringAttribute' => $this->faker()->randomDigit, + 'stringAttribute' => $this->faker()->randomDigit(), 'boolAttribute' => 1, 'booleanAttribute' => 1, 'objectAttribute' => json_encode([ diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index 528227f..273375b 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -99,8 +99,8 @@ public function testInsert(): void self::assertFalse($this->builder->insert([])); $insertedRow = [ - $this->faker()->word() => $this->faker()->randomDigit, - $this->faker()->randomLetter => $this->faker()->randomDigit, + $this->faker()->word() => $this->faker()->randomDigit(), + $this->faker()->randomLetter => $this->faker()->randomDigit(), $this->faker()->numerify('column_#') => $this->faker()->randomLetter, ]; From a17ee54e9241a044b2808174b19ecea70b13b3da Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 23:04:02 +0300 Subject: [PATCH 44/69] fix --- tests/Unit/Database/Eloquent/BuilderTest.php | 4 ++-- tests/Unit/Database/Query/BuilderTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index d9f8611..ce8955c 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -153,7 +153,7 @@ public function testOrWhere(): void public function testFind(): void { $id = $this->faker()->numberBetween(1); - $stringAttribute = $this->faker()->word; + $stringAttribute = $this->faker()->word(); $this->connection ->shouldReceive('getName') @@ -221,7 +221,7 @@ public function testGet(): void 'boolAttribute' => 1, 'booleanAttribute' => 1, 'objectAttribute' => json_encode([ - $this->faker()->word() => $this->faker()->randomLetter, + $this->faker()->word() => $this->faker()->randomLetter() ]), 'arrayAttribute' => json_encode(range(1, 5)), 'dateAttribute' => now()->toDateTimeString(), diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index 273375b..a96cb4a 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -100,8 +100,8 @@ public function testInsert(): void $insertedRow = [ $this->faker()->word() => $this->faker()->randomDigit(), - $this->faker()->randomLetter => $this->faker()->randomDigit(), - $this->faker()->numerify('column_#') => $this->faker()->randomLetter, + $this->faker()->randomLetter() => $this->faker()->randomDigit(), + $this->faker()->numerify('column_#') => $this->faker()->randomLetter(), ]; \ksort($insertedRow); From fe5d3343ba0884d59fd2a8df23de6bbdfa3fea72 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 23:06:20 +0300 Subject: [PATCH 45/69] fix --- .github/workflows/fixer.yaml | 8 +++++ ...entModelTest.php => BaseEloquentModel.php} | 2 +- ...gTest.php => BaseEloquentModelCasting.php} | 2 +- ...WithTest.php => BaseEloquentModelWith.php} | 2 +- tests/Unit/Database/Eloquent/BuilderTest.php | 12 ++++---- .../Unit/Database/Eloquent/CollectionTest.php | 30 +++++++++---------- tests/Unit/Database/Eloquent/ModelTest.php | 18 +++++------ 7 files changed, 41 insertions(+), 33 deletions(-) rename tests/{EloquentModelTest.php => BaseEloquentModel.php} (95%) rename tests/{EloquentModelCastingTest.php => BaseEloquentModelCasting.php} (92%) rename tests/{EloquentModelWithTest.php => BaseEloquentModelWith.php} (90%) diff --git a/.github/workflows/fixer.yaml b/.github/workflows/fixer.yaml index ae0e76b..27f8915 100644 --- a/.github/workflows/fixer.yaml +++ b/.github/workflows/fixer.yaml @@ -10,6 +10,14 @@ jobs: autofix: runs-on: ubuntu-latest + services: + clickhouse: + image: clickhouse/clickhouse-server + env: + CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 + ports: + - 8123:8123 + steps: - name: Checkout uses: actions/checkout@v4 diff --git a/tests/EloquentModelTest.php b/tests/BaseEloquentModel.php similarity index 95% rename from tests/EloquentModelTest.php rename to tests/BaseEloquentModel.php index 81b3827..835b9c8 100644 --- a/tests/EloquentModelTest.php +++ b/tests/BaseEloquentModel.php @@ -13,7 +13,7 @@ * @property float amount * @property string status */ -class EloquentModelTest extends Model +class BaseEloquentModel extends Model { protected $table = 'test_table'; diff --git a/tests/EloquentModelCastingTest.php b/tests/BaseEloquentModelCasting.php similarity index 92% rename from tests/EloquentModelCastingTest.php rename to tests/BaseEloquentModelCasting.php index 3cd65af..bfe436b 100644 --- a/tests/EloquentModelCastingTest.php +++ b/tests/BaseEloquentModelCasting.php @@ -4,7 +4,7 @@ namespace Bavix\LaravelClickHouse\Tests; -class EloquentModelCastingTest extends EloquentModelTest +class BaseEloquentModelCasting extends BaseEloquentModel { use Helpers; diff --git a/tests/EloquentModelWithTest.php b/tests/BaseEloquentModelWith.php similarity index 90% rename from tests/EloquentModelWithTest.php rename to tests/BaseEloquentModelWith.php index 7cc8ba8..4948df3 100644 --- a/tests/EloquentModelWithTest.php +++ b/tests/BaseEloquentModelWith.php @@ -7,7 +7,7 @@ use Bavix\LaravelClickHouse\Database\Eloquent\Builder; use Mockery\MockInterface; -class EloquentModelWithTest extends EloquentModelTest +class BaseEloquentModelWith extends BaseEloquentModel { use Helpers; diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index ce8955c..76b4191 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -8,7 +8,7 @@ use Bavix\LaravelClickHouse\Database\Eloquent\Builder; use Bavix\LaravelClickHouse\Database\Eloquent\Collection; use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; -use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\BaseEloquentModelCasting; use Bavix\LaravelClickHouse\Tests\Helpers; use Illuminate\Database\DatabaseManager; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -24,7 +24,7 @@ /** * @property Mock|Connection connection * @property Builder builder - * @property EloquentModelCastingTest model + * @property BaseEloquentModelCasting model */ class BuilderTest extends TestCase { @@ -35,7 +35,7 @@ class BuilderTest extends TestCase */ private MockInterface $connection; private Builder $builder; - private EloquentModelCastingTest $model; + private BaseEloquentModelCasting $model; protected function setUp(): void { @@ -43,7 +43,7 @@ protected function setUp(): void $this->connection = $this->mock(Connection::class); - $this->model = new EloquentModelCastingTest(); + $this->model = new BaseEloquentModelCasting(); $this->builder = (new Builder(new QueryBuilder($this->connection, new Grammar()))) ->setModel($this->model); @@ -122,7 +122,7 @@ public function testWhereClosure(): void $resolver = $this->mock(DatabaseManager::class); $resolver->shouldReceive('connection') ->andReturn($this->connection); - EloquentModelCastingTest::setConnectionResolver($resolver); + BaseEloquentModelCasting::setConnectionResolver($resolver); $this->builder ->where(function (Builder $query) { @@ -167,7 +167,7 @@ public function testFind(): void $model = $this->builder->find($id); - self::assertInstanceOf(EloquentModelCastingTest::class, $model); + self::assertInstanceOf(BaseEloquentModelCasting::class, $model); self::assertSame($id, $model->id); self::assertSame($stringAttribute, $model->stringAttribute); } diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index 3ae1c94..50d0713 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -7,7 +7,7 @@ use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Eloquent\Collection; use Bavix\LaravelClickHouse\Database\Query\Builder; -use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; +use Bavix\LaravelClickHouse\Tests\BaseEloquentModelCasting; use Bavix\LaravelClickHouse\Tests\Helpers; use Carbon\Carbon; use Illuminate\Database\DatabaseManager; @@ -36,14 +36,14 @@ protected function setUp(): void $this->connection ->shouldReceive('getName') - ->andReturn((new EloquentModelCastingTest())->getConnectionName()); + ->andReturn((new BaseEloquentModelCasting())->getConnectionName()); /** @var Mock|DatabaseManager $resolver */ $resolver = $this->mock(DatabaseManager::class); $resolver->shouldReceive('connection') ->andReturn($this->connection); - EloquentModelCastingTest::setConnectionResolver($resolver); + BaseEloquentModelCasting::setConnectionResolver($resolver); } public function testMapModelToModel(): void @@ -59,8 +59,8 @@ public function testMapModelToModel(): void $now = now(); - $models = EloquentModelCastingTest::all() - ->map(function (EloquentModelCastingTest $model) use ($now) { + $models = BaseEloquentModelCasting::all() + ->map(function (BaseEloquentModelCasting $model) use ($now) { $model->datetimeAttribute = $now; return $model; @@ -69,7 +69,7 @@ public function testMapModelToModel(): void self::assertInstanceOf(Collection::class, $models); self::assertCount($connectionResult->count(), $models); - $models->each(function (EloquentModelCastingTest $model, int $key) use ($now) { + $models->each(function (BaseEloquentModelCasting $model, int $key) use ($now) { self::assertSame($key + 1, $model->id); self::assertInstanceOf(Carbon::class, $model->datetimeAttribute); self::assertSame($now->toDateTimeString(), $model->datetimeAttribute->toDateTimeString()); @@ -89,8 +89,8 @@ public function testMapModelToArray(): void $now = now(); - $collection = EloquentModelCastingTest::all() - ->map(function (EloquentModelCastingTest $model) use ($now) { + $collection = BaseEloquentModelCasting::all() + ->map(function (BaseEloquentModelCasting $model) use ($now) { return [ 'id' => $model->id, 'datetimeAttribute' => $now, @@ -123,13 +123,13 @@ public function testFind($key): void ->shouldReceive('select') ->andReturn($connectionResult->toArray()); - $found = EloquentModelCastingTest::all()->find($key); + $found = BaseEloquentModelCasting::all()->find($key); if (is_array($key)) { self::assertInstanceOf(Collection::class, $found); self::assertCount(count($key), $found); } else { - self::assertInstanceOf(EloquentModelCastingTest::class, $found); + self::assertInstanceOf(BaseEloquentModelCasting::class, $found); } } @@ -153,9 +153,9 @@ public function testContains(bool $expected, $key, $operator = null, $value = nu ->andReturn($connectionResult->toArray()); if ($operator !== null && $value !== null) { - $contains = EloquentModelCastingTest::all()->contains($key, $operator, $value); + $contains = BaseEloquentModelCasting::all()->contains($key, $operator, $value); } else { - $contains = EloquentModelCastingTest::all()->contains($key); + $contains = BaseEloquentModelCasting::all()->contains($key); } self::assertSame($expected, $contains); @@ -175,11 +175,11 @@ public function testGet(): void ->shouldReceive('select') ->andReturn($connectionResult->toArray()); - $models = EloquentModelCastingTest::all(); + $models = BaseEloquentModelCasting::all(); self::assertInstanceOf(Collection::class, $models); self::assertCount($connectionResult->count(), $models); - $models = $models->map(function (EloquentModelCastingTest $model) { + $models = $models->map(function (BaseEloquentModelCasting $model) { return $model->toArray(); }); @@ -200,7 +200,7 @@ public static function findDataProvider(): array return [ [5], [ - tap(new EloquentModelCastingTest(), function (EloquentModelCastingTest $model) { + tap(new BaseEloquentModelCasting(), function (BaseEloquentModelCasting $model) { $model->id = 5; }), ], diff --git a/tests/Unit/Database/Eloquent/ModelTest.php b/tests/Unit/Database/Eloquent/ModelTest.php index 2194663..3cc275e 100644 --- a/tests/Unit/Database/Eloquent/ModelTest.php +++ b/tests/Unit/Database/Eloquent/ModelTest.php @@ -4,9 +4,9 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; -use Bavix\LaravelClickHouse\Tests\EloquentModelCastingTest; -use Bavix\LaravelClickHouse\Tests\EloquentModelTest; -use Bavix\LaravelClickHouse\Tests\EloquentModelWithTest; +use Bavix\LaravelClickHouse\Tests\BaseEloquentModelCasting; +use Bavix\LaravelClickHouse\Tests\BaseEloquentModel; +use Bavix\LaravelClickHouse\Tests\BaseEloquentModelWith; use Bavix\LaravelClickHouse\Tests\Helpers; use Illuminate\Database\Eloquent\MassAssignmentException; use Illuminate\Support\Carbon; @@ -18,7 +18,7 @@ class ModelTest extends TestCase public function testAttributeManipulation(): void { - $model = new EloquentModelTest(); + $model = new BaseEloquentModel(); $model->status = 'successful'; self::assertEquals('successful', $model->status); self::assertTrue(isset($model->status)); @@ -35,12 +35,12 @@ public function testDirtyAttributes(): void { $this->expectException(MassAssignmentException::class); - new EloquentModelTest(['foo' => '1', 'bar' => 2, 'baz' => 3]); + new BaseEloquentModel(['foo' => '1', 'bar' => 2, 'baz' => 3]); } public function testDirtyOnCastOrDateAttributes(): void { - $model = new EloquentModelCastingTest(); + $model = new BaseEloquentModelCasting(); $model->setDateFormat('Y-m-d H:i:s'); $model->boolAttribute = 1; $model->foo = 1; @@ -63,7 +63,7 @@ public function testDirtyOnCastOrDateAttributes(): void public function testCalculatedAttributes(): void { - $model = new EloquentModelTest(); + $model = new BaseEloquentModel(); $model->password = 'secret'; $attributes = $model->getAttributes(); // ensure password attribute was not set to null @@ -76,14 +76,14 @@ public function testCalculatedAttributes(): void public function testWithMethodCallsQueryBuilderCorrectly(): void { - $result = EloquentModelWithTest::with('foo', 'bar'); + $result = BaseEloquentModelWith::with('foo', 'bar'); self::assertEquals('foo', $result); } public function testTimestampsAreReturnedAsObjectsFromPlainDatesAndTimestamps(): void { $datetime = '2012-12-04'; - $model = new EloquentModelCastingTest(); + $model = new BaseEloquentModelCasting(); $model->payed_at = $datetime; self::assertInstanceOf(Carbon::class, $model->payed_at); From 363d681cffdc5dad3b8ec3d75675bb32f7646ae8 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 14 Mar 2024 23:09:51 +0300 Subject: [PATCH 46/69] test --- .github/workflows/fixer.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/fixer.yaml b/.github/workflows/fixer.yaml index 27f8915..263c9bc 100644 --- a/.github/workflows/fixer.yaml +++ b/.github/workflows/fixer.yaml @@ -52,6 +52,12 @@ jobs: - name: Run ecs-fix run: composer ecs-fix + - name: Run rector-fix + run: composer rector-fix + + - name: Run ecs-fix + run: composer ecs-fix + - name: Run rector run: composer rector From b122fe0b2a5b76ed659cb87f5c4f0124ccf56997 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Fri, 15 Mar 2024 00:16:50 +0300 Subject: [PATCH 47/69] test --- rector.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rector.php b/rector.php index 6c5c7ee..c34009d 100644 --- a/rector.php +++ b/rector.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Rector\CodeQuality\Rector\Isset_\IssetOnPropertyObjectToPropertyExistsRector; use Rector\Config\RectorConfig; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\SetList; @@ -14,6 +15,10 @@ __DIR__ . '/tests', ]); + $config->skip([ + IssetOnPropertyObjectToPropertyExistsRector::class, + ]); + // Define what rule sets will be applied $config->import(PHPUnitSetList::ANNOTATIONS_TO_ATTRIBUTES); $config->import(LaravelLevelSetList::UP_TO_LARAVEL_110); From 524a3ed9a3fa9c1ab7dc16129f2291ff3877c065 Mon Sep 17 00:00:00 2001 From: Github bot Date: Thu, 14 Mar 2024 21:19:27 +0000 Subject: [PATCH 48/69] autofix --- src/ClickHouseServiceProvider.php | 9 +- src/Database/Connection.php | 1 - src/Database/Eloquent/Builder.php | 731 ++++++++---------- src/Database/Eloquent/Collection.php | 7 +- src/Database/Eloquent/Concerns/Common.php | 4 - src/Database/Eloquent/Model.php | 301 +++----- src/Database/Query/Builder.php | 47 +- src/Database/Query/PdoInterface.php | 2 +- tests/BaseEloquentModelCasting.php | 24 +- tests/Unit/Database/ConnectionTest.php | 37 +- tests/Unit/Database/Eloquent/BuilderTest.php | 89 ++- .../Unit/Database/Eloquent/CollectionTest.php | 50 +- tests/Unit/Database/Eloquent/ModelTest.php | 8 +- tests/Unit/Database/Query/BuilderTest.php | 35 +- 14 files changed, 587 insertions(+), 758 deletions(-) diff --git a/src/ClickHouseServiceProvider.php b/src/ClickHouseServiceProvider.php index b00b8e3..77e8fd3 100644 --- a/src/ClickHouseServiceProvider.php +++ b/src/ClickHouseServiceProvider.php @@ -15,8 +15,6 @@ class ClickHouseServiceProvider extends ServiceProvider { /** * @throws - * - * @return void */ public function boot(): void { @@ -24,15 +22,14 @@ public function boot(): void Model::setEventDispatcher($this->app['events']); } - /** - * @return void - */ public function register(): void { $this->app->singleton(PdoInterface::class, Pdo::class); $this->app->resolving('db', static function (DatabaseManager $db) { $db->extend('bavix::clickhouse', static function ($config, $name) { - return new Connection(\array_merge($config, \compact('name'))); + return new Connection(\array_merge($config, [ + 'name' => $name, + ])); }); }); } diff --git a/src/Database/Connection.php b/src/Database/Connection.php index 7cd5eb3..c5dab87 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -5,7 +5,6 @@ namespace Bavix\LaravelClickHouse\Database; use Bavix\LaravelClickHouse\Database\Query\Builder; -use Bavix\LaravelClickHouse\Database\Query\Pdo; use Bavix\LaravelClickHouse\Database\Query\PdoInterface; use Tinderbox\ClickhouseBuilder\Query\Grammar; diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index d6df1b2..1980e36 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -91,11 +91,89 @@ public function __construct(QueryBuilder $query) $this->query = $query; } + /** + * Dynamically handle calls into the query instance. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + if ($method === 'macro') { + $this->localMacros[$parameters[0]] = $parameters[1]; + + return null; + } + + if (isset($this->localMacros[$method])) { + array_unshift($parameters, $this); + + return $this->localMacros[$method](...$parameters); + } + + if (isset(static::$macros[$method])) { + if (static::$macros[$method] instanceof Closure) { + return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters); + } + + return call_user_func_array(static::$macros[$method], $parameters); + } + + if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { + return $this->callScope([$this->model, $scope], $parameters); + } + + if (in_array($method, $this->passthru, true)) { + return $this->toBase() + ->{$method}(...$parameters); + } + + $this->query->{$method}(...$parameters); + + return $this; + } + + /** + * Dynamically handle calls into the query instance. + * + * @param string $method + * @param array $parameters + * @return mixed + * + * @throws BadMethodCallException + */ + public static function __callStatic($method, $parameters) + { + if ($method === 'macro') { + static::$macros[$parameters[0]] = $parameters[1]; + + return null; + } + + if (! isset(static::$macros[$method])) { + throw new BadMethodCallException("Method {$method} does not exist."); + } + + if (static::$macros[$method] instanceof Closure) { + return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters); + } + + return call_user_func_array(static::$macros[$method], $parameters); + } + + /** + * Force a clone of the underlying query builder when cloning. + */ + public function __clone() + { + $this->query = clone $this->query; + } + /** * Add a where clause on the primary key to the query. * * @param mixed $id - * * @return $this */ public function whereKey($id): self @@ -113,7 +191,6 @@ public function whereKey($id): self * Add a where clause on the primary key to the query. * * @param mixed $id - * * @return $this */ public function whereKeyNot($id): self @@ -133,8 +210,6 @@ public function whereKeyNot($id): self * @param string|array|\Closure $column * @param string $operator * @param mixed $value - * @param string $boolean - * * @return $this */ public function where($column, $operator = null, $value = null, string $boolean = 'AND'): self @@ -157,7 +232,6 @@ public function where($column, $operator = null, $value = null, string $boolean * @param \Closure|array|string $column * @param string $operator * @param mixed $value - * * @return $this */ public function orWhere($column, $operator = null, $value = null): self @@ -167,10 +241,6 @@ public function orWhere($column, $operator = null, $value = null): self /** * Create a collection of models from plain arrays. - * - * @param iterable $items - * - * @return Collection */ public function hydrate(iterable $items): Collection { @@ -188,21 +258,16 @@ public function hydrate(iterable $items): Collection * * @param string $query * @param array $bindings - * - * @return Collection */ public function fromQuery($query, $bindings = []): Collection { - return $this->hydrate( - $this->query->getConnection()->select($query, $bindings) - ); + return $this->hydrate($this->query->getConnection()->select($query, $bindings, true)); } /** * Find a model by its primary key. * * @param mixed $id - * * @return Model|Collection|static[]|static|null */ public function find($id) @@ -211,15 +276,14 @@ public function find($id) return $this->findMany($id); } - return $this->whereKey($id)->first(); + return $this->whereKey($id) + ->first(); } /** * Find multiple models by their primary keys. * * @param \Illuminate\Contracts\Support\Arrayable|array $ids - * - * @return Collection */ public function findMany($ids): Collection { @@ -227,17 +291,17 @@ public function findMany($ids): Collection return $this->model->newCollection(); } - return $this->whereKey($ids)->get(); + return $this->whereKey($ids) + ->get(); } /** * Find a model by its primary key or throw an exception. * * @param mixed $id + * @return Model|Collection * * @throws ModelNotFoundException - * - * @return Model|Collection */ public function findOrFail($id) { @@ -252,24 +316,17 @@ public function findOrFail($id) return $result; } - throw (new ModelNotFoundException())->setModel( - get_class($this->model), - $id - ); + throw (new ModelNotFoundException())->setModel(get_class($this->model), $id); } /** * Execute the query and get the first result or throw an exception. * * @throws ModelNotFoundException - * - * @return Model|null */ public function firstOrFail(): ?Model { - /** - * @var Model $model - */ + /** @var Model $model */ $model = $this->first(); if ($model === null) { throw (new ModelNotFoundException()) @@ -283,8 +340,6 @@ public function firstOrFail(): ?Model * Execute the query as a "select" statement. * * @throws ClientException - * - * @return Collection */ public function get(): Collection { @@ -297,29 +352,28 @@ public function get(): Collection $models = $builder->eagerLoadRelations($models); } - return $builder->getModel()->newCollection($models); + return $builder->getModel() + ->newCollection($models); } /** * Get the hydrated models without eager loading. * - * @throws ClientException - * * @return Model[] + * + * @throws ClientException */ public function getModels(): array { - $result = $this->query->get()->all(); + $result = $this->query->get() + ->all(); - return $this->hydrate($result)->all(); + return $this->hydrate($result) + ->all(); } /** * Eager load the relationships for the models. - * - * @param array $models - * - * @return array */ public function eagerLoadRelations(array $models): array { @@ -335,42 +389,8 @@ public function eagerLoadRelations(array $models): array return $models; } - /** - * Eagerly load the relationship on a set of models. - * - * @param array $models - * @param string $name - * @param \Closure $constraints - * - * @return array - */ - protected function eagerLoadRelation(array $models, string $name, Closure $constraints): array - { - // First we will "back up" the existing where conditions on the query so we can - // add our eager constraints. Then we will merge the wheres that were on the - // query back to it in order that any where conditions might be specified. - $relation = $this->getRelation($name); - - $relation->addEagerConstraints($models); - - $constraints($relation); - - // Once we have the results, we just match those back up to their parent models - // using the relationship instance. Then we just return the finished arrays - // of models which have been eagerly hydrated and are readied for return. - return $relation->match( - $relation->initRelation($models, $name), - $relation->getEager(), - $name - ); - } - /** * Get the relation instance for the given relation name. - * - * @param string $name - * - * @return Relation */ public function getRelation(string $name): Relation { @@ -379,7 +399,8 @@ public function getRelation(string $name): Relation // and error prone. We don't want constraints because we add eager ones. $relation = Relation::noConstraints(function () use ($name) { try { - return $this->getModel()->{$name}(); + return $this->getModel() + ->{$name}(); } catch (BadMethodCallException $e) { throw RelationNotFoundException::make($this->getModel(), $name); } @@ -390,63 +411,25 @@ public function getRelation(string $name): Relation // If there are nested relationships set on the query, we will put those onto // the query instances so that they can be handled after this relationship // is loaded. In this way they will all trickle down as they are loaded. - if (count($nested) > 0) { - $relation->getQuery()->with($nested); + if ($nested !== []) { + $relation->getQuery() + ->with($nested); } return $relation; } - /** - * Get the deeply nested relations for a given top-level relation. - * - * @param string $relation - * - * @return array - */ - protected function relationsNestedUnder(string $relation): array - { - $nested = []; - - // We are basically looking for any relationships that are nested deeper than - // the given top-level relationship. We will just check for any relations - // that start with the given top relations and adds them to our arrays. - foreach ($this->eagerLoad as $name => $constraints) { - if ($this->isNestedUnder($relation, $name)) { - $nested[substr($name, strlen($relation.'.'))] = $constraints; - } - } - - return $nested; - } - - /** - * Determine if the relationship is nested. - * - * @param string $relation - * @param string $name - * - * @return bool - */ - protected function isNestedUnder(string $relation, string $name): bool - { - return Str::contains($name, '.') && Str::startsWith($name, $relation.'.'); - } - /** * Chunk the results of a query by comparing numeric IDs. * - * @param int $count - * @param callable $callback * @param null $column * @param string|null $alias - * - * @return bool */ public function chunkById(int $count, callable $callback, $column = null, $alias = null): bool { - $column = is_null($column) ? $this->getModel()->getKeyName() : $column; - $alias = is_null($alias) ? $column : $alias; + $column = $column === null ? $this->getModel() + ->getKeyName() : $column; + $alias = $alias === null ? $column : $alias; $lastId = 0; do { @@ -455,11 +438,12 @@ public function chunkById(int $count, callable $callback, $column = null, $alias // We'll execute the query for the given page and get the results. If there are // no results we can just break and return from here. When there are results // we will call the callback with the current chunk of these results here. - $results = $clone->forPageAfterId($count, $lastId, $column)->get(); + $results = $clone->forPageAfterId($count, $lastId, $column) + ->get(); $countResults = (int) $results->count(); - if (!$countResults) { + if ($countResults === 0) { break; } @@ -470,7 +454,8 @@ public function chunkById(int $count, callable $callback, $column = null, $alias return false; } - $lastId = $results->last()->{$alias}; + $lastId = $results->last() +->{$alias}; unset($results); } while ($countResults === $count); @@ -481,49 +466,51 @@ public function chunkById(int $count, callable $callback, $column = null, $alias /** * Get an array with the values of a given column. * - * @param string $column * @param string|null $key - * - * @return \Illuminate\Support\Collection */ public function pluck(string $column, $key = null): \Illuminate\Support\Collection { - $results = $this->toBase()->pluck($column, $key); + $results = $this->toBase() + ->pluck($column, $key); // If the model has a mutator for the requested column, we will spin through // the results and mutate the values so that the mutated version of these // columns are returned as you would expect from these Eloquent models. - if (!$this->model->hasGetMutator($column) && - !$this->model->hasCast($column) && - !in_array($column, $this->model->getDates(), true)) { + if (! $this->model->hasGetMutator($column) && + ! $this->model->hasCast($column) && + ! in_array($column, $this->model->getDates(), true)) { return $results; } return $results->map(function ($value) use ($column) { - return $this->model->newFromBuilder([$column => $value])->{$column}; + return $this->model->newFromBuilder([ + $column => $value, + ])->{$column}; }); } /** * Paginate the given query. * - * @param int|null $perPage * @param array $columns * @param string $pageName * @param int|null $page - * - * @return LengthAwarePaginator */ - public function paginate(?int $perPage = null, $columns = ['*'], $pageName = 'page', $page = null): LengthAwarePaginator - { + public function paginate( + ?int $perPage = null, + $columns = ['*'], + $pageName = 'page', + $page = null + ): LengthAwarePaginator { $page = $page ?: Paginator::resolveCurrentPage($pageName); - $perPage = $perPage ?: $this->model->getPerPage(); + $perPage = $perPage !== null && $perPage !== 0 ? $perPage : $this->model->getPerPage(); $results = ($total = $this->toBase()->getCountForPagination()) - ? $this->forPage($page, $perPage)->get($columns) + ? $this->forPage($page, $perPage) + ->get($columns) : $this->model->newCollection(); return $this->paginator($results, $total, $perPage, $page, [ - 'path' => Paginator::resolveCurrentPath(), + 'path' => Paginator::resolveCurrentPath(), 'pageName' => $pageName, ]); } @@ -531,28 +518,30 @@ public function paginate(?int $perPage = null, $columns = ['*'], $pageName = 'pa /** * Paginate the given query into a simple paginator. * - * @param int|null $perPage * @param array $columns * @param string $pageName * @param int|null $page * * @throws ClientException - * - * @return \Illuminate\Contracts\Pagination\Paginator */ - public function simplePaginate(?int $perPage = null, $columns = ['*'], $pageName = 'page', $page = null): \Illuminate\Contracts\Pagination\Paginator - { + public function simplePaginate( + ?int $perPage = null, + $columns = ['*'], + $pageName = 'page', + $page = null + ): \Illuminate\Contracts\Pagination\Paginator { $page = $page ?: Paginator::resolveCurrentPage($pageName); - $perPage = $perPage ?: $this->model->getPerPage(); + $perPage = $perPage !== null && $perPage !== 0 ? $perPage : $this->model->getPerPage(); // Next we will set the limit and offset for this query so that when we get the // results we get the proper section of results. Then, we'll create the full // paginator instances for these results with the given page and per page. - $this->skip(($page - 1) * $perPage)->take($perPage + 1); + $this->skip(($page - 1) * $perPage) + ->take($perPage + 1); - return $this->simplePaginator($this->get($columns), $perPage, $page, [ - 'path' => Paginator::resolveCurrentPath(), + return $this->simplePaginator($this->get(), $perPage, $page, [ + 'path' => Paginator::resolveCurrentPath(), 'pageName' => $pageName, ]); } @@ -560,8 +549,6 @@ public function simplePaginate(?int $perPage = null, $columns = ['*'], $pageName /** * Call the given local model scopes. * - * @param array $scopes - * * @return mixed */ public function scopes(array $scopes) @@ -573,16 +560,13 @@ public function scopes(array $scopes) // the parameter list is empty, so we will format the scope name and these // parameters here. Then, we'll be ready to call the scope on the model. if (is_int($scope)) { - list($scope, $parameters) = [$parameters, []]; + [$scope, $parameters] = [$parameters, []]; } // Next we'll pass the scope callback to the callScope method which will take // care of grouping the "wheres" properly so the logical order doesn't get // messed up when adding scopes. Then we'll return back out the builder. - $builder = $builder->callScope( - [$this->model, 'scope'.ucfirst($scope)], - (array) $parameters - ); + $builder = $builder->callScope([$this->model, 'scope'.ucfirst($scope)], (array) $parameters); } return $builder; @@ -595,14 +579,14 @@ public function scopes(array $scopes) */ public function applyScopes() { - if (!$this->scopes) { + if (! $this->scopes) { return $this; } $builder = clone $this; foreach ($this->scopes as $identifier => $scope) { - if (!isset($builder->scopes[$identifier])) { + if (! isset($builder->scopes[$identifier])) { continue; } @@ -626,110 +610,10 @@ public function applyScopes() return $builder; } - /** - * Apply the given scope on the current builder instance. - * - * @param callable $scope - * @param array $parameters - * - * @return mixed - */ - protected function callScope(callable $scope, $parameters = []) - { - array_unshift($parameters, $this); - - $query = $this->getQuery(); - - // We will keep track of how many wheres are on the query before running the - // scope so that we can properly group the added scope constraints in the - // query as their own isolated nested where statement and avoid issues. - $originalWhereCount = $query->getWheres() === null - ? 0 : count($query->getWheres()); - - $result = $scope(...array_values($parameters)) ?? $this; - - if (count((array) $query->getWheres()) > $originalWhereCount) { - $this->addNewWheresWithinGroup($query, $originalWhereCount); - } - - return $result; - } - - /** - * Nest where conditions by slicing them at the given where count. - * - * @param \Illuminate\Database\Query\Builder $query - * @param int $originalWhereCount - * - * @return void - */ - protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCount) - { - // Here, we totally remove all of the where clauses since we are going to - // rebuild them as nested queries by slicing the groups of wheres into - // their own sections. This is to prevent any confusing logic order. - $allWheres = $query->wheres; - - $query->wheres = []; - - $this->groupWhereSliceForScope( - $query, - array_slice($allWheres, 0, $originalWhereCount) - ); - - $this->groupWhereSliceForScope( - $query, - array_slice($allWheres, $originalWhereCount) - ); - } - - /** - * Slice where conditions at the given offset and add them to the query as a nested condition. - * - * @param \Illuminate\Database\Query\Builder $query - * @param array $whereSlice - * - * @return void - */ - protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) - { - $whereBooleans = collect($whereSlice)->pluck('boolean'); - - // Here we'll check if the given subset of where clauses contains any "or" - // booleans and in this case create a nested where expression. That way - // we don't add any unnecessary nesting thus keeping the query clean. - if ($whereBooleans->contains('or')) { - $query->wheres[] = $this->createNestedWhere( - $whereSlice, - $whereBooleans->first() - ); - } else { - $query->wheres = array_merge($query->wheres, $whereSlice); - } - } - - /** - * Create a where array with nested where conditions. - * - * @param array $whereSlice - * @param string $boolean - * - * @return array - */ - protected function createNestedWhere($whereSlice, $boolean = 'and') - { - $whereGroup = $this->getQuery()->forNestedWhere(); - - $whereGroup->wheres = $whereSlice; - - return ['type' => 'Nested', 'query' => $whereGroup, 'boolean' => $boolean]; - } - /** * Set the relationships that should be eager loaded. * * @param mixed $relations - * * @return $this */ public function with($relations) @@ -745,7 +629,6 @@ public function with($relations) * Prevent the specified relations from being eager loaded. * * @param mixed $relations - * * @return $this */ public function without($relations) @@ -761,104 +644,18 @@ public function without($relations) * Create a new instance of the model being queried. * * @param array $attributes - * * @return Model */ public function newModelInstance($attributes = []) { - return $this->model->newInstance($attributes)->setConnection( - $this->query->getConnection()->getName() - ); + return $this->model->newInstance($attributes) + ->setConnection($this->query->getConnection()->getName()); } - /** - * Parse a list of relations into individuals. - * - * @param array $relations - * - * @return array - */ - protected function parseWithRelations(array $relations) + public function getQuery(): QueryBuilder { - $results = []; - - foreach ($relations as $name => $constraints) { - // If the "relation" value is actually a numeric key, we can assume that no - // constraints have been specified for the eager load and we'll just put - // an empty Closure with the loader so that we can treat all the same. - if (is_numeric($name)) { - $name = $constraints; - - list($name, $constraints) = Str::contains($name, ':') - ? $this->createSelectWithConstraint($name) - : [ - $name, - function () { - // - }, - ]; - } - - // We need to separate out any nested includes. Which allows the developers - // to load deep relationships using "dots" without stating each level of - // the relationship with its own key in the array of eager load names. - $results = $this->addNestedWiths($name, $results); - - $results[$name] = $constraints; - } - - return $results; - } - - /** - * Create a constraint to select the given columns for the relation. - * - * @param string $name - * - * @return array - */ - protected function createSelectWithConstraint($name) - { - return [ - explode(':', $name)[0], - function ($query) use ($name) { - $query->select(explode(',', explode(':', $name)[1])); - }, - ]; - } - - /** - * Parse the nested relationships in a relation. - * - * @param string $name - * @param array $results - * - * @return array - */ - protected function addNestedWiths($name, $results) - { - $progress = []; - - // If the relation has already been set on the result array, we will not set it - // again, since that would override any constraints that were already placed - // on the relationships. We will only set the ones that are not specified. - foreach (explode('.', $name) as $segment) { - $progress[] = $segment; - - if (!isset($results[$last = implode('.', $progress)])) { - $results[$last] = function () { - // - }; - } - } - - return $results; - } - - public function getQuery(): QueryBuilder - { - return $this->query; - } + return $this->query; + } public function setQuery(QueryBuilder $query) { @@ -874,7 +671,8 @@ public function setQuery(QueryBuilder $query) */ public function toBase() { - return $this->applyScopes()->getQuery(); + return $this->applyScopes() + ->getQuery(); } /** @@ -890,8 +688,6 @@ public function getEagerLoads() /** * Set the relationships being eagerly loaded. * - * @param array $eagerLoad - * * @return $this */ public function setEagerLoads(array $eagerLoad) @@ -919,8 +715,7 @@ public function setModel(Model $model) * Get the given macro by name. * * @param string $name - * - * @return \Closure + * @return Closure */ public function getMacro($name) { @@ -928,84 +723,218 @@ public function getMacro($name) } /** - * Dynamically handle calls into the query instance. - * - * @param string $method - * @param array $parameters - * - * @return mixed + * Eagerly load the relationship on a set of models. */ - public function __call($method, $parameters) + protected function eagerLoadRelation(array $models, string $name, Closure $constraints): array { - if ($method === 'macro') { - $this->localMacros[$parameters[0]] = $parameters[1]; + // First we will "back up" the existing where conditions on the query so we can + // add our eager constraints. Then we will merge the wheres that were on the + // query back to it in order that any where conditions might be specified. + $relation = $this->getRelation($name); - return null; - } + $relation->addEagerConstraints($models); - if (isset($this->localMacros[$method])) { - array_unshift($parameters, $this); + $constraints($relation); - return $this->localMacros[$method](...$parameters); - } + // Once we have the results, we just match those back up to their parent models + // using the relationship instance. Then we just return the finished arrays + // of models which have been eagerly hydrated and are readied for return. + return $relation->match($relation->initRelation($models, $name), $relation->getEager(), $name); + } - if (isset(static::$macros[$method])) { - if (static::$macros[$method] instanceof Closure) { - return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters); - } + /** + * Get the deeply nested relations for a given top-level relation. + */ + protected function relationsNestedUnder(string $relation): array + { + $nested = []; - return call_user_func_array(static::$macros[$method], $parameters); + // We are basically looking for any relationships that are nested deeper than + // the given top-level relationship. We will just check for any relations + // that start with the given top relations and adds them to our arrays. + foreach ($this->eagerLoad as $name => $constraints) { + if ($this->isNestedUnder($relation, $name)) { + $nested[substr($name, strlen($relation.'.'))] = $constraints; + } } - if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { - return $this->callScope([$this->model, $scope], $parameters); - } + return $nested; + } - if (in_array($method, $this->passthru, true)) { - return $this->toBase()->{$method}(...$parameters); + /** + * Determine if the relationship is nested. + */ + protected function isNestedUnder(string $relation, string $name): bool + { + return Str::contains($name, '.') && Str::startsWith($name, $relation.'.'); + } + + /** + * Apply the given scope on the current builder instance. + * + * @param array $parameters + * @return mixed + */ + protected function callScope(callable $scope, $parameters = []) + { + array_unshift($parameters, $this); + + $query = $this->getQuery(); + + // We will keep track of how many wheres are on the query before running the + // scope so that we can properly group the added scope constraints in the + // query as their own isolated nested where statement and avoid issues. + $originalWhereCount = $query->getWheres() === null + ? 0 : count($query->getWheres()); + + $result = $scope(...array_values($parameters)) ?? $this; + + if (count($query->getWheres()) > $originalWhereCount) { + $this->addNewWheresWithinGroup($query, $originalWhereCount); } - $this->query->{$method}(...$parameters); + return $result; + } - return $this; + /** + * Nest where conditions by slicing them at the given where count. + * + * @param \Illuminate\Database\Query\Builder $query + * @param int $originalWhereCount + */ + protected function addNewWheresWithinGroup(QueryBuilder $query, $originalWhereCount) + { + // Here, we totally remove all of the where clauses since we are going to + // rebuild them as nested queries by slicing the groups of wheres into + // their own sections. This is to prevent any confusing logic order. + $allWheres = $query->wheres; + + $query->wheres = []; + + $this->groupWhereSliceForScope($query, array_slice($allWheres, 0, $originalWhereCount)); + + $this->groupWhereSliceForScope($query, array_slice($allWheres, $originalWhereCount)); } /** - * Dynamically handle calls into the query instance. + * Slice where conditions at the given offset and add them to the query as a nested condition. * - * @param string $method - * @param array $parameters + * @param \Illuminate\Database\Query\Builder $query + * @param array $whereSlice + */ + protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice) + { + $whereBooleans = collect($whereSlice) + ->pluck('boolean'); + + // Here we'll check if the given subset of where clauses contains any "or" + // booleans and in this case create a nested where expression. That way + // we don't add any unnecessary nesting thus keeping the query clean. + if ($whereBooleans->contains('or')) { + $query->wheres[] = $this->createNestedWhere($whereSlice, $whereBooleans->first()); + } else { + $query->wheres = array_merge($query->wheres, $whereSlice); + } + } + + /** + * Create a where array with nested where conditions. * - * @throws \BadMethodCallException + * @param array $whereSlice + * @param string $boolean + * @return array + */ + protected function createNestedWhere($whereSlice, $boolean = 'and') + { + $whereGroup = $this->getQuery() + ->forNestedWhere(); + + $whereGroup->wheres = $whereSlice; + + return [ + 'type' => 'Nested', + 'query' => $whereGroup, + 'boolean' => $boolean, + ]; + } + + /** + * Parse a list of relations into individuals. * - * @return mixed + * @return array */ - public static function __callStatic($method, $parameters) + protected function parseWithRelations(array $relations) { - if ($method === 'macro') { - static::$macros[$parameters[0]] = $parameters[1]; + $results = []; - return null; - } + foreach ($relations as $name => $constraints) { + // If the "relation" value is actually a numeric key, we can assume that no + // constraints have been specified for the eager load and we'll just put + // an empty Closure with the loader so that we can treat all the same. + if (is_numeric($name)) { + $name = $constraints; - if (!isset(static::$macros[$method])) { - throw new BadMethodCallException("Method {$method} does not exist."); - } + [$name, $constraints] = Str::contains($name, ':') + ? $this->createSelectWithConstraint($name) + : [ + $name, + function () { + // + }, + ]; + } - if (static::$macros[$method] instanceof Closure) { - return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters); + // We need to separate out any nested includes. Which allows the developers + // to load deep relationships using "dots" without stating each level of + // the relationship with its own key in the array of eager load names. + $results = $this->addNestedWiths($name, $results); + + $results[$name] = $constraints; } - return call_user_func_array(static::$macros[$method], $parameters); + return $results; } /** - * Force a clone of the underlying query builder when cloning. + * Create a constraint to select the given columns for the relation. * - * @return void + * @param string $name + * @return array */ - public function __clone() + protected function createSelectWithConstraint($name) { - $this->query = clone $this->query; + return [ + explode(':', $name)[0], + function ($query) use ($name) { + $query->select(explode(',', explode(':', $name)[1])); + }, + ]; + } + + /** + * Parse the nested relationships in a relation. + * + * @param string $name + * @param array $results + * @return array + */ + protected function addNestedWiths($name, $results) + { + $progress = []; + + // If the relation has already been set on the result array, we will not set it + // again, since that would override any constraints that were already placed + // on the relationships. We will only set the ones that are not specified. + foreach (explode('.', $name) as $segment) { + $progress[] = $segment; + + if (! isset($results[$last = implode('.', $progress)])) { + $results[$last] = function () { + // + }; + } + } + + return $results; } } diff --git a/src/Database/Eloquent/Collection.php b/src/Database/Eloquent/Collection.php index 96a303d..10d4f97 100644 --- a/src/Database/Eloquent/Collection.php +++ b/src/Database/Eloquent/Collection.php @@ -14,7 +14,6 @@ class Collection extends \Illuminate\Database\Eloquent\Collection * * @param mixed $key * @param mixed $default - * * @return Model|static */ public function find($key, $default = null) @@ -42,8 +41,6 @@ public function find($key, $default = null) * @param mixed $key * @param mixed $operator * @param mixed $value - * - * @return bool */ public function contains($key, $operator = null, $value = null): bool { @@ -59,8 +56,6 @@ public function contains($key, $operator = null, $value = null): bool /** * Run a map over each of the items. * - * @param callable $callback - * * @return SupportCollection|static */ public function map(callable $callback) @@ -68,7 +63,7 @@ public function map(callable $callback) $result = SupportCollection::map($callback); return $result->contains(function ($item) { - return !$item instanceof Model; + return ! $item instanceof Model; }) ? $result->toBase() : $result; } } diff --git a/src/Database/Eloquent/Concerns/Common.php b/src/Database/Eloquent/Concerns/Common.php index 20a2dd8..9aa6ee0 100644 --- a/src/Database/Eloquent/Concerns/Common.php +++ b/src/Database/Eloquent/Concerns/Common.php @@ -8,10 +8,6 @@ trait Common { /** * Save the model to the database. - * - * @param array $options - * - * @return bool */ public function save(array $options = []): bool { diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index c69b1d1..4e3e2cd 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -21,9 +21,6 @@ use JsonSerializable; use Tinderbox\ClickhouseBuilder\Query\Grammar; -/** - * Class Model. - */ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable { use Concerns\HasAttributes; @@ -33,6 +30,13 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab use HidesAttributes; use GuardsAttributes; + /** + * Indicates if the model exists. + * + * @var bool + */ + public $exists = false; + /** * Indicates if an exception should be thrown when trying to access a missing attribute on a retrieved model. * @@ -89,17 +93,10 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab */ protected $perPage = 15; - /** - * Indicates if the model exists. - * - * @var bool - */ - public $exists = false; - /** * The connection resolver instance. * - * @var \Illuminate\Database\ConnectionResolverInterface + * @var Resolver */ protected static $resolver; @@ -119,10 +116,6 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab /** * Create a new Eloquent model instance. - * - * @param array $attributes - * - * @return void */ public function __construct(array $attributes = []) { @@ -134,53 +127,75 @@ public function __construct(array $attributes = []) } /** - * Check if the model needs to be booted and if so, do it. + * Dynamically retrieve attributes on the model. * - * @return void + * @param string $key + * @return mixed */ - protected function bootIfNotBooted() + public function __get($key) { - if (!isset(static::$booted[static::class])) { - static::$booted[static::class] = true; - - $this->fireModelEvent('booting', false); + return $this->getAttribute($key); + } - static::boot(); + /** + * Dynamically set attributes on the model. + * + * @param string $key + * @param mixed $value + */ + public function __set($key, $value) + { + $this->setAttribute($key, $value); + } - $this->fireModelEvent('booted', false); - } + /** + * Determine if an attribute or relation exists on the model. + * + * @param string $key + * @return bool + */ + public function __isset($key) + { + return $this->offsetExists($key); } /** - * The "booting" method of the model. + * Unset an attribute on the model. * - * @return void + * @param string $key */ - protected static function boot() + public function __unset($key) { - static::bootTraits(); + $this->offsetUnset($key); } /** - * Boot all of the bootable traits on the model. + * Handle dynamic method calls into the model. * - * @return void + * @param string $method + * @param array $parameters + * @return mixed */ - protected static function bootTraits() + public function __call($method, $parameters) { - $class = static::class; + return $this->newQuery() + ->{$method}(...$parameters); + } - foreach (class_uses_recursive($class) as $trait) { - if (method_exists($class, $method = 'boot'.class_basename($trait))) { - forward_static_call([$class, $method]); - } - } + /** + * Handle dynamic static method calls into the method. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public static function __callStatic($method, $parameters) + { + return (new static())->{$method}(...$parameters); } /** * Clear the list of booted models so they will be re-booted. - * - * @return void */ public static function clearBootedModels() { @@ -190,11 +205,9 @@ public static function clearBootedModels() /** * Fill the model with an array of attributes. * - * @param array $attributes - * - * @throws \Illuminate\Database\Eloquent\MassAssignmentException - * * @return $this + * + * @throws MassAssignmentException */ public function fill(array $attributes) { @@ -219,8 +232,6 @@ public function fill(array $attributes) /** * Fill the model with an array of attributes. Force mass assignment. * - * @param array $attributes - * * @return $this */ public function forceFill(array $attributes) @@ -230,24 +241,11 @@ public function forceFill(array $attributes) }); } - /** - * Remove the table name from a given key. - * - * @param string $key - * - * @return string - */ - protected function removeTableFromKey($key) - { - return Str::contains($key, '.') ? last(explode('.', $key)) : $key; - } - /** * Create a new instance of the given model. * * @param array $attributes * @param bool $exists - * * @return static */ public function newInstance($attributes = [], $exists = false) @@ -259,9 +257,7 @@ public function newInstance($attributes = [], $exists = false) $model->exists = $exists; - $model->setConnection( - $this->getConnectionName() - ); + $model->setConnection($this->getConnectionName()); return $model; } @@ -269,9 +265,6 @@ public function newInstance($attributes = [], $exists = false) /** * Create a new model instance that is existing. * - * @param array $attributes - * @param string|null $connection - * * @return static */ public function newFromBuilder(array $attributes = [], string $connection = null) @@ -280,7 +273,9 @@ public function newFromBuilder(array $attributes = [], string $connection = null $model->setRawAttributes($attributes, true); - $model->setConnection($connection ?: $this->getConnectionName()); + $model->setConnection( + $connection !== null && $connection !== '' && $connection !== '0' ? $connection : $this->getConnectionName() + ); $model->fireModelEvent('retrieved', false); @@ -294,21 +289,20 @@ public function newFromBuilder(array $attributes = [], string $connection = null */ public static function all() { - return (new static())->newQuery()->get(); + return (new static())->newQuery() + ->get(); } /** * Begin querying a model with eager loading. * * @param array|string $relations - * * @return Builder|static */ public static function with($relations) { - return (new static())->newQuery()->with( - is_string($relations) ? func_get_args() : $relations - ); + return (new static())->newQuery() + ->with(is_string($relations) ? func_get_args() : $relations); } public static function query(): Builder @@ -342,20 +336,8 @@ public function newEloquentBuilder(QueryBuilder $query): Builder return new Builder($query); } - protected function newBaseQueryBuilder(): QueryBuilder - { - /** @var Connection $connection */ - $connection = $this->getConnection(); - - return new QueryBuilder($connection, new Grammar()); - } - /** * Create a new Eloquent Collection instance. - * - * @param array $models - * - * @return Collection */ public function newCollection(array $models = []): Collection { @@ -364,8 +346,6 @@ public function newCollection(array $models = []): Collection /** * Convert the model instance to an array. - * - * @return array */ public function toArray(): array { @@ -377,15 +357,13 @@ public function toArray(): array * * @param int $options * - * @throws \Illuminate\Database\Eloquent\JsonEncodingException - * - * @return string + * @throws JsonEncodingException */ public function toJson($options = 0): string { $json = json_encode($this->jsonSerialize(), $options); - if (JSON_ERROR_NONE !== json_last_error()) { + if (json_last_error() !== JSON_ERROR_NONE) { throw JsonEncodingException::forModel($this, json_last_error_msg()); } @@ -394,8 +372,6 @@ public function toJson($options = 0): string /** * Convert the object into something JSON serializable. - * - * @return array */ public function jsonSerialize(): array { @@ -404,8 +380,6 @@ public function jsonSerialize(): array /** * Get the database connection for the model. - * - * @return \Illuminate\Database\Connection */ public function getConnection(): \Illuminate\Database\Connection { @@ -414,8 +388,6 @@ public function getConnection(): \Illuminate\Database\Connection /** * Get the current connection name for the model. - * - * @return string */ public function getConnectionName(): string { @@ -425,8 +397,6 @@ public function getConnectionName(): string /** * Set the connection associated with the model. * - * @param string $name - * * @return $this */ public function setConnection(string $name) @@ -439,8 +409,6 @@ public function setConnection(string $name) /** * Resolve a connection instance. * - * @param string|null $connection - * * @return Connection|\Illuminate\Database\ConnectionInterface */ public static function resolveConnection(string $connection = null) @@ -450,8 +418,6 @@ public static function resolveConnection(string $connection = null) /** * Get the connection resolver instance. - * - * @return ConnectionResolverInterface */ public static function getConnectionResolver(): ConnectionResolverInterface { @@ -460,10 +426,6 @@ public static function getConnectionResolver(): ConnectionResolverInterface /** * Set the connection resolver instance. - * - * @param \Illuminate\Database\ConnectionResolverInterface $resolver - * - * @return void */ public static function setConnectionResolver(Resolver $resolver): void { @@ -472,17 +434,11 @@ public static function setConnectionResolver(Resolver $resolver): void /** * Get the table associated with the model. - * - * @return string */ public function getTable(): string { - if (!isset($this->table)) { - $this->setTable(str_replace( - '\\', - '', - Str::snake(Str::plural(class_basename($this))) - )); + if (! isset($this->table)) { + $this->setTable(str_replace('\\', '', Str::snake(Str::plural(class_basename($this))))); } return $this->table; @@ -491,8 +447,6 @@ public function getTable(): string /** * Set the table associated with the model. * - * @param string $table - * * @return $this */ public function setTable(string $table): self @@ -504,8 +458,6 @@ public function setTable(string $table): self /** * Get the primary key for the model. - * - * @return string */ public function getKeyName(): string { @@ -515,8 +467,6 @@ public function getKeyName(): string /** * Set the primary key for the model. * - * @param string $key - * * @return $this */ public function setKeyName(string $key): self @@ -528,8 +478,6 @@ public function setKeyName(string $key): self /** * Get the table qualified key name. - * - * @return string */ public function getQualifiedKeyName(): string { @@ -538,8 +486,6 @@ public function getQualifiedKeyName(): string /** * Get the pk key type. - * - * @return string */ public function getKeyType(): string { @@ -549,8 +495,6 @@ public function getKeyType(): string /** * Set the data type for the primary key. * - * @param string $type - * * @return $this */ public function setKeyType(string $type) @@ -572,8 +516,6 @@ public function getKey() /** * Get the default foreign key name for the model. - * - * @return string */ public function getForeignKey(): string { @@ -582,8 +524,6 @@ public function getForeignKey(): string /** * Get the number of models to return per page. - * - * @return int */ public function getPerPage(): int { @@ -593,8 +533,6 @@ public function getPerPage(): int /** * Set the number of models to return per page. * - * @param int $perPage - * * @return $this */ public function setPerPage(int $perPage): self @@ -604,37 +542,10 @@ public function setPerPage(int $perPage): self return $this; } - /** - * Dynamically retrieve attributes on the model. - * - * @param string $key - * - * @return mixed - */ - public function __get($key) - { - return $this->getAttribute($key); - } - - /** - * Dynamically set attributes on the model. - * - * @param string $key - * @param mixed $value - * - * @return void - */ - public function __set($key, $value) - { - $this->setAttribute($key, $value); - } - /** * Determine if the given attribute exists. * * @param mixed $offset - * - * @return bool */ public function offsetExists($offset): bool { @@ -645,7 +556,6 @@ public function offsetExists($offset): bool * Get the value for a given offset. * * @param mixed $offset - * * @return mixed */ #[\ReturnTypeWillChange] @@ -659,8 +569,6 @@ public function offsetGet($offset) * * @param mixed $offset * @param mixed $value - * - * @return void */ public function offsetSet($offset, $value): void { @@ -671,66 +579,71 @@ public function offsetSet($offset, $value): void * Unset the value for a given offset. * * @param mixed $offset - * - * @return void */ public function offsetUnset($offset): void { unset($this->attributes[$offset]); } + public static function preventsAccessingMissingAttributes(): bool + { + return static::$modelsShouldPreventAccessingMissingAttributes; + } + /** - * Determine if an attribute or relation exists on the model. - * - * @param string $key - * - * @return bool + * Check if the model needs to be booted and if so, do it. */ - public function __isset($key) + protected function bootIfNotBooted() { - return $this->offsetExists($key); + if (! isset(static::$booted[static::class])) { + static::$booted[static::class] = true; + + $this->fireModelEvent('booting', false); + + static::boot(); + + $this->fireModelEvent('booted', false); + } } /** - * Unset an attribute on the model. - * - * @param string $key - * - * @return void + * The "booting" method of the model. */ - public function __unset($key) + protected static function boot() { - $this->offsetUnset($key); + static::bootTraits(); } /** - * Handle dynamic method calls into the model. - * - * @param string $method - * @param array $parameters - * - * @return mixed + * Boot all of the bootable traits on the model. */ - public function __call($method, $parameters) + protected static function bootTraits() { - return $this->newQuery()->$method(...$parameters); + $class = static::class; + + foreach (class_uses_recursive($class) as $trait) { + if (method_exists($class, $method = 'boot'.class_basename($trait))) { + forward_static_call([$class, $method]); + } + } } /** - * Handle dynamic static method calls into the method. - * - * @param string $method - * @param array $parameters + * Remove the table name from a given key. * - * @return mixed + * @param string $key + * @return string */ - public static function __callStatic($method, $parameters) + protected function removeTableFromKey($key) { - return (new static())->$method(...$parameters); + return Str::contains($key, '.') ? last(explode('.', $key)) : $key; } - public static function preventsAccessingMissingAttributes(): bool + protected function newBaseQueryBuilder(): QueryBuilder { - return static::$modelsShouldPreventAccessingMissingAttributes; + /** @var Connection $connection */ + $connection = $this->getConnection(); + + return new QueryBuilder($connection, new Grammar()); } } diff --git a/src/Database/Query/Builder.php b/src/Database/Query/Builder.php index b2645bb..9a9d090 100644 --- a/src/Database/Query/Builder.php +++ b/src/Database/Query/Builder.php @@ -14,7 +14,7 @@ class Builder extends BaseBuilder { - use Macroable { + use Macroable { __call as macroCall; } @@ -32,12 +32,10 @@ public function __construct( * Perform compiled from builder sql query and getting result. * * @throws \Tinderbox\Clickhouse\Exceptions\ClientException - * - * @return Collection */ public function get(): Collection { - if (!empty($this->async)) { + if ($this->async !== []) { $result = $this->connection->selectAsync($this->toAsyncSqls()); } else { $result = $this->connection->select($this->toSql(), [], $this->getFiles()); @@ -53,12 +51,10 @@ public function get(): Collection * @param string $column Column to pass into count() aggregate function * * @throws \Tinderbox\Clickhouse\Exceptions\ClientException - * - * @return int */ public function count($column = '*'): int { - $builder = $this->getCountQuery($column); + $builder = $this->getCountQuery(); $result = $builder->get(); if (count($this->groups) > 0) { @@ -71,19 +67,18 @@ public function count($column = '*'): int /** * Perform query and get first row. * - * @throws \Tinderbox\Clickhouse\Exceptions\ClientException - * * @return mixed|null + * + * @throws \Tinderbox\Clickhouse\Exceptions\ClientException */ public function first() { - return $this->get()->first(); + return $this->get() + ->first(); } /** * Makes clean instance of builder. - * - * @return self */ public function newQuery(): self { @@ -93,19 +88,13 @@ public function newQuery(): self /** * Insert in table data from files. * - * @param array $columns - * @param array $files - * @param string $format - * @param int $concurrency - * * @throws \Tinderbox\Clickhouse\Exceptions\ClientException - * - * @return array */ public function insertFiles(array $columns, array $files, string $format = Format::CSV, int $concurrency = 5): array { return $this->connection->insertFiles( - (string) $this->getFrom()->getTable(), + (string) $this->getFrom() + ->getTable(), $columns, $files, $format, @@ -115,37 +104,27 @@ public function insertFiles(array $columns, array $files, string $format = Forma /** * Performs insert query. - * - * @param array $values - * - * @return bool */ public function insert(array $values): bool { - if (empty($values)) { + if ($values === []) { return false; } - if (!is_array(reset($values))) { + if (! is_array(reset($values))) { $values = [$values]; } // Here, we will sort the insert keys for every record so that each insert is // in the same order for the record. We need to make sure this is the case // so there are not any errors or problems when inserting these records. - foreach ($values as $key => &$value) { + foreach ($values as &$value) { ksort($value); } - return $this->connection->insert( - $this->grammar->compileInsert($this, $values), - Arr::flatten($values) - ); + return $this->connection->insert($this->grammar->compileInsert($this, $values), Arr::flatten($values)); } - /** - * @return Connection - */ public function getConnection(): Connection { return $this->connection; diff --git a/src/Database/Query/PdoInterface.php b/src/Database/Query/PdoInterface.php index 259ea73..c809688 100644 --- a/src/Database/Query/PdoInterface.php +++ b/src/Database/Query/PdoInterface.php @@ -7,4 +7,4 @@ interface PdoInterface { public function quote(mixed $binding): mixed; -} \ No newline at end of file +} diff --git a/tests/BaseEloquentModelCasting.php b/tests/BaseEloquentModelCasting.php index bfe436b..5f3426b 100644 --- a/tests/BaseEloquentModelCasting.php +++ b/tests/BaseEloquentModelCasting.php @@ -9,22 +9,20 @@ class BaseEloquentModelCasting extends BaseEloquentModel use Helpers; protected $casts = [ - 'intAttribute' => 'int', - 'floatAttribute' => 'float', - 'stringAttribute' => 'string', - 'boolAttribute' => 'bool', - 'booleanAttribute' => 'boolean', - 'objectAttribute' => 'object', - 'arrayAttribute' => 'array', - 'jsonAttribute' => 'json', - 'dateAttribute' => 'date', - 'datetimeAttribute' => 'datetime', + 'intAttribute' => 'int', + 'floatAttribute' => 'float', + 'stringAttribute' => 'string', + 'boolAttribute' => 'bool', + 'booleanAttribute' => 'boolean', + 'objectAttribute' => 'object', + 'arrayAttribute' => 'array', + 'jsonAttribute' => 'json', + 'dateAttribute' => 'date', + 'datetimeAttribute' => 'datetime', 'timestampAttribute' => 'timestamp', ]; - protected $dates = [ - 'payed_at', - ]; + protected $dates = ['payed_at']; public function jsonAttributeValue() { diff --git a/tests/Unit/Database/ConnectionTest.php b/tests/Unit/Database/ConnectionTest.php index 225665c..2d6d956 100644 --- a/tests/Unit/Database/ConnectionTest.php +++ b/tests/Unit/Database/ConnectionTest.php @@ -16,22 +16,16 @@ class ConnectionTest extends TestCase */ protected $connection; - /** - * @return void - */ - public function setUp(): void + protected function setUp(): void { parent::setUp(); $this->connection = new Connection([ - 'host' => 'localhost', - 'port' => '8123', + 'host' => 'localhost', + 'port' => '8123', 'database' => 'default', ]); } - /** - * @return void - */ public function testQuery(): void { self::assertInstanceOf(Builder::class, $this->connection->query()); @@ -39,22 +33,14 @@ public function testQuery(): void /** * @throws ClientException - * - * @return void */ public function testSystemEvents(): void { - self::assertIsNumeric( - $this->connection->query() - ->table('system.events') - ->count() - ); + self::assertIsNumeric($this->connection->query()->table('system.events')->count()); } /** * @throws ClientException - * - * @return void */ public function testMyDatabase(): void { @@ -77,9 +63,18 @@ public function testMyDatabase(): void self::assertTrue($result); $values = [ - ['timestamp' => '2019-01-01 00:00:00', 'event_id' => 1], - ['event_id' => 2, 'timestamp' => '2020-01-01 00:00:00'], - ['event_id' => 3, 'timestamp' => 1546300800], + [ + 'timestamp' => '2019-01-01 00:00:00', + 'event_id' => 1, + ], + [ + 'event_id' => 2, + 'timestamp' => '2020-01-01 00:00:00', + ], + [ + 'event_id' => 3, + 'timestamp' => 1546300800, + ], ]; $this->connection->query() ->table('tests.dt') diff --git a/tests/Unit/Database/Eloquent/BuilderTest.php b/tests/Unit/Database/Eloquent/BuilderTest.php index 76b4191..2371fd5 100644 --- a/tests/Unit/Database/Eloquent/BuilderTest.php +++ b/tests/Unit/Database/Eloquent/BuilderTest.php @@ -34,7 +34,9 @@ class BuilderTest extends TestCase * @var MockInterface&Connection */ private MockInterface $connection; + private Builder $builder; + private BaseEloquentModelCasting $model; protected function setUp(): void @@ -51,11 +53,13 @@ protected function setUp(): void public function testWhereKey(): void { - $id = $this->faker()->numberBetween(1); + $id = $this->faker() + ->numberBetween(1); $this->builder->whereKey($id); - $wheres = $this->builder->getQuery()->getWheres(); + $wheres = $this->builder->getQuery() + ->getWheres(); self::assertCount(1, $wheres); /** @var TwoElementsLogicExpression $expression */ @@ -77,7 +81,8 @@ public function testWhereKeyNot(): void $this->builder->whereKeyNot($ids); - $wheres = $this->builder->getQuery()->getWheres(); + $wheres = $this->builder->getQuery() + ->getWheres(); self::assertCount(1, $wheres); /** @var TwoElementsLogicExpression $expression */ @@ -97,10 +102,12 @@ public function testWhereKeyNot(): void public function testWhereSimple(): void { - $date = $this->faker()->date(); + $date = $this->faker() + ->date(); $this->builder->where('date_column', '>', $date); - $wheres = $this->builder->getQuery()->getWheres(); + $wheres = $this->builder->getQuery() + ->getWheres(); self::assertCount(1, $wheres); /** @var TwoElementsLogicExpression $expression */ @@ -138,22 +145,23 @@ public function testWhereClosure(): void public function testOrWhere(): void { - $id = $this->faker()->numberBetween(1); - $date = $this->faker()->date(); + $id = $this->faker() + ->numberBetween(1); + $date = $this->faker() + ->date(); $this->builder->where('id', $id); $this->builder->orWhere('date_column', '>', $date); $sql = $this->builder->toSql(); - self::assertSame( - 'SELECT * FROM `test_table` WHERE `id` = '.$id.' OR `date_column` > \''.$date.'\'', - $sql - ); + self::assertSame('SELECT * FROM `test_table` WHERE `id` = '.$id.' OR `date_column` > \''.$date.'\'', $sql); } public function testFind(): void { - $id = $this->faker()->numberBetween(1); - $stringAttribute = $this->faker()->word(); + $id = $this->faker() + ->numberBetween(1); + $stringAttribute = $this->faker() + ->word(); $this->connection ->shouldReceive('getName') @@ -162,7 +170,10 @@ public function testFind(): void $this->connection ->shouldReceive('select') ->andReturn([ - ['id' => $id, 'stringAttribute' => $stringAttribute], + [ + 'id' => $id, + 'stringAttribute' => $stringAttribute, + ], ]); $model = $this->builder->find($id); @@ -174,7 +185,8 @@ public function testFind(): void public function testFindMany(): void { - $ids = collect()->times(5); + $ids = collect() + ->times(5); $this->connection ->shouldReceive('getName') @@ -182,13 +194,11 @@ public function testFindMany(): void $this->connection ->shouldReceive('select') - ->andReturn( - $ids - ->map(function ($id) { - return ['id' => $id]; - }) - ->toArray() - ); + ->andReturn($ids->map(function ($id) { + return [ + 'id' => $id, + ]; + })->toArray()); $models = $this->builder->findMany($ids->toArray()); @@ -214,19 +224,28 @@ public function testFindOrFail(): void public function testGet(): void { $connectionResultRow = [ - 'id' => $this->faker()->randomDigit(), - 'intAttribute' => (string) $this->faker()->randomDigit(), - 'floatAttribute' => (string) $this->faker()->randomFloat(2), - 'stringAttribute' => $this->faker()->randomDigit(), - 'boolAttribute' => 1, + 'id' => $this->faker() + ->randomDigit(), + 'intAttribute' => (string) $this->faker() + ->randomDigit(), + 'floatAttribute' => (string) $this->faker() + ->randomFloat(2), + 'stringAttribute' => $this->faker() + ->randomDigit(), + 'boolAttribute' => 1, 'booleanAttribute' => 1, - 'objectAttribute' => json_encode([ - $this->faker()->word() => $this->faker()->randomLetter() + 'objectAttribute' => json_encode([ + $this->faker() + ->word() => $this->faker() + ->randomLetter(), ]), - 'arrayAttribute' => json_encode(range(1, 5)), - 'dateAttribute' => now()->toDateTimeString(), - 'datetimeAttribute' => now()->toDateString(), - 'timestampAttribute' => now()->toDateString(), + 'arrayAttribute' => json_encode(range(1, 5)), + 'dateAttribute' => now() + ->toDateTimeString(), + 'datetimeAttribute' => now() + ->toDateString(), + 'timestampAttribute' => now() + ->toDateString(), ]; $connectionResultRow['jsonAttribute'] = json_encode($connectionResultRow['arrayAttribute']); @@ -236,9 +255,7 @@ public function testGet(): void $this->connection ->shouldReceive('select') - ->andReturn([ - $connectionResultRow, - ]); + ->andReturn([$connectionResultRow]); $collection = $this->builder->get(); diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index 50d0713..0a7581d 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -26,6 +26,7 @@ class CollectionTest extends TestCase * @var MockInterface&Connection */ private MockInterface $connection; + private Builder $builder; protected function setUp(): void @@ -50,7 +51,9 @@ public function testMapModelToModel(): void { $connectionResult = collect() ->times(5, function (int $id) { - return ['id' => $id]; + return [ + 'id' => $id, + ]; }); $this->connection @@ -80,7 +83,9 @@ public function testMapModelToArray(): void { $connectionResult = collect() ->times(5, function (int $id) { - return ['id' => $id]; + return [ + 'id' => $id, + ]; }); $this->connection @@ -92,7 +97,7 @@ public function testMapModelToArray(): void $collection = BaseEloquentModelCasting::all() ->map(function (BaseEloquentModelCasting $model) use ($now) { return [ - 'id' => $model->id, + 'id' => $model->id, 'datetimeAttribute' => $now, ]; }); @@ -107,16 +112,14 @@ public function testMapModelToArray(): void }); } - /** - * @dataProvider findDataProvider - * - * @param $key - */ + #[\PHPUnit\Framework\Attributes\DataProvider('findDataProvider')] public function testFind($key): void { $connectionResult = collect() ->times(5, function (int $id) { - return ['id' => $id]; + return [ + 'id' => $id, + ]; }); $this->connection @@ -134,18 +137,17 @@ public function testFind($key): void } /** - * @dataProvider containsDataProvider - * - * @param bool $expected - * @param $key * @param null $operator * @param null $value */ + #[\PHPUnit\Framework\Attributes\DataProvider('containsDataProvider')] public function testContains(bool $expected, $key, $operator = null, $value = null): void { $connectionResult = collect() ->times(5, function (int $id) { - return ['id' => $id]; + return [ + 'id' => $id, + ]; }); $this->connection @@ -166,8 +168,9 @@ public function testGet(): void $connectionResult = collect() ->times(5, function (int $id) { return [ - 'id' => $id, - 'floatAttribute' => (string) $this->faker()->randomFloat(2), + 'id' => $id, + 'floatAttribute' => (string) $this->faker() + ->randomFloat(2), ]; }); @@ -199,22 +202,15 @@ public static function findDataProvider(): array { return [ [5], - [ - tap(new BaseEloquentModelCasting(), function (BaseEloquentModelCasting $model) { - $model->id = 5; - }), - ], + [tap(new BaseEloquentModelCasting(), function (BaseEloquentModelCasting $model) { + $model->id = 5; + }), ], [1, 5], ]; } public static function containsDataProvider() { - return [ - [true, 5], - [false, 6], - [true, 'id', '>=', 5], - [false, 'id', '>=', 6], - ]; + return [[true, 5], [false, 6], [true, 'id', '>=', 5], [false, 'id', '>=', 6]]; } } diff --git a/tests/Unit/Database/Eloquent/ModelTest.php b/tests/Unit/Database/Eloquent/ModelTest.php index 3cc275e..c9160be 100644 --- a/tests/Unit/Database/Eloquent/ModelTest.php +++ b/tests/Unit/Database/Eloquent/ModelTest.php @@ -4,8 +4,8 @@ namespace Bavix\LaravelClickHouse\Tests\Unit\Database\Eloquent; -use Bavix\LaravelClickHouse\Tests\BaseEloquentModelCasting; use Bavix\LaravelClickHouse\Tests\BaseEloquentModel; +use Bavix\LaravelClickHouse\Tests\BaseEloquentModelCasting; use Bavix\LaravelClickHouse\Tests\BaseEloquentModelWith; use Bavix\LaravelClickHouse\Tests\Helpers; use Illuminate\Database\Eloquent\MassAssignmentException; @@ -35,7 +35,11 @@ public function testDirtyAttributes(): void { $this->expectException(MassAssignmentException::class); - new BaseEloquentModel(['foo' => '1', 'bar' => 2, 'baz' => 3]); + new BaseEloquentModel([ + 'foo' => '1', + 'bar' => 2, + 'baz' => 3, + ]); } public function testDirtyOnCastOrDateAttributes(): void diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index a96cb4a..a31a1c1 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -25,6 +25,7 @@ class BuilderTest extends TestCase * @var MockInterface&Connection */ private MockInterface $connection; + private Builder $builder; protected function setUp(): void @@ -32,16 +33,14 @@ protected function setUp(): void parent::setUp(); $this->connection = $this->mock(Connection::class); - $this->builder = new Builder( - $this->connection, - new Grammar() - ); + $this->builder = new Builder($this->connection, new Grammar()); $this->builder->from($this->faker()->word()); } public function testGet(): void { - $connectionResult = $this->faker()->shuffle(range(1, 5)); + $connectionResult = $this->faker() + ->shuffle(range(1, 5)); $this->connection ->shouldReceive('select') @@ -59,7 +58,9 @@ public function testCount(): void $this->connection ->shouldReceive('select') - ->andReturn([['count' => count($connectionResult)]]); + ->andReturn([[ + 'count' => count($connectionResult), + ]]); $builderResult = $this->builder->count(); @@ -68,7 +69,8 @@ public function testCount(): void public function testFirst(): void { - $connectionResult = $this->faker()->shuffle(range(1, 5)); + $connectionResult = $this->faker() + ->shuffle(range(1, 5)); $this->connection ->shouldReceive('select') @@ -99,16 +101,23 @@ public function testInsert(): void self::assertFalse($this->builder->insert([])); $insertedRow = [ - $this->faker()->word() => $this->faker()->randomDigit(), - $this->faker()->randomLetter() => $this->faker()->randomDigit(), - $this->faker()->numerify('column_#') => $this->faker()->randomLetter(), + $this->faker() + ->word() => $this->faker() + ->randomDigit(), + $this->faker() + ->randomLetter() => $this->faker() + ->randomDigit(), + $this->faker() + ->numerify('column_#') => $this->faker() + ->randomLetter(), ]; \ksort($insertedRow); $inserted = [$insertedRow]; $generatedSql = sprintf( 'INSERT INTO `%s` (%s) FORMAT %s (%s)', - $this->builder->getFrom()->getTable(), + $this->builder->getFrom() + ->getTable(), collect($insertedRow) ->keys() ->map(function (string $columnName) { @@ -128,7 +137,9 @@ public function testInsert(): void ->implode(', ') ); - $values = collect($insertedRow)->values()->toArray(); + $values = collect($insertedRow) + ->values() + ->toArray(); $this->connection ->shouldReceive('insert') ->withArgs([$generatedSql, $values]) From 282e61d4308532c66199b68d686f1f340dee4eb8 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Fri, 15 Mar 2024 00:20:56 +0300 Subject: [PATCH 49/69] generate baseline --- phpstan.baseline.neon | 971 ++++++++++++++++++++++++++++++++++++++++++ phpstan.neon | 1 + 2 files changed, 972 insertions(+) create mode 100644 phpstan.baseline.neon diff --git a/phpstan.baseline.neon b/phpstan.baseline.neon new file mode 100644 index 0000000..825e05f --- /dev/null +++ b/phpstan.baseline.neon @@ -0,0 +1,971 @@ +parameters: + ignoreErrors: + - + message: "#^Cannot access offset 'db' on Illuminate\\\\Contracts\\\\Foundation\\\\Application\\.$#" + count: 1 + path: src/ClickHouseServiceProvider.php + + - + message: "#^Cannot access offset 'events' on Illuminate\\\\Contracts\\\\Foundation\\\\Application\\.$#" + count: 1 + path: src/ClickHouseServiceProvider.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\ClickHouseServiceProvider is neither abstract nor final\\.$#" + count: 1 + path: src/ClickHouseServiceProvider.php + + - + message: "#^PHPDoc tag @throws has invalid value \\(\\)\\: Unexpected token \"\\\\n \", expected type at offset 18$#" + count: 1 + path: src/ClickHouseServiceProvider.php + + - + message: "#^Class \"Bavix\\\\LaravelClickHouse\\\\Database\\\\Connection\" is not allowed to extend \"Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\"\\.$#" + count: 1 + path: src/Database/Connection.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Connection is neither abstract nor final\\.$#" + count: 1 + path: src/Database/Connection.php + + - + message: "#^Access to protected property Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:\\$wheres\\.$#" + count: 5 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:forPage\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:forPageAfterId\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:skip\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:forNestedWhere\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Cannot call method getQuery\\(\\) on mixed\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder is neither abstract nor final\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Language construct isset\\(\\) should not be used\\.$#" + count: 5 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:__call\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:__callStatic\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:addNestedWiths\\(\\) has parameter \\$results with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:addNestedWiths\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:addNewWheresWithinGroup\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:callScope\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) has parameter \\$whereSlice with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createSelectWithConstraint\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelation\\(\\) has parameter \\$models with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelation\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelations\\(\\) has parameter \\$models with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelations\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:find\\(\\) should return array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\|null but returns object\\|null\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findMany\\(\\) has parameter \\$ids with generic interface Illuminate\\\\Contracts\\\\Support\\\\Arrayable but does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findMany\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findOrFail\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model but returns array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findOrFail\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model but returns array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\|null\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:fromQuery\\(\\) has parameter \\$bindings with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getEagerLoads\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getMacro\\(\\) should return Closure but returns mixed\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getModels\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getRelation\\(\\) return type with generic class Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation does not specify its types\\: TRelatedModel$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getRelation\\(\\) should return Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation but returns mixed\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:groupWhereSliceForScope\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:groupWhereSliceForScope\\(\\) has parameter \\$whereSlice with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:hydrate\\(\\) has parameter \\$items with no value type specified in iterable type iterable\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:newModelInstance\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:orWhere\\(\\) has parameter \\$column with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:paginate\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:paginate\\(\\) return type with generic interface Illuminate\\\\Contracts\\\\Pagination\\\\LengthAwarePaginator does not specify its types\\: TItem$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:parseWithRelations\\(\\) has parameter \\$relations with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:parseWithRelations\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:pluck\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:relationsNestedUnder\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:scopes\\(\\) has parameter \\$scopes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:setEagerLoads\\(\\) has parameter \\$eagerLoad with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:setModel\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:setQuery\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:simplePaginate\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:simplePaginate\\(\\) return type with generic interface Illuminate\\\\Contracts\\\\Pagination\\\\Paginator does not specify its types\\: TItem$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:toBase\\(\\) should return Illuminate\\\\Database\\\\Query\\\\Builder but returns Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:where\\(\\) has parameter \\$column with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^PHPDoc tag @param for parameter \\$query with type Illuminate\\\\Database\\\\Query\\\\Builder is incompatible with native type Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\.$#" + count: 2 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$array of function array_flip expects array\\, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$builder of method Illuminate\\\\Database\\\\Eloquent\\\\Scope\\:\\:apply\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder, Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, Closure\\|null given\\.$#" + count: 2 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$column of method Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\\:\\:where\\(\\) expects Closure\\|string\\|Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\\|Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\TwoElementsLogicExpression, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$model of method Illuminate\\\\Database\\\\Eloquent\\\\ModelNotFoundException\\\\:\\:setModel\\(\\) expects class\\-string\\, class\\-string\\ given\\.$#" + count: 2 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$name of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setConnection\\(\\) expects string, string\\|null given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$relations of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:parseWithRelations\\(\\) expects array, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$scope of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:callScope\\(\\) expects callable\\(\\)\\: mixed, array\\{Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model, non\\-falsy\\-string\\} given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\|null given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\|Illuminate\\\\Contracts\\\\Support\\\\Arrayable given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#2 \\$boolean of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) expects string, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#2 \\$ids of method Illuminate\\\\Database\\\\Eloquent\\\\ModelNotFoundException\\\\:\\:setModel\\(\\) expects array\\\\|int\\|string, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#2 \\$model of method Illuminate\\\\Database\\\\Eloquent\\\\Scope\\:\\:apply\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Model, Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Parameter \\#3 \\$tables of method Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\\:\\:select\\(\\) expects array, true given\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$eagerLoad type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$localMacros type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$macros type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$passthru type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$scopes type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Property Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\\:\\:\\$wheres \\(array\\\\) does not accept array\\\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Strict comparison using \\=\\=\\= between Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model and null will always evaluate to false\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Strict comparison using \\=\\=\\= between array and null will always evaluate to false\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Cannot call method getKeyName\\(\\) on Illuminate\\\\Database\\\\Eloquent\\\\Model\\|null\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Class \"Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\" is not allowed to extend \"Illuminate\\\\Database\\\\Eloquent\\\\Collection\"\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection extends generic class Illuminate\\\\Database\\\\Eloquent\\\\Collection but does not specify its types\\: TKey, TModel$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection is neither abstract nor final\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\:\\:find\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\) but returns mixed\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\:\\:map\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Parameter \\#1 \\$key of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:contains\\(\\) expects \\(callable\\(Illuminate\\\\Database\\\\Eloquent\\\\Model, int\\|string\\)\\: bool\\)\\|Illuminate\\\\Database\\\\Eloquent\\\\Model\\|string, Closure\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\)\\: bool given\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Parameter \\#1 \\$key of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:contains\\(\\) expects \\(callable\\(Illuminate\\\\Database\\\\Eloquent\\\\Model, int\\|string\\)\\: bool\\)\\|Illuminate\\\\Database\\\\Eloquent\\\\Model\\|string, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Parameter \\#2 \\$callback of static method Illuminate\\\\Support\\\\Arr\\:\\:first\\(\\) expects \\(callable\\(Illuminate\\\\Database\\\\Eloquent\\\\Model, int\\|string\\)\\: bool\\)\\|null, Closure\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\)\\: bool given\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Collection.php + + - + message: "#^Call to an undefined static method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:insert\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model implements generic interface ArrayAccess but does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model implements generic interface Illuminate\\\\Contracts\\\\Support\\\\Arrayable but does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Constructor in Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model has parameter \\$attributes with default value\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Language construct isset\\(\\) should not be used\\.$#" + count: 2 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__call\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__call\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__callStatic\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__callStatic\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__construct\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__get\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__isset\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__set\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__unset\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:all\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:boot\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:boot\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootIfNotBooted\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootIfNotBooted\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootTraits\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootTraits\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:clearBootedModels\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:clearBootedModels\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:fill\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:fill\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:forceFill\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:forceFill\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:forceFill\\(\\) should return \\$this\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\) but returns mixed\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getCasts\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getCasts\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnection\\(\\) should return Illuminate\\\\Database\\\\Connection but returns Illuminate\\\\Database\\\\ConnectionInterface\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnectionName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnectionResolver\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getDateFormat\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getDates\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getDates\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getForeignKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getKeyType\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getPerPage\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getQualifiedKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getTable\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:jsonSerialize\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:jsonSerialize\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newBaseQueryBuilder\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newCollection\\(\\) has parameter \\$models with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newCollection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newEloquentBuilder\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newFromBuilder\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newFromBuilder\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newInstance\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newInstance\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQuery\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQueryWithoutScope\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQueryWithoutScope\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQueryWithoutScopes\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetExists\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetGet\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetSet\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetUnset\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:preventsAccessingMissingAttributes\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:query\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:removeTableFromKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:removeTableFromKey\\(\\) should return string but returns mixed\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:save\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:save\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setConnectionResolver\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setKeyType\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setPerPage\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setTable\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:toArray\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:toJson\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:toJson\\(\\) should return string but returns string\\|false\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:with\\(\\) has parameter \\$relations with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:with\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Parameter \\#1 \\$callback of function forward_static_call expects callable\\(\\)\\: mixed, array\\{class\\-string\\, non\\-falsy\\-string\\} given\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Parameter \\#1 \\$key of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getAttribute\\(\\) expects string, mixed given\\.$#" + count: 2 + path: src/Database/Eloquent/Model.php + + - + message: "#^Parameter \\#1 \\$key of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setAttribute\\(\\) expects string, mixed given\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$booted type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$dateFormat \\(string\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$table \\(string\\) in isset\\(\\) is not nullable\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$with type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$withCount type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 5 + path: src/Database/Eloquent/Model.php + + - + message: "#^Cannot access offset 'count' on mixed\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Cannot call method getTable\\(\\) on Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\From\\|null\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Cannot cast mixed to int\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Class \"Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\" is not allowed to extend \"Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\"\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder is neither abstract nor final\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:get\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insert\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insertFiles\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insertFiles\\(\\) has parameter \\$files with no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insertFiles\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Unable to resolve the template type TKey in call to function collect$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Unable to resolve the template type TValue in call to function collect$#" + count: 1 + path: src/Database/Query/Builder.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Database/Query/Builder.php diff --git a/phpstan.neon b/phpstan.neon index 8da6d34..0d78f1e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ includes: - phpstan.common.neon + - phpstan.baseline.neon parameters: level: 9 From 3f3f214f4b017183cf1cfe208a2a54a73832ab76 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Fri, 15 Mar 2024 00:23:29 +0300 Subject: [PATCH 50/69] check laravel ^10.0 and ^11.0 --- .github/workflows/phpunits.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/phpunits.yaml b/.github/workflows/phpunits.yaml index 5db2a8a..595f351 100644 --- a/.github/workflows/phpunits.yaml +++ b/.github/workflows/phpunits.yaml @@ -13,6 +13,7 @@ jobs: strategy: matrix: php-versions: [8.2, 8.3] + laravel-versions: [^10.0, ^11.0] services: clickhouse: @@ -50,7 +51,7 @@ jobs: - name: Install dependencies id: composer-dependencies - run: composer install --prefer-dist --no-progress + run: composer req --dev laravel/framework:${{ matrix.laravel-versions }} -W || composer install - name: Check codeclimate id: codeclimate-check From aa007e065e5aaa0829ce1c5ba4462eaf4d5c9cf1 Mon Sep 17 00:00:00 2001 From: Github bot Date: Thu, 14 Mar 2024 21:30:29 +0000 Subject: [PATCH 51/69] Update changelog.md --- changelog.md | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/changelog.md b/changelog.md index bb0aa30..ae7bc9f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,25 +1,40 @@ # Changelog +## 3.0.0 - 2024-03-14 + +### What's Changed + +* Configure Mend Bolt for GitHub by [@mend-bolt-for-github](https://github.com/mend-bolt-for-github) in https://github.com/bavix/laravel-clickhouse/pull/8 +* [3.0] Add support laravel ^11.0 & ^10.0 by [@rez1dent3](https://github.com/rez1dent3) in https://github.com/bavix/laravel-clickhouse/pull/9 + +### New Contributors + +* [@mend-bolt-for-github](https://github.com/mend-bolt-for-github) made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/8 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.4...3.0.0 + ## 2.3.4 - 2024-01-17 **Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.3...2.3.4 ## 2.3.3 - 2023-02-21 -## What's Changed -* Suppress deprecation warning by @evgeek in https://github.com/bavix/laravel-clickhouse/pull/5 -* Fix Eloquent\Builder::where to pass along AND/OR by @glmdev in https://github.com/bavix/laravel-clickhouse/pull/4 - -## New Contributors -* @evgeek made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/5 -* @glmdev made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/4 - +## What's Changed + +* Suppress deprecation warning by [@evgeek](https://github.com/evgeek) in https://github.com/bavix/laravel-clickhouse/pull/5 +* Fix Eloquent\Builder::where to pass along AND/OR by [@glmdev](https://github.com/glmdev) in https://github.com/bavix/laravel-clickhouse/pull/4 + +## New Contributors + +* [@evgeek](https://github.com/evgeek) made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/5 +* [@glmdev](https://github.com/glmdev) made their first contribution in https://github.com/bavix/laravel-clickhouse/pull/4 + **Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.2...2.3.3 ## 2.3.2 - 2023-01-23 -Add support laravel 10 - +Add support laravel 10 + **Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.3.1...2.3.2 ## 2.3.1 - 2022-10-27 @@ -28,30 +43,20 @@ Add support laravel 10 ## 2.3.0 - 2022-10-16 -add support laravel 9 - +add support laravel 9 + **Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/2.2.0...2.3.0 ## 2.2.0 - 2021-03-15 - - ## 2.1.1 - 2021-03-15 - - ## 2.1.0 - 2020-09-24 - - ## 2.0.0 - 2020-09-24 - - ## 1.1.0 - 2020-08-31 - - ## 1.0.1 - 2020-07-09 Add support `laravel/telescope` @@ -59,4 +64,3 @@ Add support `laravel/telescope` ## 1.0.0 - 2020-07-09 First version - From 4c07da7df54180e01faf8e35d5c3e93a8e223650 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Fri, 15 Mar 2024 00:33:37 +0300 Subject: [PATCH 52/69] Update README.md Signed-off-by: Maxim Babichev --- README.md | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 838d9a1..718057b 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,18 @@ -We switched to the standard mysql/postgres interface from clickhouse. More details here: https://clickhouse.com/docs/en/interfaces/mysql - ---- - # Laravel Clickhouse -[![Build Status](https://travis-ci.org/bavix/laravel-clickhouse.svg?branch=master)](https://travis-ci.org/bavix/laravel-clickhouse) -[![StyleCI](https://styleci.io/repos/269384604/shield?branch=master)](https://styleci.io/repos/269384604) -[![Coverage Status](https://coveralls.io/repos/github/bavix/laravel-clickhouse/badge.svg)](https://coveralls.io/github/bavix/laravel-clickhouse) - -[![Package Rank](https://phppackages.org/p/bavix/laravel-clickhouse/badge/rank.svg)](https://packagist.org/packages/bavix/laravel-clickhouse) [![Latest Stable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/stable)](https://packagist.org/packages/bavix/laravel-clickhouse) -[![Latest Unstable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/unstable)](https://packagist.org/packages/bavix/laravel-clickhouse) [![License](https://poser.pugx.org/bavix/laravel-clickhouse/license)](https://packagist.org/packages/bavix/laravel-clickhouse) [![composer.lock](https://poser.pugx.org/bavix/laravel-clickhouse/composerlock)](https://packagist.org/packages/bavix/laravel-clickhouse) Laravel Clickhouse - Eloquent model for ClickHouse. * **Vendor**: bavix -* **Package**: Laravel Clickhouse -* **Version**: [![Latest Stable Version](https://poser.pugx.org/bavix/laravel-clickhouse/v/stable)](https://packagist.org/packages/bavix/laravel-clickhouse) -* **Laravel Version**: `6.x`, `7.x`, `8.x`, `9.x` -* **PHP Version**: 7.2+ -* **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-clickhouse` +* **Package**: laravel-clickhouse +* **[Composer](https://getcomposer.org/):** `composer require bavix/laravel-wallet-uuid` + +> [!IMPORTANT] +> I recommend using the standard postgres/mysql interface for clickhouse. More details here: https://clickhouse.com/docs/en/interfaces/mysql + ## Get started ```sh From 36bbec5f97ae48b8bef578f0282404f4e6c62e6e Mon Sep 17 00:00:00 2001 From: Github bot Date: Thu, 14 Mar 2024 21:35:04 +0000 Subject: [PATCH 53/69] Update changelog.md --- changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/changelog.md b/changelog.md index ae7bc9f..2d81f4f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 3.0.1 - 2024-03-14 + +### What's Changed + +* Update README.md + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/3.0.0...3.0.1 + ## 3.0.0 - 2024-03-14 ### What's Changed From d7785de0bc03cf3227e44cf857cb7a085712eea9 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 18 Mar 2024 18:15:27 +0300 Subject: [PATCH 54/69] Update stale.yml Signed-off-by: Maxim Babichev --- .github/workflows/stale.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5a1a09f..b55be58 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: Mark stale issues on: schedule: - - cron: "0 0 * * *" + - cron: "0 */8 * * *" jobs: stale: runs-on: ubuntu-latest @@ -9,6 +9,8 @@ jobs: - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: 'This issue is stale because it has been open 21 days with no activity.' - days-before-stale: 21 + stale-issue-message: 'This issue is stale because it has been open 7 days with no activity.' + days-before-stale: 7 days-before-close: 3 + exempt-issue-labels: 'bug,in-developing' + exempt-pr-labels: 'bug,frozen,in-developing' From 5380a7eef0d0181599ae1978fe28e5b446fcb6eb Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 1 Apr 2024 20:19:57 +0300 Subject: [PATCH 55/69] fix Method Bavix\LaravelClickHouse\Database\Query\Builder::getCountForPagination does not exist #7 --- phpunit.xml | 12 ++--- src/Database/Query/Builder.php | 24 +++++++++ tests/FirstTableEntry.php | 22 ++++++++ tests/TestCase.php | 27 ++++++++++ tests/Unit/Database/ConnectionTest.php | 8 +-- .../Unit/Database/Eloquent/FirstTableTest.php | 50 +++++++++++++++++++ 6 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 tests/FirstTableEntry.php create mode 100644 tests/TestCase.php create mode 100644 tests/Unit/Database/Eloquent/FirstTableTest.php diff --git a/phpunit.xml b/phpunit.xml index 4b8b29f..716d0a0 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,17 +7,17 @@ - + tests - - - - - + + + + + diff --git a/src/Database/Query/Builder.php b/src/Database/Query/Builder.php index 9a9d090..4f1b700 100644 --- a/src/Database/Query/Builder.php +++ b/src/Database/Query/Builder.php @@ -10,6 +10,7 @@ use Illuminate\Support\Traits\Macroable; use Tinderbox\Clickhouse\Common\Format; use Tinderbox\ClickhouseBuilder\Query\BaseBuilder; +use Tinderbox\ClickhouseBuilder\Query\Expression; use Tinderbox\ClickhouseBuilder\Query\Grammar; class Builder extends BaseBuilder @@ -125,6 +126,29 @@ public function insert(array $values): bool return $this->connection->insert($this->grammar->compileInsert($this, $values), Arr::flatten($values)); } + public function getCountForPagination() + { + return (int) $this->getConnection() + ->table( + $this + ->cloneWithout(['columns' => [], 'orders' => [], 'limit' => null]) + ->select(new Expression('1')) + ) + ->count(); + } + + /** + * Set the limit and offset for a given page. + * + * @param int $page + * @param int $perPage + * @return $this + */ + public function forPage($page, $perPage = 15) + { + return $this->limit($perPage, ($page - 1) * $perPage); + } + public function getConnection(): Connection { return $this->connection; diff --git a/tests/FirstTableEntry.php b/tests/FirstTableEntry.php new file mode 100644 index 0000000..ba83fce --- /dev/null +++ b/tests/FirstTableEntry.php @@ -0,0 +1,22 @@ +set('database.connections.bavix::clickhouse', [ + 'host' => env('CLICKHOUSE_HOST', 'localhost'), + 'port' => env('CLICKHOUSE_PORT', '8123'), + 'driver' => env('CLICKHOUSE_DRIVER', 'bavix::clickhouse'), + 'database' => env('CLICKHOUSE_DATABASE', 'default'), + 'username' => env('CLICKHOUSE_USERNAME', 'default'), + 'password' => env('CLICKHOUSE_PASSWORD', ''), + ]); + } +} diff --git a/tests/Unit/Database/ConnectionTest.php b/tests/Unit/Database/ConnectionTest.php index 2d6d956..c5904ae 100644 --- a/tests/Unit/Database/ConnectionTest.php +++ b/tests/Unit/Database/ConnectionTest.php @@ -6,7 +6,7 @@ use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Query\Builder; -use PHPUnit\Framework\TestCase; +use Bavix\LaravelClickHouse\Tests\TestCase; use Tinderbox\Clickhouse\Exceptions\ClientException; class ConnectionTest extends TestCase @@ -19,11 +19,7 @@ class ConnectionTest extends TestCase protected function setUp(): void { parent::setUp(); - $this->connection = new Connection([ - 'host' => 'localhost', - 'port' => '8123', - 'database' => 'default', - ]); + $this->connection = $this->getConnection('bavix::clickhouse'); } public function testQuery(): void diff --git a/tests/Unit/Database/Eloquent/FirstTableTest.php b/tests/Unit/Database/Eloquent/FirstTableTest.php new file mode 100644 index 0000000..2da6425 --- /dev/null +++ b/tests/Unit/Database/Eloquent/FirstTableTest.php @@ -0,0 +1,50 @@ +connection = $this->getConnection('bavix::clickhouse'); + } + + public function testPaginate(): void + { + $this->connection->statement('DROP TABLE IF EXISTS my_first_table'); + + $result = $this->connection->statement('CREATE TABLE my_first_table +( + user_id UInt32, + message String, + timestamp DateTime, + metric Float32 +) +ENGINE = MergeTree() +PRIMARY KEY (user_id, timestamp)'); + self::assertTrue($result); + + + + self::assertTrue(FirstTableEntry::query()->insert([ + 'user_id' => 1, + 'message' => 'hello world', + 'timestamp' => new \DateTime(), + 'metric' => 42, + ])); + + self::assertCount(1, FirstTableEntry::query()->paginate()->items()); + } +} From 2f59ed36e490f3717da9d6b2cc5c1ea98c9f16b6 Mon Sep 17 00:00:00 2001 From: Github bot Date: Mon, 1 Apr 2024 17:22:54 +0000 Subject: [PATCH 56/69] autofix --- src/Database/Query/Builder.php | 8 ++++++-- tests/FirstTableEntry.php | 7 +------ tests/Unit/Database/Eloquent/FirstTableTest.php | 8 +++----- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/Database/Query/Builder.php b/src/Database/Query/Builder.php index 4f1b700..4550f0a 100644 --- a/src/Database/Query/Builder.php +++ b/src/Database/Query/Builder.php @@ -131,8 +131,12 @@ public function getCountForPagination() return (int) $this->getConnection() ->table( $this - ->cloneWithout(['columns' => [], 'orders' => [], 'limit' => null]) - ->select(new Expression('1')) + ->cloneWithout([ + 'columns' => [], + 'orders' => [], + 'limit' => null, + ]) + ->select(new Expression('1')), null ) ->count(); } diff --git a/tests/FirstTableEntry.php b/tests/FirstTableEntry.php index ba83fce..5dcb97b 100644 --- a/tests/FirstTableEntry.php +++ b/tests/FirstTableEntry.php @@ -13,10 +13,5 @@ class FirstTableEntry extends Model */ protected $table = 'my_first_table'; - protected $fillable = [ - 'user_id', - 'message', - 'timestamp', - 'metric', - ]; + protected $fillable = ['user_id', 'message', 'timestamp', 'metric']; } diff --git a/tests/Unit/Database/Eloquent/FirstTableTest.php b/tests/Unit/Database/Eloquent/FirstTableTest.php index 2da6425..ba220f7 100644 --- a/tests/Unit/Database/Eloquent/FirstTableTest.php +++ b/tests/Unit/Database/Eloquent/FirstTableTest.php @@ -36,13 +36,11 @@ public function testPaginate(): void PRIMARY KEY (user_id, timestamp)'); self::assertTrue($result); - - self::assertTrue(FirstTableEntry::query()->insert([ - 'user_id' => 1, - 'message' => 'hello world', + 'user_id' => 1, + 'message' => 'hello world', 'timestamp' => new \DateTime(), - 'metric' => 42, + 'metric' => 42, ])); self::assertCount(1, FirstTableEntry::query()->paginate()->items()); From b8c0cf9fcccb3bc12cf8940941b20f1fa486f827 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 1 Apr 2024 20:23:46 +0300 Subject: [PATCH 57/69] update phpstan.baseline.neon --- phpstan.baseline.neon | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/phpstan.baseline.neon b/phpstan.baseline.neon index 825e05f..a7ed06f 100644 --- a/phpstan.baseline.neon +++ b/phpstan.baseline.neon @@ -35,11 +35,6 @@ parameters: count: 5 path: src/Database/Eloquent/Builder.php - - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:forPage\\(\\)\\.$#" - count: 1 - path: src/Database/Eloquent/Builder.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:forPageAfterId\\(\\)\\.$#" count: 1 @@ -290,6 +285,11 @@ parameters: count: 1 path: src/Database/Eloquent/Builder.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:get\\(\\) invoked with 1 parameter, 0 required\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + - message: "#^PHPDoc tag @param for parameter \\$query with type Illuminate\\\\Database\\\\Query\\\\Builder is incompatible with native type Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\.$#" count: 2 @@ -912,7 +912,7 @@ parameters: - message: "#^Cannot cast mixed to int\\.$#" - count: 1 + count: 2 path: src/Database/Query/Builder.php - @@ -925,11 +925,21 @@ parameters: count: 1 path: src/Database/Query/Builder.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:forPage\\(\\) should return \\$this\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\) but returns static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\)\\.$#" + count: 1 + path: src/Database/Query/Builder.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:get\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" count: 1 path: src/Database/Query/Builder.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:getCountForPagination\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Query/Builder.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insert\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" count: 1 @@ -950,6 +960,11 @@ parameters: count: 1 path: src/Database/Query/Builder.php + - + message: "#^Parameter \\#1 \\$table of method Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\\:\\:table\\(\\) expects Closure\\|string\\|Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Builder, static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\) given\\.$#" + count: 1 + path: src/Database/Query/Builder.php + - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:\\$connection has no type specified\\.$#" count: 1 From 20c4ea89422d4a6ae58a9300845b75ac5090a4ff Mon Sep 17 00:00:00 2001 From: Github bot Date: Mon, 1 Apr 2024 17:27:17 +0000 Subject: [PATCH 58/69] Update changelog.md --- changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/changelog.md b/changelog.md index 2d81f4f..bc808b8 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 3.0.2 - 2024-04-01 + +### What's Changed + +* Method Bavix\LaravelClickHouse\Database\Query\Builder::getCountForPagination does not exist by [@rez1dent3](https://github.com/rez1dent3) in https://github.com/bavix/laravel-clickhouse/pull/10 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/3.0.1...3.0.2 + ## 3.0.1 - 2024-03-14 ### What's Changed From e802f6cbcfbb93f64a3315f740374a2eb54b26bd Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 1 Apr 2024 20:46:07 +0300 Subject: [PATCH 59/69] init fixes --- src/Database/Connection.php | 5 +- src/Database/Eloquent/Builder.php | 7 ++ .../Eloquent/Concerns/HasAttributes.php | 6 +- src/Database/Eloquent/Model.php | 92 +++++++++++++++---- src/Database/Query/Builder.php | 2 +- 5 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/Database/Connection.php b/src/Database/Connection.php index c5dab87..b9c1f76 100644 --- a/src/Database/Connection.php +++ b/src/Database/Connection.php @@ -10,10 +10,7 @@ class Connection extends \Tinderbox\ClickhouseBuilder\Integrations\Laravel\Connection { - /** - * @return Builder|\Tinderbox\ClickhouseBuilder\Integrations\Laravel\Builder - */ - public function query() + public function query(): Builder { return new Builder($this, new Grammar()); } diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index 1980e36..d714795 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -652,6 +652,13 @@ public function newModelInstance($attributes = []) ->setConnection($this->query->getConnection()->getName()); } + public function create ($attributes = []) + { + return tap($this->newModelInstance($attributes), static function ($instance) { + $instance->save(); + }); + } + public function getQuery(): QueryBuilder { return $this->query; diff --git a/src/Database/Eloquent/Concerns/HasAttributes.php b/src/Database/Eloquent/Concerns/HasAttributes.php index 7813588..6b28a8e 100644 --- a/src/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Database/Eloquent/Concerns/HasAttributes.php @@ -12,14 +12,12 @@ trait HasAttributes public function getDates(): array { - return property_exists($this, 'dates') && is_array($this->dates) - ? $this->dates - : []; + return $this->dates ?? []; } public function getCasts(): array { - return $this->casts; + return $this->casts ?? []; } protected function getDateFormat(): string diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index 4e3e2cd..cf1246a 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -7,8 +7,11 @@ use ArrayAccess; use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Contracts\Routing\UrlRoutable; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Contracts\Support\Jsonable; +use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionResolverInterface; use Illuminate\Database\ConnectionResolverInterface as Resolver; use Illuminate\Database\Eloquent\Concerns\GuardsAttributes; @@ -17,11 +20,14 @@ use Illuminate\Database\Eloquent\Concerns\HidesAttributes; use Illuminate\Database\Eloquent\JsonEncodingException; use Illuminate\Database\Eloquent\MassAssignmentException; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasManyThrough; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Str; use JsonSerializable; use Tinderbox\ClickhouseBuilder\Query\Grammar; -abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable +abstract class Model implements ArrayAccess, UrlRoutable, Arrayable, Jsonable, JsonSerializable { use Concerns\HasAttributes; use Concerns\Common; @@ -35,7 +41,7 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab * * @var bool */ - public $exists = false; + public bool $exists = false; /** * Indicates if an exception should be thrown when trying to access a missing attribute on a retrieved model. @@ -93,19 +99,9 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab */ protected $perPage = 15; - /** - * The connection resolver instance. - * - * @var Resolver - */ - protected static $resolver; + protected static ConnectionResolverInterface $resolver; - /** - * The event dispatcher instance. - * - * @var \Illuminate\Contracts\Events\Dispatcher - */ - protected static $dispatcher; + protected static Dispatcher $dispatcher; /** * The array of booted models. @@ -114,6 +110,8 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab */ protected static $booted = []; + public bool $wasRecentlyCreated = false; + /** * Create a new Eloquent model instance. */ @@ -381,7 +379,7 @@ public function jsonSerialize(): array /** * Get the database connection for the model. */ - public function getConnection(): \Illuminate\Database\Connection + public function getConnection(): ConnectionInterface { return static::resolveConnection($this->getConnectionName()); } @@ -408,10 +406,8 @@ public function setConnection(string $name) /** * Resolve a connection instance. - * - * @return Connection|\Illuminate\Database\ConnectionInterface */ - public static function resolveConnection(string $connection = null) + public static function resolveConnection(string $connection = null): ConnectionInterface { return static::getConnectionResolver()->connection($connection); } @@ -456,6 +452,52 @@ public function setTable(string $table): self return $this; } + public function resolveRouteBinding($value, $field = null): ?Model + { + return $this->resolveRouteBindingQuery($this, $value, $field)->first(); + } + + public function resolveSoftDeletableRouteBinding(mixed $value, ?string $field = null): ?Model + { + return $this->resolveRouteBindingQuery($this, $value, $field)->withTrashed()->first(); + } + + public function resolveChildRouteBinding($childType, $value, $field): ?Model + { + return $this->resolveChildRouteBindingQuery($childType, $value, $field)->first(); + } + + public function resolveSoftDeletableChildRouteBinding(string $childType, mixed $value, ?string $field = null): ?Model + { + return $this->resolveChildRouteBindingQuery($childType, $value, $field)->withTrashed()->first(); + } + + protected function resolveChildRouteBindingQuery(string $childType, mixed $value, ?string $field = null): Relation|Model + { + $relationship = $this->{$this->childRouteBindingRelationshipName($childType)}(); + + $field = $field ?: $relationship->getRelated()->getRouteKeyName(); + + if ($relationship instanceof HasManyThrough || + $relationship instanceof BelongsToMany) { + $field = $relationship->getRelated()->getTable().'.'.$field; + } + + return $relationship instanceof Model + ? $relationship->resolveRouteBindingQuery($relationship, $value, $field) + : $relationship->getRelated()->resolveRouteBindingQuery($relationship, $value, $field); + } + + protected function childRouteBindingRelationshipName(string $childType): string + { + return Str::plural(Str::camel($childType)); + } + + public function resolveRouteBindingQuery(Relation|Model $query, mixed $value, ?string $field = null): Builder + { + return $query->where($field ?? $this->getRouteKeyName(), $value); + } + /** * Get the primary key for the model. */ @@ -504,6 +546,16 @@ public function setKeyType(string $type) return $this; } + public function getRouteKey(): mixed + { + return $this->getAttribute($this->getRouteKeyName()); + } + + public function getRouteKeyName(): string + { + return $this->getKeyName(); + } + /** * Get the value of the model's primary key. * @@ -533,9 +585,9 @@ public function getPerPage(): int /** * Set the number of models to return per page. * - * @return $this + * @return static */ - public function setPerPage(int $perPage): self + public function setPerPage(int $perPage): static { $this->perPage = $perPage; diff --git a/src/Database/Query/Builder.php b/src/Database/Query/Builder.php index 4550f0a..55a1548 100644 --- a/src/Database/Query/Builder.php +++ b/src/Database/Query/Builder.php @@ -19,7 +19,7 @@ class Builder extends BaseBuilder __call as macroCall; } - protected $connection; + protected Connection $connection; public function __construct( Connection $connection, From d978fbc1fb84b3ae29dd2082236a637db21735a7 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 1 Apr 2024 21:37:46 +0300 Subject: [PATCH 60/69] baseline --- phpstan.baseline.neon | 120 +++++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 20 deletions(-) diff --git a/phpstan.baseline.neon b/phpstan.baseline.neon index a7ed06f..a98b569 100644 --- a/phpstan.baseline.neon +++ b/phpstan.baseline.neon @@ -30,6 +30,11 @@ parameters: count: 1 path: src/Database/Connection.php + - + message: "#^Return type \\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\) of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Connection\\:\\:query\\(\\) should be compatible with return type \\(Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Builder\\) of method Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\\:\\:query\\(\\)$#" + count: 1 + path: src/Database/Connection.php + - message: "#^Access to protected property Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:\\$wheres\\.$#" count: 5 @@ -100,6 +105,16 @@ parameters: count: 1 path: src/Database/Eloquent/Builder.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:create\\(\\) has no return type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:create\\(\\) has parameter \\$attributes with no type specified\\.$#" + count: 1 + path: src/Database/Eloquent/Builder.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) has parameter \\$whereSlice with no value type specified in iterable type array\\.$#" count: 1 @@ -455,6 +470,26 @@ parameters: count: 1 path: src/Database/Eloquent/Collection.php + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:withTrashed\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:first\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:where\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:withTrashed\\(\\)\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + - message: "#^Call to an undefined static method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:insert\\(\\)\\.$#" count: 1 @@ -560,6 +595,11 @@ parameters: count: 1 path: src/Database/Eloquent/Model.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:childRouteBindingRelationshipName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:clearBootedModels\\(\\) has no return type specified\\.$#" count: 1 @@ -610,11 +650,6 @@ parameters: count: 1 path: src/Database/Eloquent/Model.php - - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnection\\(\\) should return Illuminate\\\\Database\\\\Connection but returns Illuminate\\\\Database\\\\ConnectionInterface\\.$#" - count: 1 - path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnectionName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" count: 1 @@ -670,6 +705,16 @@ parameters: count: 1 path: src/Database/Eloquent/Model.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getRouteKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getRouteKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getTable\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" count: 1 @@ -785,11 +830,56 @@ parameters: count: 1 path: src/Database/Eloquent/Model.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveChildRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveChildRouteBindingQuery\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveChildRouteBindingQuery\\(\\) return type with generic class Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation does not specify its types\\: TRelatedModel$#" + count: 1 + path: src/Database/Eloquent/Model.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" count: 1 path: src/Database/Eloquent/Model.php + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBinding\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|null but returns object\\|null\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBindingQuery\\(\\) has parameter \\$query with generic class Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation but does not specify its types\\: TRelatedModel$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBindingQuery\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveSoftDeletableChildRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + + - + message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveSoftDeletableRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:save\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" count: 1 @@ -875,6 +965,11 @@ parameters: count: 1 path: src/Database/Eloquent/Model.php + - + message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$casts \\(array\\) on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: src/Database/Eloquent/Model.php + - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$dateFormat \\(string\\) on left side of \\?\\? is not nullable\\.$#" count: 1 @@ -965,21 +1060,6 @@ parameters: count: 1 path: src/Database/Query/Builder.php - - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:\\$connection has no type specified\\.$#" - count: 1 - path: src/Database/Query/Builder.php - - - - message: "#^Unable to resolve the template type TKey in call to function collect$#" - count: 1 - path: src/Database/Query/Builder.php - - - - message: "#^Unable to resolve the template type TValue in call to function collect$#" - count: 1 - path: src/Database/Query/Builder.php - - message: "#^Unsafe usage of new static\\(\\)\\.$#" count: 1 From b0f99e83e520fe39930c98c763b069d47117cfc8 Mon Sep 17 00:00:00 2001 From: Github bot Date: Mon, 1 Apr 2024 18:39:06 +0000 Subject: [PATCH 61/69] autofix --- src/Database/Eloquent/Builder.php | 2 +- src/Database/Eloquent/Model.php | 77 ++++++++++++++++++------------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index d714795..adc05ba 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -652,7 +652,7 @@ public function newModelInstance($attributes = []) ->setConnection($this->query->getConnection()->getName()); } - public function create ($attributes = []) + public function create($attributes = []) { return tap($this->newModelInstance($attributes), static function ($instance) { $instance->save(); diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index cf1246a..4efb015 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -38,11 +38,11 @@ abstract class Model implements ArrayAccess, UrlRoutable, Arrayable, Jsonable, J /** * Indicates if the model exists. - * - * @var bool */ public bool $exists = false; + public bool $wasRecentlyCreated = false; + /** * Indicates if an exception should be thrown when trying to access a missing attribute on a retrieved model. * @@ -110,8 +110,6 @@ abstract class Model implements ArrayAccess, UrlRoutable, Arrayable, Jsonable, J */ protected static $booted = []; - public bool $wasRecentlyCreated = false; - /** * Create a new Eloquent model instance. */ @@ -454,43 +452,31 @@ public function setTable(string $table): self public function resolveRouteBinding($value, $field = null): ?Model { - return $this->resolveRouteBindingQuery($this, $value, $field)->first(); + return $this->resolveRouteBindingQuery($this, $value, $field) + ->first(); } public function resolveSoftDeletableRouteBinding(mixed $value, ?string $field = null): ?Model { - return $this->resolveRouteBindingQuery($this, $value, $field)->withTrashed()->first(); + return $this->resolveRouteBindingQuery($this, $value, $field) + ->withTrashed() + ->first(); } public function resolveChildRouteBinding($childType, $value, $field): ?Model { - return $this->resolveChildRouteBindingQuery($childType, $value, $field)->first(); - } - - public function resolveSoftDeletableChildRouteBinding(string $childType, mixed $value, ?string $field = null): ?Model - { - return $this->resolveChildRouteBindingQuery($childType, $value, $field)->withTrashed()->first(); - } - - protected function resolveChildRouteBindingQuery(string $childType, mixed $value, ?string $field = null): Relation|Model - { - $relationship = $this->{$this->childRouteBindingRelationshipName($childType)}(); - - $field = $field ?: $relationship->getRelated()->getRouteKeyName(); - - if ($relationship instanceof HasManyThrough || - $relationship instanceof BelongsToMany) { - $field = $relationship->getRelated()->getTable().'.'.$field; - } - - return $relationship instanceof Model - ? $relationship->resolveRouteBindingQuery($relationship, $value, $field) - : $relationship->getRelated()->resolveRouteBindingQuery($relationship, $value, $field); + return $this->resolveChildRouteBindingQuery($childType, $value, $field) + ->first(); } - protected function childRouteBindingRelationshipName(string $childType): string - { - return Str::plural(Str::camel($childType)); + public function resolveSoftDeletableChildRouteBinding( + string $childType, + mixed $value, + ?string $field = null + ): ?Model { + return $this->resolveChildRouteBindingQuery($childType, $value, $field) + ->withTrashed() + ->first(); } public function resolveRouteBindingQuery(Relation|Model $query, mixed $value, ?string $field = null): Builder @@ -584,8 +570,6 @@ public function getPerPage(): int /** * Set the number of models to return per page. - * - * @return static */ public function setPerPage(int $perPage): static { @@ -642,6 +626,33 @@ public static function preventsAccessingMissingAttributes(): bool return static::$modelsShouldPreventAccessingMissingAttributes; } + protected function resolveChildRouteBindingQuery( + string $childType, + mixed $value, + ?string $field = null + ): Relation|Model { + $relationship = $this->{$this->childRouteBindingRelationshipName($childType)}(); + + $field = $field !== null && $field !== '' && $field !== '0' ? $field : $relationship->getRelated() + ->getRouteKeyName(); + + if ($relationship instanceof HasManyThrough || + $relationship instanceof BelongsToMany) { + $field = $relationship->getRelated() + ->getTable().'.'.$field; + } + + return $relationship instanceof Model + ? $relationship->resolveRouteBindingQuery($relationship, $value, $field) + : $relationship->getRelated() + ->resolveRouteBindingQuery($relationship, $value, $field); + } + + protected function childRouteBindingRelationshipName(string $childType): string + { + return Str::plural(Str::camel($childType)); + } + /** * Check if the model needs to be booted and if so, do it. */ From d10a56cb4a8db8886d0beef7ccd5063e80d0a0b2 Mon Sep 17 00:00:00 2001 From: Github bot Date: Mon, 1 Apr 2024 18:40:14 +0000 Subject: [PATCH 62/69] Update changelog.md --- changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/changelog.md b/changelog.md index bc808b8..90817a2 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 3.0.3 - 2024-04-01 + +### What's Changed + +* init fixes by [@rez1dent3](https://github.com/rez1dent3) in https://github.com/bavix/laravel-clickhouse/pull/11 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/3.0.2...3.0.3 + ## 3.0.2 - 2024-04-01 ### What's Changed From a1ff036ee3203ecbb8e93ae4601d1a3b8963c6b3 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 1 Apr 2024 22:03:23 +0300 Subject: [PATCH 63/69] Update README.md Signed-off-by: Maxim Babichev --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 718057b..d6edeb2 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Laravel Clickhouse - Eloquent model for ClickHouse. > [!IMPORTANT] > I recommend using the standard postgres/mysql interface for clickhouse. More details here: https://clickhouse.com/docs/en/interfaces/mysql +The implementation is provided as is. Further work with the library only through contributors. Added linters, tests and much more. To make it easier for you to send PR. ## Get started ```sh From bba6ced83319c083e2c2e3c202a360925340f0ba Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Wed, 18 Dec 2024 20:30:10 +0300 Subject: [PATCH 64/69] Update README.md Signed-off-by: Maxim Babichev --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index d6edeb2..ff8c73a 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,3 @@ Payment::select(raw('count() AS cnt'), 'payment_system') ->get(); ``` - ---- -Supported by - -[![Supported by JetBrains](https://cdn.rawgit.com/bavix/development-through/46475b4b/jetbrains.svg)](https://www.jetbrains.com/) From d82282a2665cdcca7ce034c86e24666eccdf6ab5 Mon Sep 17 00:00:00 2001 From: "kirill.bor" Date: Mon, 3 Mar 2025 21:58:24 +0300 Subject: [PATCH 65/69] bump laravel to latest version --- composer.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index c8ecf3d..80fe499 100644 --- a/composer.json +++ b/composer.json @@ -9,21 +9,21 @@ "eloquent" ], "require": { - "php": "^8.2", - "laravel/framework": "^10.0|^11.0", + "php": "^8.2|^8.3|^8.4", + "laravel/framework": "^10.0|^11.0|^12.0", "the-tinderbox/clickhouse-builder": "^6.1", "ext-json": "*" }, "require-dev": { - "driftingly/rector-laravel": "^1.0", + "driftingly/rector-laravel": "^2.0", "ergebnis/phpstan-rules": "^2.1", "infection/infection": "~0.27", - "larastan/larastan": "^2.8", + "larastan/larastan": "^3.0", "nunomaduro/collision": "^8.0", - "orchestra/testbench": "^9.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "rector/rector": "^1.0", + "orchestra/testbench": "^9.0|^10.0|^11.0", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5|^11.0", + "rector/rector": "^2.0", "symplify/easy-coding-standard": "^12.1", "mockery/mockery": "^1.6", "fakerphp/faker": "^1.23" From f008da75527c49504e0badcce199f9822e5d4700 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Thu, 13 Mar 2025 17:45:55 +0300 Subject: [PATCH 66/69] test --- .github/workflows/phpunits.yaml | 4 ++-- composer.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/phpunits.yaml b/.github/workflows/phpunits.yaml index 595f351..aa35bc3 100644 --- a/.github/workflows/phpunits.yaml +++ b/.github/workflows/phpunits.yaml @@ -12,8 +12,8 @@ jobs: strategy: matrix: - php-versions: [8.2, 8.3] - laravel-versions: [^10.0, ^11.0] + php-versions: [8.2, 8.3, 8.4] + laravel-versions: [^10.0, ^11.0, ^12.0] services: clickhouse: diff --git a/composer.json b/composer.json index 80fe499..385c079 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "eloquent" ], "require": { - "php": "^8.2|^8.3|^8.4", + "php": "^8.2", "laravel/framework": "^10.0|^11.0|^12.0", "the-tinderbox/clickhouse-builder": "^6.1", "ext-json": "*" From 5e02d82ffb64c78d12304e1b5fc8f8c68cf42eb1 Mon Sep 17 00:00:00 2001 From: Github bot Date: Thu, 13 Mar 2025 14:50:31 +0000 Subject: [PATCH 67/69] autofix --- src/Database/Eloquent/Builder.php | 11 +++++------ tests/Unit/Database/Eloquent/CollectionTest.php | 4 ---- tests/Unit/Database/Query/BuilderTest.php | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Database/Eloquent/Builder.php b/src/Database/Eloquent/Builder.php index adc05ba..90e9638 100755 --- a/src/Database/Eloquent/Builder.php +++ b/src/Database/Eloquent/Builder.php @@ -207,7 +207,7 @@ public function whereKeyNot($id): self /** * Add a basic where clause to the query. * - * @param string|array|\Closure $column + * @param string|array|Closure $column * @param string $operator * @param mixed $value * @return $this @@ -229,7 +229,7 @@ public function where($column, $operator = null, $value = null, string $boolean /** * Add an "or where" clause to the query. * - * @param \Closure|array|string $column + * @param Closure|array|string $column * @param string $operator * @param mixed $value * @return $this @@ -283,7 +283,7 @@ public function find($id) /** * Find multiple models by their primary keys. * - * @param \Illuminate\Contracts\Support\Arrayable|array $ids + * @param Arrayable|array $ids */ public function findMany($ids): Collection { @@ -422,7 +422,6 @@ public function getRelation(string $name): Relation /** * Chunk the results of a query by comparing numeric IDs. * - * @param null $column * @param string|null $alias */ public function chunkById(int $count, callable $callback, $column = null, $alias = null): bool @@ -455,7 +454,7 @@ public function chunkById(int $count, callable $callback, $column = null, $alias } $lastId = $results->last() -->{$alias}; + ->{$alias}; unset($results); } while ($countResults === $count); @@ -506,7 +505,7 @@ public function paginate( $perPage = $perPage !== null && $perPage !== 0 ? $perPage : $this->model->getPerPage(); $results = ($total = $this->toBase()->getCountForPagination()) ? $this->forPage($page, $perPage) - ->get($columns) + ->get() : $this->model->newCollection(); return $this->paginator($results, $total, $perPage, $page, [ diff --git a/tests/Unit/Database/Eloquent/CollectionTest.php b/tests/Unit/Database/Eloquent/CollectionTest.php index 0a7581d..da034f8 100644 --- a/tests/Unit/Database/Eloquent/CollectionTest.php +++ b/tests/Unit/Database/Eloquent/CollectionTest.php @@ -136,10 +136,6 @@ public function testFind($key): void } } - /** - * @param null $operator - * @param null $value - */ #[\PHPUnit\Framework\Attributes\DataProvider('containsDataProvider')] public function testContains(bool $expected, $key, $operator = null, $value = null): void { diff --git a/tests/Unit/Database/Query/BuilderTest.php b/tests/Unit/Database/Query/BuilderTest.php index a31a1c1..7f8fd3e 100644 --- a/tests/Unit/Database/Query/BuilderTest.php +++ b/tests/Unit/Database/Query/BuilderTest.php @@ -14,7 +14,7 @@ use Tinderbox\ClickhouseBuilder\Query\Grammar; /** - * @property \Mockery\MockInterface|Connection connection + * @property MockInterface|Connection connection * @property Builder builder */ class BuilderTest extends TestCase From f8e2beab279e146b2e125f570db54443df3ae76c Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Tue, 27 May 2025 21:10:45 +0300 Subject: [PATCH 68/69] patch --- composer.json | 13 +- phpstan.baseline.neon | 667 +++++++++++++++++++++----------- src/Database/Eloquent/Model.php | 5 + src/Database/Query/Builder.php | 6 +- 4 files changed, 448 insertions(+), 243 deletions(-) diff --git a/composer.json b/composer.json index 385c079..ff9ba6c 100644 --- a/composer.json +++ b/composer.json @@ -12,18 +12,19 @@ "php": "^8.2", "laravel/framework": "^10.0|^11.0|^12.0", "the-tinderbox/clickhouse-builder": "^6.1", + "bavix/clickhouse-php-client": "^3.1", "ext-json": "*" }, "require-dev": { - "driftingly/rector-laravel": "^2.0", + "driftingly/rector-laravel": "^1.0|^2.0", "ergebnis/phpstan-rules": "^2.1", "infection/infection": "~0.27", - "larastan/larastan": "^3.0", - "nunomaduro/collision": "^8.0", - "orchestra/testbench": "^9.0|^10.0|^11.0", - "phpstan/phpstan": "^2.0", + "larastan/larastan": "^2.0|^3.0", + "nunomaduro/collision": "^7.0|^8.0", + "orchestra/testbench": "^8.0|^9.0|^10.0", + "phpstan/phpstan": "^1.0|^2.0", "phpunit/phpunit": "^10.5|^11.0", - "rector/rector": "^2.0", + "rector/rector": "^1.0|^2.0", "symplify/easy-coding-standard": "^12.1", "mockery/mockery": "^1.6", "fakerphp/faker": "^1.23" diff --git a/phpstan.baseline.neon b/phpstan.baseline.neon index a98b569..6d57a49 100644 --- a/phpstan.baseline.neon +++ b/phpstan.baseline.neon @@ -1,1066 +1,1267 @@ parameters: ignoreErrors: - - message: "#^Cannot access offset 'db' on Illuminate\\\\Contracts\\\\Foundation\\\\Application\\.$#" + message: '#^Cannot access offset ''db'' on Illuminate\\Contracts\\Foundation\\Application\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 path: src/ClickHouseServiceProvider.php - - message: "#^Cannot access offset 'events' on Illuminate\\\\Contracts\\\\Foundation\\\\Application\\.$#" + message: '#^Cannot access offset ''events'' on Illuminate\\Contracts\\Foundation\\Application\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 path: src/ClickHouseServiceProvider.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\ClickHouseServiceProvider is neither abstract nor final\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\ClickHouseServiceProvider is neither abstract nor final\.$#' + identifier: ergebnis.final count: 1 path: src/ClickHouseServiceProvider.php - - message: "#^PHPDoc tag @throws has invalid value \\(\\)\\: Unexpected token \"\\\\n \", expected type at offset 18$#" + message: '#^PHPDoc tag @throws has invalid value \(\)\: Unexpected token "\\n ", expected type at offset 18 on line 2$#' + identifier: phpDoc.parseError count: 1 path: src/ClickHouseServiceProvider.php - - message: "#^Class \"Bavix\\\\LaravelClickHouse\\\\Database\\\\Connection\" is not allowed to extend \"Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\"\\.$#" + message: '#^Class "Bavix\\LaravelClickHouse\\Database\\Connection" is not allowed to extend "Tinderbox\\ClickhouseBuilder\\Integrations\\Laravel\\Connection"\.$#' + identifier: ergebnis.noExtends count: 1 path: src/Database/Connection.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Connection is neither abstract nor final\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Connection is neither abstract nor final\.$#' + identifier: ergebnis.final count: 1 path: src/Database/Connection.php - - message: "#^Return type \\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\) of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Connection\\:\\:query\\(\\) should be compatible with return type \\(Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Builder\\) of method Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\\:\\:query\\(\\)$#" + message: '#^Return type \(Bavix\\LaravelClickHouse\\Database\\Query\\Builder\) of method Bavix\\LaravelClickHouse\\Database\\Connection\:\:query\(\) should be compatible with return type \(Tinderbox\\ClickhouseBuilder\\Integrations\\Laravel\\Builder\) of method Tinderbox\\ClickhouseBuilder\\Integrations\\Laravel\\Connection\:\:query\(\)$#' + identifier: method.childReturnType count: 1 path: src/Database/Connection.php - - message: "#^Access to protected property Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:\\$wheres\\.$#" + message: '#^Access to protected property Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:\$wheres\.$#' + identifier: property.protected count: 5 path: src/Database/Eloquent/Builder.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:forPageAfterId\\(\\)\\.$#" + message: '#^Call to an undefined method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:forNestedWhere\(\)\.$#' + identifier: method.notFound count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:skip\\(\\)\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder is neither abstract nor final\.$#' + identifier: ergebnis.final count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:forNestedWhere\\(\\)\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder uses generic trait Illuminate\\Database\\Concerns\\BuildsQueries but does not specify its types\: TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Cannot call method getQuery\\(\\) on mixed\\.$#" - count: 1 + message: '#^Language construct isset\(\) should not be used\.$#' + identifier: ergebnis.noIsset + count: 5 path: src/Database/Eloquent/Builder.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder is neither abstract nor final\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:__call\(\) has parameter \$parameters with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:__callStatic\(\) has parameter \$parameters with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Language construct isset\\(\\) should not be used\\.$#" - count: 5 + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:addNestedWiths\(\) has parameter \$results with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:__call\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:addNestedWiths\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:__callStatic\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:addNewWheresWithinGroup\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:addNestedWiths\\(\\) has parameter \\$results with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:callScope\(\) has parameter \$parameters with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:addNestedWiths\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:chunkById\(\) has parameter \$column with no type specified\.$#' + identifier: missingType.parameter count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:addNewWheresWithinGroup\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:create\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:callScope\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:create\(\) has parameter \$attributes with no type specified\.$#' + identifier: missingType.parameter count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:create\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:createNestedWhere\(\) has parameter \$whereSlice with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:create\\(\\) has parameter \\$attributes with no type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:createNestedWhere\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) has parameter \\$whereSlice with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:createSelectWithConstraint\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:eagerLoadRelation\(\) has parameter \$models with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createSelectWithConstraint\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:eagerLoadRelation\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelation\\(\\) has parameter \\$models with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:eagerLoadRelations\(\) has parameter \$models with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelation\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:eagerLoadRelations\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelations\\(\\) has parameter \\$models with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:find\(\) should return array\\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|static\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\)\|null but returns mixed\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:eagerLoadRelations\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:findMany\(\) has parameter \$ids with generic interface Illuminate\\Contracts\\Support\\Arrayable but does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:find\\(\\) should return array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\|null but returns object\\|null\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:findMany\(\) has parameter \$ids with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findMany\\(\\) has parameter \\$ids with generic interface Illuminate\\\\Contracts\\\\Support\\\\Arrayable but does not specify its types\\: TKey, TValue$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:findOrFail\(\) should return Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model but returns array\\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|static\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\)\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findMany\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:findOrFail\(\) should return Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model but returns array\\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|static\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\)\|null\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findOrFail\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model but returns array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:fromQuery\(\) has parameter \$bindings with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:findOrFail\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model but returns array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\|null\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:getEagerLoads\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:fromQuery\\(\\) has parameter \\$bindings with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:getMacro\(\) should return Closure but returns mixed\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getEagerLoads\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:getModels\(\) should return array\ but returns array\\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getMacro\\(\\) should return Closure but returns mixed\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:getRelation\(\) return type with generic class Illuminate\\Database\\Eloquent\\Relations\\Relation does not specify its types\: TRelatedModel, TDeclaringModel, TResult$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getModels\\(\\) should return array\\ but returns array\\\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:groupWhereSliceForScope\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getRelation\\(\\) return type with generic class Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation does not specify its types\\: TRelatedModel$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:groupWhereSliceForScope\(\) has parameter \$whereSlice with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:getRelation\\(\\) should return Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation but returns mixed\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:hydrate\(\) has parameter \$items with no value type specified in iterable type iterable\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:groupWhereSliceForScope\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:newModelInstance\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:groupWhereSliceForScope\\(\\) has parameter \\$whereSlice with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:orWhere\(\) has parameter \$column with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:hydrate\\(\\) has parameter \\$items with no value type specified in iterable type iterable\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:paginate\(\) has parameter \$columns with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:newModelInstance\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:paginate\(\) return type with generic interface Illuminate\\Contracts\\Pagination\\LengthAwarePaginator does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:orWhere\\(\\) has parameter \\$column with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:parseWithRelations\(\) has parameter \$relations with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:paginate\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:parseWithRelations\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:paginate\\(\\) return type with generic interface Illuminate\\\\Contracts\\\\Pagination\\\\LengthAwarePaginator does not specify its types\\: TItem$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:pluck\(\) return type with generic class Illuminate\\Support\\Collection does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:parseWithRelations\\(\\) has parameter \\$relations with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:relationsNestedUnder\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:parseWithRelations\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:scopes\(\) has parameter \$scopes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:pluck\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:setEagerLoads\(\) has parameter \$eagerLoad with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:relationsNestedUnder\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:setModel\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:scopes\\(\\) has parameter \\$scopes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:setQuery\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:setEagerLoads\\(\\) has parameter \\$eagerLoad with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:simplePaginate\(\) has parameter \$columns with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:setModel\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:simplePaginate\(\) return type with generic interface Illuminate\\Contracts\\Pagination\\Paginator does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:setQuery\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:toBase\(\) should return Illuminate\\Database\\Query\\Builder but returns Bavix\\LaravelClickHouse\\Database\\Query\\Builder\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:simplePaginate\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:where\(\) has parameter \$column with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:simplePaginate\\(\\) return type with generic interface Illuminate\\\\Contracts\\\\Pagination\\\\Paginator does not specify its types\\: TItem$#" - count: 1 + message: '#^PHPDoc tag @param for parameter \$query with type Illuminate\\Database\\Query\\Builder is incompatible with native type Bavix\\LaravelClickHouse\\Database\\Query\\Builder\.$#' + identifier: parameter.phpDocType + count: 2 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:toBase\\(\\) should return Illuminate\\\\Database\\\\Query\\\\Builder but returns Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\.$#" + message: '#^Parameter \#1 \$array of function array_flip expects array\, mixed given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:where\\(\\) has parameter \\$column with no value type specified in iterable type array\\.$#" + message: '#^Parameter \#1 \$builder of method Illuminate\\Database\\Eloquent\\Scope\:\:apply\(\) expects Illuminate\\Database\\Eloquent\\Builder\, Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:get\\(\\) invoked with 1 parameter, 0 required\\.$#" + message: '#^Parameter \#1 \$column of method Tinderbox\\ClickhouseBuilder\\Query\\BaseBuilder\:\:where\(\) expects Closure\|string\|Tinderbox\\ClickhouseBuilder\\Query\\BaseBuilder\|Tinderbox\\ClickhouseBuilder\\Query\\TwoElementsLogicExpression, mixed given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^PHPDoc tag @param for parameter \\$query with type Illuminate\\\\Database\\\\Query\\\\Builder is incompatible with native type Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\.$#" + message: '#^Parameter \#1 \$model of method Illuminate\\Database\\Eloquent\\ModelNotFoundException\\:\:setModel\(\) expects class\-string\, class\-string\ given\.$#' + identifier: argument.type count: 2 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$array of function array_flip expects array\\, mixed given\\.$#" + message: '#^Parameter \#1 \$name of method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setConnection\(\) expects string, string\|null given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$builder of method Illuminate\\\\Database\\\\Eloquent\\\\Scope\\:\\:apply\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Builder, Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder given\\.$#" + message: '#^Parameter \#1 \$relations of method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:parseWithRelations\(\) expects array, mixed given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$callback of function call_user_func_array expects callable\\(\\)\\: mixed, Closure\\|null given\\.$#" - count: 2 - path: src/Database/Eloquent/Builder.php - - - - message: "#^Parameter \\#1 \\$column of method Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\\:\\:where\\(\\) expects Closure\\|string\\|Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\\|Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\TwoElementsLogicExpression, mixed given\\.$#" + message: '#^Parameter \#1 \$scope of method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:callScope\(\) expects callable\(\)\: mixed, array\{Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model, non\-falsy\-string\} given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$model of method Illuminate\\\\Database\\\\Eloquent\\\\ModelNotFoundException\\\\:\\:setModel\\(\\) expects class\\-string\\, class\\-string\\ given\\.$#" - count: 2 - path: src/Database/Eloquent/Builder.php - - - - message: "#^Parameter \\#1 \\$name of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setConnection\\(\\) expects string, string\\|null given\\.$#" + message: '#^Parameter \#1 \$value of function count expects array\|Countable, array\\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\|Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|static\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\)\|null given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$relations of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:parseWithRelations\\(\\) expects array, mixed given\\.$#" + message: '#^Parameter \#1 \$value of function count expects array\|Countable, array\|Illuminate\\Contracts\\Support\\Arrayable given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$scope of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:callScope\\(\\) expects callable\\(\\)\\: mixed, array\\{Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model, non\\-falsy\\-string\\} given\\.$#" + message: '#^Parameter \#2 \$boolean of method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:createNestedWhere\(\) expects string, TValue\|null given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\|Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\)\\|null given\\.$#" + message: '#^Parameter \#2 \$ids of method Illuminate\\Database\\Eloquent\\ModelNotFoundException\\:\:setModel\(\) expects array\\|int\|string, mixed given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\|Illuminate\\\\Contracts\\\\Support\\\\Arrayable given\\.$#" + message: '#^Parameter \#2 \$model of method Illuminate\\Database\\Eloquent\\Scope\:\:apply\(\) expects Illuminate\\Database\\Eloquent\\Model, Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#2 \\$boolean of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:createNestedWhere\\(\\) expects string, mixed given\\.$#" + message: '#^Parameter \#3 \$tables of method Tinderbox\\ClickhouseBuilder\\Integrations\\Laravel\\Connection\:\:select\(\) expects array, true given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#2 \\$ids of method Illuminate\\\\Database\\\\Eloquent\\\\ModelNotFoundException\\\\:\\:setModel\\(\\) expects array\\\\|int\\|string, mixed given\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:\$eagerLoad type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#2 \\$model of method Illuminate\\\\Database\\\\Eloquent\\\\Scope\\:\\:apply\\(\\) expects Illuminate\\\\Database\\\\Eloquent\\\\Model, Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model given\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:\$localMacros type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Parameter \\#3 \\$tables of method Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\\:\\:select\\(\\) expects array, true given\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:\$macros type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$eagerLoad type has no value type specified in iterable type array\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:\$passthru type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$localMacros type has no value type specified in iterable type array\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:\$scopes type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$macros type has no value type specified in iterable type array\\.$#" + message: '#^Property Tinderbox\\ClickhouseBuilder\\Query\\BaseBuilder\:\:\$wheres \(array\\) does not accept array\\.$#' + identifier: assign.propertyType count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$passthru type has no value type specified in iterable type array\\.$#" + message: '#^Strict comparison using \=\=\= between Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model and null will always evaluate to false\.$#' + identifier: identical.alwaysFalse count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:\\$scopes type has no value type specified in iterable type array\\.$#" + message: '#^Strict comparison using \=\=\= between array and null will always evaluate to false\.$#' + identifier: identical.alwaysFalse count: 1 path: src/Database/Eloquent/Builder.php - - message: "#^Property Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\\:\\:\\$wheres \\(array\\\\) does not accept array\\\\.$#" + message: '#^Class "Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection" is not allowed to extend "Illuminate\\Database\\Eloquent\\Collection"\.$#' + identifier: ergebnis.noExtends count: 1 - path: src/Database/Eloquent/Builder.php + path: src/Database/Eloquent/Collection.php - - message: "#^Strict comparison using \\=\\=\\= between Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model and null will always evaluate to false\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection extends generic class Illuminate\\Database\\Eloquent\\Collection but does not specify its types\: TKey, TModel$#' + identifier: missingType.generics count: 1 - path: src/Database/Eloquent/Builder.php + path: src/Database/Eloquent/Collection.php - - message: "#^Strict comparison using \\=\\=\\= between array and null will always evaluate to false\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection is neither abstract nor final\.$#' + identifier: ergebnis.final count: 1 - path: src/Database/Eloquent/Builder.php + path: src/Database/Eloquent/Collection.php - - message: "#^Cannot call method getKeyName\\(\\) on Illuminate\\\\Database\\\\Eloquent\\\\Model\\|null\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\:\:find\(\) should return Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|static\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\) but returns mixed\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Collection.php - - message: "#^Class \"Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\" is not allowed to extend \"Illuminate\\\\Database\\\\Eloquent\\\\Collection\"\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Collection\:\:map\(\) return type with generic class Illuminate\\Support\\Collection does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Collection.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection extends generic class Illuminate\\\\Database\\\\Eloquent\\\\Collection but does not specify its types\\: TKey, TModel$#" + message: '#^Parameter \#1 \$key of method Illuminate\\Support\\Collection\<\(int\|string\),Illuminate\\Database\\Eloquent\\Model\>\:\:contains\(\) expects \(callable\(Illuminate\\Database\\Eloquent\\Model, int\|string\)\: bool\)\|Illuminate\\Database\\Eloquent\\Model\|string, Closure\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\)\: bool given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Collection.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection is neither abstract nor final\\.$#" + message: '#^Parameter \#1 \$key of method Illuminate\\Support\\Collection\<\(int\|string\),Illuminate\\Database\\Eloquent\\Model\>\:\:contains\(\) expects \(callable\(Illuminate\\Database\\Eloquent\\Model, int\|string\)\: bool\)\|Illuminate\\Database\\Eloquent\\Model\|string, mixed given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Collection.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\:\\:find\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\) but returns mixed\\.$#" + message: '#^Parameter \#2 \$callback of static method Illuminate\\Support\\Arr\:\:first\(\) expects \(callable\(Illuminate\\Database\\Eloquent\\Model, int\|string\)\: bool\)\|null, Closure\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\)\: bool given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Collection.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Collection\\:\\:map\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static count: 1 path: src/Database/Eloquent/Collection.php - - message: "#^Parameter \\#1 \\$key of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:contains\\(\\) expects \\(callable\\(Illuminate\\\\Database\\\\Eloquent\\\\Model, int\\|string\\)\\: bool\\)\\|Illuminate\\\\Database\\\\Eloquent\\\\Model\\|string, Closure\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\)\\: bool given\\.$#" + message: '#^Call to an undefined method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder\:\:withTrashed\(\)\.$#' + identifier: method.notFound count: 1 - path: src/Database/Eloquent/Collection.php + path: src/Database/Eloquent/Model.php - - message: "#^Parameter \\#1 \\$key of method Illuminate\\\\Support\\\\Collection\\<\\(int\\|string\\),Illuminate\\\\Database\\\\Eloquent\\\\Model\\>\\:\\:contains\\(\\) expects \\(callable\\(Illuminate\\\\Database\\\\Eloquent\\\\Model, int\\|string\\)\\: bool\\)\\|Illuminate\\\\Database\\\\Eloquent\\\\Model\\|string, mixed given\\.$#" + message: '#^Call to an undefined method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|Illuminate\\Database\\Eloquent\\Relations\\Relation\:\:first\(\)\.$#' + identifier: method.notFound count: 1 - path: src/Database/Eloquent/Collection.php + path: src/Database/Eloquent/Model.php - - message: "#^Parameter \\#2 \\$callback of static method Illuminate\\\\Support\\\\Arr\\:\\:first\\(\\) expects \\(callable\\(Illuminate\\\\Database\\\\Eloquent\\\\Model, int\\|string\\)\\: bool\\)\\|null, Closure\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\)\\: bool given\\.$#" + message: '#^Call to an undefined method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|Illuminate\\Database\\Eloquent\\Relations\\Relation\:\:where\(\)\.$#' + identifier: method.notFound count: 1 - path: src/Database/Eloquent/Collection.php + path: src/Database/Eloquent/Model.php - - message: "#^Unsafe usage of new static\\(\\)\\.$#" + message: '#^Call to an undefined method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|Illuminate\\Database\\Eloquent\\Relations\\Relation\:\:withTrashed\(\)\.$#' + identifier: method.notFound count: 1 - path: src/Database/Eloquent/Collection.php + path: src/Database/Eloquent/Model.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Builder\\:\\:withTrashed\\(\\)\\.$#" + message: '#^Call to an undefined static method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:insert\(\)\.$#' + identifier: staticMethod.notFound count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:first\\(\\)\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model implements generic interface ArrayAccess but does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:where\\(\\)\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model implements generic interface Illuminate\\Contracts\\Support\\Arrayable but does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Call to an undefined method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation\\:\\:withTrashed\\(\\)\\.$#" + message: '#^Constructor in Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model has parameter \$attributes with default value\.$#' + identifier: ergebnis.noConstructorParameterWithDefaultValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Call to an undefined static method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:insert\\(\\)\\.$#" - count: 1 + message: '#^Language construct isset\(\) should not be used\.$#' + identifier: ergebnis.noIsset + count: 2 path: src/Database/Eloquent/Model.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model implements generic interface ArrayAccess but does not specify its types\\: TKey, TValue$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__call\(\) has parameter \$parameters with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model implements generic interface Illuminate\\\\Contracts\\\\Support\\\\Arrayable but does not specify its types\\: TKey, TValue$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__call\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Constructor in Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model has parameter \\$attributes with default value\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__callStatic\(\) has parameter \$parameters with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Language construct isset\\(\\) should not be used\\.$#" - count: 2 + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__callStatic\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass + count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__call\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__construct\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__call\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__get\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__callStatic\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__isset\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__callStatic\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__set\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__construct\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:__unset\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__get\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:all\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__isset\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:boot\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__set\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:boot\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:__unset\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:bootIfNotBooted\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:all\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:bootIfNotBooted\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:boot\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:bootTraits\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:boot\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:bootTraits\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootIfNotBooted\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:childRouteBindingRelationshipName\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootIfNotBooted\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:clearBootedModels\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootTraits\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:clearBootedModels\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:bootTraits\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:fill\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:childRouteBindingRelationshipName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:fill\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:clearBootedModels\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:forceFill\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:clearBootedModels\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:forceFill\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:fill\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:forceFill\(\) should return \$this\(Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\) but returns mixed\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:fill\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getCasts\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:forceFill\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getCasts\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:forceFill\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getConnection\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:forceFill\\(\\) should return \\$this\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\) but returns mixed\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getConnectionName\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getCasts\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getConnectionResolver\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getCasts\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getDateFormat\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getDates\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnectionName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getDates\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getConnectionResolver\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getForeignKey\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getDateFormat\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getKey\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getDates\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getKeyName\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getDates\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getKeyType\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getForeignKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getPerPage\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getQualifiedKeyName\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getRouteKey\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getKeyType\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getRouteKeyName\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getPerPage\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getTable\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getQualifiedKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:jsonSerialize\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getRouteKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:jsonSerialize\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getRouteKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newBaseQueryBuilder\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getTable\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newCollection\(\) has parameter \$models with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:jsonSerialize\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newCollection\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:jsonSerialize\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newEloquentBuilder\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newBaseQueryBuilder\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newFromBuilder\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newCollection\\(\\) has parameter \\$models with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newFromBuilder\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newCollection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newInstance\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newEloquentBuilder\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newInstance\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newFromBuilder\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newQuery\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newFromBuilder\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newQueryWithoutScope\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newInstance\\(\\) has parameter \\$attributes with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newQueryWithoutScope\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newInstance\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:newQueryWithoutScopes\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQuery\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:offsetExists\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQueryWithoutScope\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:offsetGet\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQueryWithoutScope\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:offsetSet\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:newQueryWithoutScopes\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:offsetUnset\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetExists\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:preventsAccessingMissingAttributes\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetGet\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:query\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetSet\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:removeTableFromKey\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:offsetUnset\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:removeTableFromKey\(\) should return string but returns mixed\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:preventsAccessingMissingAttributes\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveChildRouteBinding\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:query\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveChildRouteBinding\(\) should return Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|null but returns Illuminate\\Database\\Eloquent\\Model\|null\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:removeTableFromKey\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveChildRouteBindingQuery\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:removeTableFromKey\\(\\) should return string but returns mixed\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveChildRouteBindingQuery\(\) return type with generic class Illuminate\\Database\\Eloquent\\Relations\\Relation does not specify its types\: TRelatedModel, TDeclaringModel, TResult$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveChildRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveConnection\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveChildRouteBindingQuery\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveRouteBinding\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveChildRouteBindingQuery\\(\\) return type with generic class Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation does not specify its types\\: TRelatedModel$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveRouteBinding\(\) should return Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\|null but returns mixed\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveRouteBindingQuery\(\) has parameter \$query with generic class Illuminate\\Database\\Eloquent\\Relations\\Relation but does not specify its types\: TRelatedModel, TDeclaringModel, TResult$#' + identifier: missingType.generics count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveRouteBindingQuery\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBinding\\(\\) should return Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\|null but returns object\\|null\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveRouteBindingQuery\(\) should return Bavix\\LaravelClickHouse\\Database\\Eloquent\\Builder but returns Illuminate\\Database\\Eloquent\\Relations\\Relation\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBindingQuery\\(\\) has parameter \\$query with generic class Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\Relation but does not specify its types\\: TRelatedModel$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveSoftDeletableChildRouteBinding\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveRouteBindingQuery\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:resolveSoftDeletableRouteBinding\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveSoftDeletableChildRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:save\(\) has parameter \$options with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:resolveSoftDeletableRouteBinding\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:save\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:save\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setConnection\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:save\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setConnectionResolver\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setConnection\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setKeyName\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setConnectionResolver\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setKeyType\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setKeyName\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setPerPage\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setKeyType\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setTable\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setPerPage\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:toArray\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setTable\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:toJson\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:toArray\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:toJson\(\) should return string but returns string\|false\.$#' + identifier: return.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:toJson\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:whenBooted\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:toJson\\(\\) should return string but returns string\\|false\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:whenBooted\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:with\\(\\) has parameter \\$relations with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:with\(\) has parameter \$relations with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:with\\(\\) is not final, but since the containing class is abstract, it should be\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:with\(\) is not final, but since the containing class is abstract, it should be\.$#' + identifier: ergebnis.finalInAbstractClass count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Parameter \\#1 \\$callback of function forward_static_call expects callable\\(\\)\\: mixed, array\\{class\\-string\\, non\\-falsy\\-string\\} given\\.$#" + message: '#^Parameter \#1 \$callback of function forward_static_call expects callable\(\)\: mixed, array\{class\-string\, non\-falsy\-string\} given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Parameter \\#1 \\$key of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:getAttribute\\(\\) expects string, mixed given\\.$#" + message: '#^Parameter \#1 \$key of method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:getAttribute\(\) expects string, mixed given\.$#' + identifier: argument.type count: 2 path: src/Database/Eloquent/Model.php - - message: "#^Parameter \\#1 \\$key of method Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:setAttribute\\(\\) expects string, mixed given\\.$#" + message: '#^Parameter \#1 \$key of method Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:setAttribute\(\) expects string, mixed given\.$#' + identifier: argument.type count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$booted type has no value type specified in iterable type array\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:\$booted type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$casts \\(array\\) on left side of \\?\\? is not nullable\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:\$casts \(array\) on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.property count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$dateFormat \\(string\\) on left side of \\?\\? is not nullable\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:\$table \(string\) in isset\(\) is not nullable\.$#' + identifier: isset.property count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$table \\(string\\) in isset\\(\\) is not nullable\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:\$with type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$with type has no value type specified in iterable type array\\.$#" + message: '#^Property Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model\:\:\$withCount type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Property Bavix\\\\LaravelClickHouse\\\\Database\\\\Eloquent\\\\Model\\:\\:\\$withCount type has no value type specified in iterable type array\\.$#" + message: '#^Trait Illuminate\\Database\\Eloquent\\Concerns\\HasRelationships requires using class to extend Illuminate\\Database\\Eloquent\\Model, but Bavix\\LaravelClickHouse\\Database\\Eloquent\\Model does not\.$#' + identifier: class.missingExtends count: 1 path: src/Database/Eloquent/Model.php - - message: "#^Unsafe usage of new static\\(\\)\\.$#" + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static count: 5 path: src/Database/Eloquent/Model.php - - message: "#^Cannot access offset 'count' on mixed\\.$#" + message: '#^Cannot access offset ''count'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible count: 1 path: src/Database/Query/Builder.php - - message: "#^Cannot call method getTable\\(\\) on Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\From\\|null\\.$#" + message: '#^Cannot call method getTable\(\) on Tinderbox\\ClickhouseBuilder\\Query\\From\|null\.$#' + identifier: method.nonObject count: 1 path: src/Database/Query/Builder.php - - message: "#^Cannot cast mixed to int\\.$#" + message: '#^Cannot cast mixed to int\.$#' + identifier: cast.int count: 2 path: src/Database/Query/Builder.php - - message: "#^Class \"Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\" is not allowed to extend \"Tinderbox\\\\ClickhouseBuilder\\\\Query\\\\BaseBuilder\"\\.$#" + message: '#^Class "Bavix\\LaravelClickHouse\\Database\\Query\\Builder" is not allowed to extend "Tinderbox\\ClickhouseBuilder\\Query\\BaseBuilder"\.$#' + identifier: ergebnis.noExtends count: 1 path: src/Database/Query/Builder.php - - message: "#^Class Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder is neither abstract nor final\\.$#" + message: '#^Class Bavix\\LaravelClickHouse\\Database\\Query\\Builder is neither abstract nor final\.$#' + identifier: ergebnis.final count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:forPage\\(\\) should return \\$this\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\) but returns static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\)\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:forPage\(\) should return \$this\(Bavix\\LaravelClickHouse\\Database\\Query\\Builder\) but returns static\(Bavix\\LaravelClickHouse\\Database\\Query\\Builder\)\.$#' + identifier: return.type count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:get\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:get\(\) return type with generic class Illuminate\\Support\\Collection does not specify its types\: TKey, TValue$#' + identifier: missingType.generics count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:getCountForPagination\\(\\) has no return type specified\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:getCountForPagination\(\) has no return type specified\.$#' + identifier: missingType.return count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insert\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:insert\(\) has parameter \$values with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insertFiles\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:insertFiles\(\) has parameter \$columns with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insertFiles\\(\\) has parameter \\$files with no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:insertFiles\(\) has parameter \$files with no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Query/Builder.php - - message: "#^Method Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\:\\:insertFiles\\(\\) return type has no value type specified in iterable type array\\.$#" + message: '#^Method Bavix\\LaravelClickHouse\\Database\\Query\\Builder\:\:insertFiles\(\) return type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue count: 1 path: src/Database/Query/Builder.php - - message: "#^Parameter \\#1 \\$table of method Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Connection\\:\\:table\\(\\) expects Closure\\|string\\|Tinderbox\\\\ClickhouseBuilder\\\\Integrations\\\\Laravel\\\\Builder, static\\(Bavix\\\\LaravelClickHouse\\\\Database\\\\Query\\\\Builder\\) given\\.$#" + message: '#^Parameter \#1 \$table of method Tinderbox\\ClickhouseBuilder\\Integrations\\Laravel\\Connection\:\:table\(\) expects Closure\|string\|Tinderbox\\ClickhouseBuilder\\Integrations\\Laravel\\Builder, static\(Bavix\\LaravelClickHouse\\Database\\Query\\Builder\) given\.$#' + identifier: argument.type count: 1 path: src/Database/Query/Builder.php - - message: "#^Unsafe usage of new static\\(\\)\\.$#" + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static count: 1 path: src/Database/Query/Builder.php diff --git a/src/Database/Eloquent/Model.php b/src/Database/Eloquent/Model.php index 4efb015..36b8a9b 100644 --- a/src/Database/Eloquent/Model.php +++ b/src/Database/Eloquent/Model.php @@ -7,6 +7,7 @@ use ArrayAccess; use Bavix\LaravelClickHouse\Database\Connection; use Bavix\LaravelClickHouse\Database\Query\Builder as QueryBuilder; +use Closure; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Routing\UrlRoutable; use Illuminate\Contracts\Support\Arrayable; @@ -626,6 +627,10 @@ public static function preventsAccessingMissingAttributes(): bool return static::$modelsShouldPreventAccessingMissingAttributes; } + protected static function whenBooted(Closure $callback) + { + } + protected function resolveChildRouteBindingQuery( string $childType, mixed $value, diff --git a/src/Database/Query/Builder.php b/src/Database/Query/Builder.php index 55a1548..58e8419 100644 --- a/src/Database/Query/Builder.php +++ b/src/Database/Query/Builder.php @@ -21,10 +21,8 @@ class Builder extends BaseBuilder protected Connection $connection; - public function __construct( - Connection $connection, - Grammar $grammar - ) { + public function __construct(Connection $connection, Grammar $grammar) + { $this->connection = $connection; $this->grammar = $grammar; } From 25b42b315c3f51048275c49653de7c77807411e5 Mon Sep 17 00:00:00 2001 From: Github bot Date: Tue, 27 May 2025 18:15:30 +0000 Subject: [PATCH 69/69] Update changelog.md --- changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/changelog.md b/changelog.md index 90817a2..233032c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 3.0.5 - 2025-05-27 + +### What's Changed + +* req bavix/clickhouse-php-client by [@rez1dent3](https://github.com/rez1dent3) in https://github.com/bavix/laravel-clickhouse/pull/15 + +**Full Changelog**: https://github.com/bavix/laravel-clickhouse/compare/3.0.4...3.0.5 + ## 3.0.3 - 2024-04-01 ### What's Changed