Skip to content

Commit 5cd1a62

Browse files
committed
Merge branch 'type-hints'
1 parent fecf727 commit 5cd1a62

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+389
-655
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Once the Docker environment is running, you can run the tests more quickly on th
5757

5858
Once running, if you prefer, you can also just shell into the PHP container and run the tests from there, for example:
5959

60-
docker compose exec php sh
60+
docker compose exec php bash
6161
composer update
6262
composer test
6363
exit

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"mindplay/testies": "^1.0",
2626
"mindplay/benchpress": "^0.1",
2727
"mockery/mockery": "^1.5.1",
28-
"phpunit/php-code-coverage": "^9.2.19"
28+
"phpunit/php-code-coverage": "^9.2.19",
29+
"phpstan/phpstan": "^1.11"
2930
},
3031
"suggest": {
3132
"ext-pdo_pgsql": "for PostgreSQL support (duh.)",

phpstan.neon

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
parameters:
2+
level: 8
3+
paths:
4+
- src

src/exceptions/SQLException.php

+12-7
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@
1212
class SQLException extends RuntimeException
1313
{
1414
/**
15-
* @param string $sql SQL statement (with ":name" placeholders)
16-
* @param array $params map of parameter name/value pairs (to bind against placeholders in the statement)
17-
* @param string $message
18-
* @param int $code
19-
* @param Exception|null $previous
15+
* @param string $sql SQL statement (with ":name" placeholders)
16+
* @param array<string,mixed> $params map of parameter name/value pairs (to bind against placeholders in the statement)
17+
* @param string $message
18+
* @param int $code
19+
* @param Exception|null $previous
2020
*/
21-
public function __construct($sql, $params = [], $message = 'SQL Error', $code = 0, Exception $previous = null)
22-
{
21+
public function __construct(
22+
string $sql,
23+
array $params = [],
24+
string $message = 'SQL Error',
25+
int $code = 0,
26+
Exception $previous = null
27+
) {
2328
parent::__construct(
2429
"{$message}\n" . QueryFormatter::formatQuery($sql, $params),
2530
$code,

src/framework/BufferedPSRLogger.php

+8-5
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@
1818
class BufferedPSRLogger implements Logger
1919
{
2020
/**
21-
* @var array
21+
* @var array<string,mixed>[] buffered query log-entries
2222
*/
23-
private $entries = [];
23+
private array $entries = [];
2424

2525
/**
2626
* Flush all recorded query log-entries to a single PSR-3 log-entry
2727
*
2828
* @param LoggerInterface $logger the PSR Logger to which the query-log will be flushed
29-
* @param string|mixed $log_level PSR-3 log level (defaults to INFO)
29+
* @param string|mixed $log_level PSR-3 log level (usually a string, defaults to "info")
3030
* @param string $message combined log entry title
3131
*
3232
* @see LogLevel
3333
*/
34-
public function flushTo(LoggerInterface $logger, $log_level = LogLevel::INFO, $message = "INFO")
34+
public function flushTo(LoggerInterface $logger, mixed $log_level = LogLevel::INFO, string $message = "INFO"): void
3535
{
3636
$logger->log(
3737
$log_level,
@@ -42,7 +42,10 @@ public function flushTo(LoggerInterface $logger, $log_level = LogLevel::INFO, $m
4242
$this->entries = [];
4343
}
4444

45-
public function logQuery($sql, $params, $time_msec)
45+
/**
46+
* @param array<string,mixed> $params
47+
*/
48+
public function logQuery(string $sql, array $params, float $time_msec): void
4649
{
4750
$this->entries[] = [
4851
"time" => sprintf('%0.3f', $time_msec / 1000) . " s",

src/framework/Connection.php

+10-10
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ interface Connection
2525
*
2626
* @return Result
2727
*/
28-
public function fetch(Statement $statement, $batch_size = 1000);
28+
public function fetch(Statement $statement, int $batch_size = 1000);
2929

3030
/**
3131
* Execute an SQL statement, which does not produce a result, e.g. an "INSERT", "UPDATE" or "DELETE" statement.
@@ -34,16 +34,16 @@ public function fetch(Statement $statement, $batch_size = 1000);
3434
*
3535
* @return PreparedStatement
3636
*/
37-
public function execute(Statement $statement);
38-
37+
38+
public function execute(Statement $statement): PreparedStatement;
3939
/**
4040
* Prepare an SQL statement.
4141
*
4242
* @param Statement $statement
4343
*
4444
* @return PreparedStatement
4545
*/
46-
public function prepare(Statement $statement);
46+
public function prepare(Statement $statement): PreparedStatement;
4747

4848
/**
4949
* Execute a `SELECT COUNT(*)` SQL statement and return the result.
@@ -52,10 +52,10 @@ public function prepare(Statement $statement);
5252
*
5353
* @return int
5454
*/
55-
public function count(Countable $statement);
55+
public function count(Countable $statement): int;
5656

5757
/**
58-
* @param callable $func function () : bool - must return TRUE to commit or FALSE to roll back
58+
* @param callable():bool $func function (): bool - must return TRUE to commit or FALSE to roll back
5959
*
6060
* @return bool TRUE on success (committed) or FALSE on failure (rolled back)
6161
*
@@ -65,14 +65,14 @@ public function count(Countable $statement);
6565
* @throws LogicException if an unhandled Exception occurs while calling the provided function
6666
* @throws UnexpectedValueException if the provided function does not return TRUE or FALSE
6767
*/
68-
public function transact(callable $func);
68+
public function transact(callable $func): bool;
6969

7070
/**
7171
* @param string|null $sequence_name auto-sequence name (or NULL for e.g. MySQL which supports only one auto-key)
7272
*
73-
* @return mixed
73+
* @return string|int|null the last auto-generated ID (usually an integer, could be a string for UUIDs, etc.)
7474
*/
75-
public function lastInsertId($sequence_name = null);
75+
public function lastInsertId(?string $sequence_name = null): string|int|null;
7676

7777
/**
7878
* Add a `Logger` instance, which will be notified when a query is executed.
@@ -81,5 +81,5 @@ public function lastInsertId($sequence_name = null);
8181
*
8282
* @return void
8383
*/
84-
public function addLogger(Logger $logger);
84+
public function addLogger(Logger $logger): void;
8585
}

src/framework/Countable.php

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,5 @@
99
*/
1010
interface Countable
1111
{
12-
/**
13-
* @return Statement
14-
*/
15-
public function createCountStatement();
12+
public function createCountStatement(): Statement;
1613
}

src/framework/Logger.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ interface Logger
1010
/**
1111
* This function is called every time a query has been executed
1212
*
13-
* @param string $sql SQL statement
14-
* @param array $params placeholder name/value pairs
15-
* @param float $time_msec execution time (in milliseconds)
13+
* @param string $sql SQL statement
14+
* @param array<string,mixed> $params placeholder name/value pairs
15+
* @param float $time_msec execution time (in milliseconds)
1616
*
1717
* @return void
1818
*/
19-
public function logQuery($sql, $params, $time_msec);
19+
public function logQuery(string $sql, array $params, float $time_msec): void;
2020
}

src/framework/Mapper.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
interface Mapper
1111
{
1212
/**
13-
* @param array $record_set
14-
*
15-
* @return array|Traversable
13+
* @param array<string,mixed>[] $record_set
14+
*
15+
* @return iterable<array<string,mixed>>
1616
*/
17-
public function map(array $record_set);
17+
public function map(array $record_set): array|Traversable;
1818
}

src/framework/MapperProvider.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ interface MapperProvider
1313
/**
1414
* @return Mapper[] list of Mappers to apply while fetching returned records
1515
*/
16-
public function getMappers();
16+
public function getMappers(): array;
1717
}

src/framework/PreparedStatement.php

+7-11
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,27 @@ interface PreparedStatement
1212
/**
1313
* Bind an individual placeholder name to a given scalar (int|float|string|bool|null) value.
1414
*
15-
* @param string $name placeholder name
16-
* @param int|float|string|bool|null $value scalar value
17-
*
18-
* @return void
15+
* @param $name placeholder name
16+
* @param $value scalar value
1917
*/
20-
public function bind($name, $value);
18+
public function bind(string $name, int|float|string|bool|null $value): void;
2119

2220
/**
2321
* Executes the underlying SQL statement.
2422
*
25-
* @return void
26-
*
2723
* @throws SQLException on failure to execute the underlying SQL statement
2824
*/
29-
public function execute();
25+
public function execute(): void;
3026

3127
/**
3228
* Fetches the next record from the result set and advances the cursor.
3329
*
34-
* @return array|null next record-set (or NULL, if no more records are available)
30+
* @return array<string,mixed>|null next record-set (or NULL, if no more records are available)
3531
*/
36-
public function fetch();
32+
public function fetch(): array|null;
3733

3834
/**
3935
* @return int number of rows affected by a non-returning query (e.g. INSERT, UPDATE or DELETE)
4036
*/
41-
public function getRowsAffected();
37+
public function getRowsAffected(): int;
4238
}

src/framework/QueryFormatter.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
abstract class QueryFormatter
1111
{
1212
/**
13-
* @param string $sql
14-
* @param array $params
13+
* @param string $sql
14+
* @param array<string,mixed> $params
1515
*
1616
* @return string SQL with emulated prepare (for diagnostic purposes only)
1717
*/
18-
public static function formatQuery($sql, $params)
18+
public static function formatQuery(string $sql, array $params): string
1919
{
2020
$quoted_params = [];
2121

src/framework/Result.php

+12-17
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,35 @@
1313
*
1414
* It implements `IteratorAggregate`, allowing you to execute the query and iterate
1515
* over the result set with a `foreach` statement.
16+
*
17+
* @implements IteratorAggregate<array<string,mixed>>
1618
*/
1719
class Result implements IteratorAggregate
1820
{
19-
/**
20-
* @var PreparedStatement
21-
*/
22-
private $statement;
23-
24-
/**
25-
* @var int
26-
*/
27-
private $batch_size;
21+
private PreparedStatement $statement;
22+
private int $batch_size;
2823

2924
/**
3025
* @var Mapper[] list of Mappers to apply when fetching results
3126
*/
32-
private $mappers;
27+
private array $mappers;
3328

3429
/**
3530
* @param PreparedStatement $statement prepared statement
3631
* @param int $batch_size batch-size (when fetching large result sets)
3732
* @param Mapper[] $mappers list of Mappers to apply while fetching results
3833
*/
39-
public function __construct(PreparedStatement $statement, $batch_size, array $mappers)
34+
public function __construct(PreparedStatement $statement, int $batch_size, array $mappers)
4035
{
4136
$this->statement = $statement;
4237
$this->batch_size = $batch_size;
4338
$this->mappers = $mappers;
4439
}
4540

4641
/**
47-
* @return mixed|null first record of the record-set (or NULL, if the record-set is empty)
42+
* @return array<string,mixed>|null first record of the record-set (or NULL, if the record-set is empty)
4843
*/
49-
public function firstRow()
44+
public function firstRow(): array|null
5045
{
5146
foreach ($this->createIterator(1) as $record) {
5247
return $record; // break from loop immediately after fetching the first record
@@ -58,7 +53,7 @@ public function firstRow()
5853
/**
5954
* @return mixed|null first column value of the first record of the record-set (or NULL, if the record-set is empty)
6055
*/
61-
public function firstCol()
56+
public function firstCol(): mixed
6257
{
6358
foreach ($this->createIterator(1) as $record) {
6459
$keys = array_keys($record);
@@ -70,9 +65,9 @@ public function firstCol()
7065
}
7166

7267
/**
73-
* @return array all the records of the record-set
68+
* @return array<array<string,mixed>> all the records of the record-set
7469
*/
75-
public function all()
70+
public function all(): array
7671
{
7772
return iterator_to_array($this->getIterator());
7873
}
@@ -95,7 +90,7 @@ public function getIterator(): Traversable
9590
*
9691
* @return Iterator
9792
*/
98-
private function createIterator($batch_size)
93+
private function createIterator($batch_size): Iterator
9994
{
10095
$fetching = true;
10196

src/framework/Statement.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ interface Statement
1414
/**
1515
* @return string SQL statement (with placeholders)
1616
*/
17-
public function getSQL();
17+
public function getSQL(): string;
1818

1919
/**
20-
* @return array map where placeholder name maps to a scalar value, or arrays of scalar values
20+
* @return array<string,string|int|float|bool|null|array<string|int|float|bool|null>> map where placeholder name maps to a scalar value, or arrays of scalar values
2121
*/
22-
public function getParams();
22+
public function getParams(): array;
2323
}

src/framework/mappers/BatchMapper.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,28 @@
33
namespace mindplay\sql\framework\mappers;
44

55
use mindplay\sql\framework\Mapper;
6+
use Traversable;
67

78
/**
89
* Use this Mapper for quick, on-demand batch mapping - as an alternative to implementing an actual Mapper class.
910
*/
1011
class BatchMapper implements Mapper
1112
{
1213
/**
13-
* @var callable
14+
* @var callable(array<array<string,mixed>>):iterable<array<string,mixed>>
1415
*/
1516
private $mapper;
1617

1718
/**
18-
* @param callable $mapper function (array $record_set) : array
19+
* @param callable(array<array<string,mixed>>):iterable<array<string,mixed>> $mapper function (array $record_set): array
1920
*/
2021
public function __construct(callable $mapper)
2122
{
2223
$this->mapper = $mapper;
2324
}
2425

25-
public function map(array $record_set)
26+
public function map(array $record_set): array|Traversable
2627
{
27-
return call_user_func($this->mapper, $record_set);
28+
return ($this->mapper)($record_set);
2829
}
2930
}

0 commit comments

Comments
 (0)