Skip to content

Commit f76b790

Browse files
committed
Make Realtime Database value objects final and readonly
1 parent 80dd563 commit f76b790

File tree

8 files changed

+74
-37
lines changed

8 files changed

+74
-37
lines changed

.php-cs-fixer.dist.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
'method_argument_space' => [
2626
'attribute_placement' => 'standalone', // same_line can break PHP <8.2
2727
],
28+
'no_blank_lines_after_phpdoc' => true,
29+
'no_empty_phpdoc' => true,
30+
'no_unneeded_braces' => true,
2831
'no_unused_imports' => true,
2932
'ordered_imports' => [
3033
'imports_order' => [
@@ -34,6 +37,9 @@
3437
],
3538
'sort_algorithm' => 'alpha',
3639
],
40+
'phpdoc_align' => [
41+
'align' => 'left',
42+
],
3743
'php_unit_method_casing' => [
3844
'case' => 'camel_case',
3945
],

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ If it saves you or your team time, please consider [sponsoring its development](
1515
* Type declarations have been simplified to reduce runtime overhead (e.g., `Stringable|string` to `string`).
1616
* The transitional `Kreait\Firebase\Contract\Transitional\FederatedUserFetcher::getUserByProviderUid()` method
1717
has been moved into the `Kreait\Firebase\Contract\Auth` interface
18+
* Realtime Database objects considered value objects have been made final and readonly
1819

1920
See **[UPGRADE-8.0](UPGRADE-8.0.md) for more details on the changes between 7.x and 8.0.**
2021

UPGRADE-8.0.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ from 7.x to 8.0.
1111
supported versions are 8.3, 8.4, and 8.5.
1212
* [Firebase Dynamic Links was shut down on August 25th, 2025](https://firebase.google.com/support/dynamic-links-faq)
1313
and has been removed from the SDK.
14+
* Realtime Database objects considered value objects have been made final and readonly
1415

1516
### Type simplifications to reduce runtime overhead
1617

@@ -29,6 +30,10 @@ The following list has been generated with [roave/backward-compatibility-check](
2930

3031
```
3132
[BC] ADDED: Method getUserByProviderUid() was added to interface Kreait\Firebase\Contract\Auth
33+
[BC] CHANGED: Class Kreait\Firebase\Database\Query became final
34+
[BC] CHANGED: Class Kreait\Firebase\Database\Reference became final
35+
[BC] CHANGED: Class Kreait\Firebase\Database\RuleSet became final
36+
[BC] CHANGED: Class Kreait\Firebase\Database\Snapshot became final
3237
[BC] CHANGED: Default parameter value for parameter $code of Kreait\Firebase\Exception\Database\TransactionFailed#__construct() changed from 0 to NULL
3338
[BC] CHANGED: Default parameter value for parameter $code of Kreait\Firebase\Exception\Database\UnsupportedQuery#__construct() changed from 0 to NULL
3439
[BC] CHANGED: The number of required arguments for Kreait\Firebase\Exception\Database\UnsupportedQuery#__construct() increased from 1 to 2

src/Firebase/Database/Query.php

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Kreait\Firebase\Database\Query\Filter\StartAfter;
1515
use Kreait\Firebase\Database\Query\Filter\StartAt;
1616
use Kreait\Firebase\Database\Query\Sorter;
17+
use Kreait\Firebase\Database\Query\Sorter\Noop;
1718
use Kreait\Firebase\Database\Query\Sorter\OrderByChild;
1819
use Kreait\Firebase\Database\Query\Sorter\OrderByKey;
1920
use Kreait\Firebase\Database\Query\Sorter\OrderByValue;
@@ -34,19 +35,19 @@
3435
* {@see getSnapshot()} or {@see getValue()} method. You will only receive
3536
* Snapshots for the subset of the data that matches your query.
3637
*/
37-
class Query implements Stringable
38+
final readonly class Query implements Stringable
3839
{
39-
/**
40-
* @var Filter[]
41-
*/
42-
private array $filters = [];
43-
44-
private ?Sorter $sorter = null;
45-
4640
/**
4741
* @internal
42+
*
43+
* @param list<Filter> $filters
4844
*/
49-
public function __construct(private readonly Reference $reference, private readonly ApiClient $apiClient)
45+
public function __construct(
46+
private Reference $reference,
47+
private ApiClient $apiClient,
48+
private array $filters,
49+
private Sorter $sorter,
50+
)
5051
{
5152
}
5253

@@ -91,9 +92,7 @@ public function getSnapshot(): Snapshot
9192
);
9293
}
9394

94-
if ($this->sorter !== null) {
95-
$value = $this->sorter->modifyValue($value);
96-
}
95+
$value = $this->sorter->modifyValue($value);
9796

9897
foreach ($this->filters as $filter) {
9998
$value = $filter->modifyValue($value);
@@ -253,10 +252,7 @@ public function shallow(): self
253252
public function getUri(): UriInterface
254253
{
255254
$uri = $this->reference->getUri();
256-
257-
if ($this->sorter !== null) {
258-
$uri = $this->sorter->modifyUri($uri);
259-
}
255+
$uri = $this->sorter->modifyUri($uri);
260256

261257
foreach ($this->filters as $filter) {
262258
$uri = $filter->modifyUri($uri);
@@ -267,21 +263,25 @@ public function getUri(): UriInterface
267263

268264
private function withAddedFilter(Filter $filter): self
269265
{
270-
$query = clone $this;
271-
$query->filters[] = $filter;
272-
273-
return $query;
266+
return new self(
267+
$this->reference,
268+
$this->apiClient,
269+
[...$this->filters, $filter],
270+
$this->sorter
271+
);
274272
}
275273

276274
private function withSorter(Sorter $sorter): self
277275
{
278-
if ($this->sorter !== null) {
276+
if (!($this->sorter instanceof Noop)) {
279277
throw new UnsupportedQuery($this, 'This query is already ordered.');
280278
}
281279

282-
$query = clone $this;
283-
$query->sorter = $sorter;
284-
285-
return $query;
280+
return new self(
281+
$this->reference,
282+
$this->apiClient,
283+
$this->filters,
284+
$sorter
285+
);
286286
}
287287
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Kreait\Firebase\Database\Query\Sorter;
6+
7+
use Kreait\Firebase\Database\Query\Sorter;
8+
use Psr\Http\Message\UriInterface;
9+
10+
/**
11+
* @internal
12+
*/
13+
final readonly class Noop implements Sorter
14+
{
15+
public function modifyUri(UriInterface $uri): UriInterface
16+
{
17+
return $uri;
18+
}
19+
20+
public function modifyValue(mixed $value): mixed
21+
{
22+
return $value;
23+
}
24+
}

src/Firebase/Database/Reference.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Kreait\Firebase\Database;
66

7+
use Kreait\Firebase\Database\Query\Sorter\Noop;
78
use Kreait\Firebase\Exception\DatabaseException;
89
use Kreait\Firebase\Exception\InvalidArgumentException;
910
use Kreait\Firebase\Exception\OutOfRangeException;
@@ -24,14 +25,14 @@
2425
* A Reference represents a specific location in your database and can be used
2526
* for reading or writing data to that database location.
2627
*/
27-
class Reference implements Stringable
28+
final readonly class Reference implements Stringable
2829
{
2930
/**
3031
* @internal
3132
*/
3233
public function __construct(
33-
private readonly UriInterface $uri,
34-
private readonly ApiClient $apiClient,
34+
private UriInterface $uri,
35+
private ApiClient $apiClient,
3536
) {
3637
}
3738

@@ -42,7 +43,7 @@ public function __construct(
4243
*/
4344
public function __toString(): string
4445
{
45-
return (string) $this->getUri();
46+
return (string) $this->uri;
4647
}
4748

4849
/**
@@ -74,12 +75,12 @@ public function getPath(): string
7475
*/
7576
public function getParent(): self
7677
{
77-
$parentPath = dirname($this->getPath());
78-
79-
if ($parentPath === '.') {
78+
if ($this->getPath() === '') {
8079
throw new OutOfRangeException('Cannot get parent of root reference');
8180
}
8281

82+
$parentPath = dirname($this->getPath());
83+
8384
return new self($this->uri->withPath('/'.ltrim($parentPath, '/')), $this->apiClient);
8485
}
8586

@@ -388,6 +389,6 @@ public function getUri(): UriInterface
388389
*/
389390
private function query(): Query
390391
{
391-
return new Query($this, $this->apiClient);
392+
return new Query($this, $this->apiClient, [], new Noop());
392393
}
393394
}

src/Firebase/Database/RuleSet.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
use function array_key_exists;
1010

11-
class RuleSet implements JsonSerializable
11+
final readonly class RuleSet implements JsonSerializable
1212
{
1313
/**
1414
* @var array<string, array<mixed>>
1515
*/
16-
private readonly array $rules;
16+
private array $rules;
1717

1818
/**
1919
* @param array<string, array<mixed>> $rules

src/Firebase/Database/Snapshot.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
* Alternatively, you can traverse into the snapshot by calling {@see getChild()}
2525
* to return child snapshots (which you could then call {@see getValue()} on).
2626
*/
27-
class Snapshot
27+
final readonly class Snapshot
2828
{
2929
/**
3030
* @internal
3131
*/
32-
public function __construct(private readonly Reference $reference, private readonly mixed $value)
32+
public function __construct(private Reference $reference, private mixed $value)
3333
{
3434
}
3535

0 commit comments

Comments
 (0)