Skip to content
Merged
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
11 changes: 9 additions & 2 deletions src/Driver/Mysqli/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,17 @@ final class Result implements ResultInterface
/**
* @internal The result can be only instantiated by its driver connection or statement.
*
* @param Statement|null $statementReference Maintains a reference to the Statement that generated this result. This
* ensures that the lifetime of the Statement is managed in conjunction
* with its associated results, so they are destroyed together at the
* appropriate time, see {@see Statement::__destruct()}.
*
* @throws Exception
*/
public function __construct(private readonly mysqli_stmt $statement)
{
public function __construct(
private readonly mysqli_stmt $statement,
private ?Statement $statementReference = null, // @phpstan-ignore property.onlyWritten
) {
$meta = $statement->result_metadata();
$this->hasColumns = $meta !== false;
$this->columnNames = $meta !== false ? array_column($meta->fetch_fields(), 'name') : [];
Expand Down
7 changes: 6 additions & 1 deletion src/Driver/Mysqli/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public function __construct(private readonly mysqli_stmt $stmt)
$this->boundValues = array_fill(1, $paramCount, null);
}

public function __destruct()
{
@$this->stmt->close();
}

public function bindValue(int|string $param, mixed $value, ParameterType $type): void
{
assert(is_int($param));
Expand All @@ -72,7 +77,7 @@ public function execute(): Result
throw StatementError::upcast($e);
}

return new Result($this->stmt);
return new Result($this->stmt, $this);
}

/**
Expand Down
46 changes: 46 additions & 0 deletions tests/Functional/Driver/Mysqli/StatementTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Tests\Functional\Driver\Mysqli;

use Doctrine\DBAL\Driver\Mysqli\Statement;
use Doctrine\DBAL\Statement as WrapperStatement;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use Doctrine\DBAL\Tests\TestUtil;
use Error;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use ReflectionProperty;

#[RequiresPhpExtension('mysqli')]
class StatementTest extends FunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();

if (TestUtil::isDriverOneOf('mysqli')) {
return;
}

self::markTestSkipped('This test requires the mysqli driver.');
}

public function testStatementsAreDeallocatedProperly(): void
{
$statement = $this->connection->prepare('SELECT 1');

$property = new ReflectionProperty(WrapperStatement::class, 'stmt');
$driverStatement = $property->getValue($statement);

$mysqliProperty = new ReflectionProperty(Statement::class, 'stmt');
$mysqliStatement = $mysqliProperty->getValue($driverStatement);

unset($statement, $driverStatement);

$this->expectException(Error::class);
$this->expectExceptionMessage('mysqli_stmt object is already closed');

$mysqliStatement->execute();
}
}
Loading