Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/core/src/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,22 @@ protected function resolveCustomBuilderClass(): string|false
return $attributes[0]->newInstance()->builderClass;
}

/**
* Get a new query builder instance for the connection.
*
* Delegates to the connection so custom connections can provide
* custom query builders with additional methods.
*
* @return \Hyperf\Database\Query\Builder
*/
protected function newBaseQueryBuilder()
{
/** @var \Hyperf\Database\Connection $connection */
$connection = $this->getConnection();

return $connection->query();
}

/**
* @param array<array-key, static> $models
* @return \Hypervel\Database\Eloquent\Collection<array-key, static>
Expand Down
16 changes: 16 additions & 0 deletions src/core/src/Database/Eloquent/Relations/MorphPivot.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ class MorphPivot extends BaseMorphPivot
use HasObservers;
use HasTimestamps;

/**
* Get a new query builder instance for the connection.
*
* Delegates to the connection so custom connections can provide
* custom query builders with additional methods.
*
* @return \Hyperf\Database\Query\Builder
*/
protected function newBaseQueryBuilder()
{
/** @var \Hyperf\Database\Connection $connection */
$connection = $this->getConnection();

return $connection->query();
}

/**
* Delete the pivot model record from the database.
*
Expand Down
16 changes: 16 additions & 0 deletions src/core/src/Database/Eloquent/Relations/Pivot.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ class Pivot extends BasePivot
use HasObservers;
use HasTimestamps;

/**
* Get a new query builder instance for the connection.
*
* Delegates to the connection so custom connections can provide
* custom query builders with additional methods.
*
* @return \Hyperf\Database\Query\Builder
*/
protected function newBaseQueryBuilder()
{
/** @var \Hyperf\Database\Connection $connection */
$connection = $this->getConnection();

return $connection->query();
}

/**
* Delete the pivot model record from the database.
*
Expand Down
161 changes: 161 additions & 0 deletions tests/Core/Database/Eloquent/NewBaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

declare(strict_types=1);

namespace Hypervel\Tests\Core\Database\Eloquent;

use Hyperf\Database\ConnectionInterface;
use Hyperf\Database\Query\Builder as QueryBuilder;
use Hyperf\Database\Query\Grammars\Grammar;
use Hyperf\Database\Query\Processors\Processor;
use Hypervel\Database\Eloquent\Model;
use Hypervel\Database\Eloquent\Relations\MorphPivot;
use Hypervel\Database\Eloquent\Relations\Pivot;
use Hypervel\Testbench\TestCase;
use Mockery as m;

/**
* Tests that Model, Pivot, and MorphPivot delegate to the connection's
* query() method when creating base query builders. This allows custom
* connections to provide custom query builders with additional methods.
*
* @internal
* @coversNothing
*/
class NewBaseQueryBuilderTest extends TestCase
{
public function testModelUsesConnectionQueryMethod(): void
{
$customBuilder = new CustomQueryBuilder(
m::mock(ConnectionInterface::class),
new Grammar(),
new Processor()
);

$connection = m::mock(ConnectionInterface::class);
$connection->shouldReceive('query')->once()->andReturn($customBuilder);

$model = new NewBaseQueryBuilderTestModel();
$model->setTestConnection($connection);

$builder = $model->testNewBaseQueryBuilder();

$this->assertInstanceOf(CustomQueryBuilder::class, $builder);
$this->assertSame($customBuilder, $builder);
}

public function testPivotUsesConnectionQueryMethod(): void
{
$customBuilder = new CustomQueryBuilder(
m::mock(ConnectionInterface::class),
new Grammar(),
new Processor()
);

$connection = m::mock(ConnectionInterface::class);
$connection->shouldReceive('query')->once()->andReturn($customBuilder);

$pivot = new NewBaseQueryBuilderTestPivot();
$pivot->setTestConnection($connection);

$builder = $pivot->testNewBaseQueryBuilder();

$this->assertInstanceOf(CustomQueryBuilder::class, $builder);
$this->assertSame($customBuilder, $builder);
}

public function testMorphPivotUsesConnectionQueryMethod(): void
{
$customBuilder = new CustomQueryBuilder(
m::mock(ConnectionInterface::class),
new Grammar(),
new Processor()
);

$connection = m::mock(ConnectionInterface::class);
$connection->shouldReceive('query')->once()->andReturn($customBuilder);

$morphPivot = new NewBaseQueryBuilderTestMorphPivot();
$morphPivot->setTestConnection($connection);

$builder = $morphPivot->testNewBaseQueryBuilder();

$this->assertInstanceOf(CustomQueryBuilder::class, $builder);
$this->assertSame($customBuilder, $builder);
}
}

// Test fixtures

class NewBaseQueryBuilderTestModel extends Model
{
protected ?string $table = 'test_models';

protected ?ConnectionInterface $testConnection = null;

public function setTestConnection(ConnectionInterface $connection): void
{
$this->testConnection = $connection;
}

public function getConnection(): ConnectionInterface
{
return $this->testConnection ?? parent::getConnection();
}

public function testNewBaseQueryBuilder(): QueryBuilder
{
return $this->newBaseQueryBuilder();
}
}

class NewBaseQueryBuilderTestPivot extends Pivot
{
protected ?string $table = 'test_pivots';

protected ?ConnectionInterface $testConnection = null;

public function setTestConnection(ConnectionInterface $connection): void
{
$this->testConnection = $connection;
}

public function getConnection(): ConnectionInterface
{
return $this->testConnection ?? parent::getConnection();
}

public function testNewBaseQueryBuilder(): QueryBuilder
{
return $this->newBaseQueryBuilder();
}
}

class NewBaseQueryBuilderTestMorphPivot extends MorphPivot
{
protected ?string $table = 'test_morph_pivots';

protected ?ConnectionInterface $testConnection = null;

public function setTestConnection(ConnectionInterface $connection): void
{
$this->testConnection = $connection;
}

public function getConnection(): ConnectionInterface
{
return $this->testConnection ?? parent::getConnection();
}

public function testNewBaseQueryBuilder(): QueryBuilder
{
return $this->newBaseQueryBuilder();
}
}

/**
* A custom query builder to verify the connection's builder is used.
*/
class CustomQueryBuilder extends QueryBuilder
{
}