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)); } }