• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tempestphp / tempest-framework / 14662931729

25 Apr 2025 10:52AM UTC coverage: 80.242% (+0.02%) from 80.219%
14662931729

Pull #1174

github

web-flow
Merge 1300c0e23 into be8067395
Pull Request #1174: feat(database): add `Count` query builder and statement

62 of 73 new or added lines in 4 files covered. (84.93%)

11847 of 14764 relevant lines covered (80.24%)

106.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.58
/src/Tempest/Database/src/Builder/QueryBuilders/CountQueryBuilder.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Tempest\Database\Builder\QueryBuilders;
6

7
use Tempest\Database\Builder\ModelDefinition;
8
use Tempest\Database\Builder\TableDefinition;
9
use Tempest\Database\Exceptions\CannotCountDistinctWithoutSpecifyingAColumn;
10
use Tempest\Database\Query;
11
use Tempest\Database\QueryStatements\CountStatement;
12
use Tempest\Database\QueryStatements\WhereStatement;
13
use Tempest\Support\Conditions\HasConditions;
14

15
/**
16
 * @template TModelClass of object
17
 */
18
final class CountQueryBuilder
19
{
20
    use HasConditions;
21

22
    private ?ModelDefinition $modelDefinition;
23

24
    private CountStatement $count;
25

26
    private array $bindings = [];
27

28
    public function __construct(string|object $model, ?string $column = null)
11✔
29
    {
30
        $this->modelDefinition = ModelDefinition::tryFrom($model);
11✔
31

32
        $this->count = new CountStatement(
11✔
33
            table: $this->resolveTable($model),
11✔
34
            column: $column,
11✔
35
        );
11✔
36
    }
37

NEW
38
    public function execute(mixed ...$bindings): int
×
39
    {
NEW
40
        return $this->build()->fetchFirst(...$bindings)[$this->count->getKey()];
×
41
    }
42

43
    /** @return self<TModelClass> */
44
    public function as(string $alias): self
3✔
45
    {
46
        $this->count->alias = $alias;
3✔
47

48
        return $this;
3✔
49
    }
50

51
    /** @return self<TModelClass> */
52
    public function distinct(): self
4✔
53
    {
54
        if ($this->count->column === null || $this->count->column === '*') {
4✔
55
            throw new CannotCountDistinctWithoutSpecifyingAColumn();
2✔
56
        }
57

58
        $this->count->distinct = true;
2✔
59

60
        return $this;
2✔
61
    }
62

63
    /** @return self<TModelClass> */
64
    public function where(string $where, mixed ...$bindings): self
3✔
65
    {
66
        $this->count->where[] = new WhereStatement($where);
3✔
67

68
        $this->bind(...$bindings);
3✔
69

70
        return $this;
3✔
71
    }
72

73
    public function andWhere(string $where, mixed ...$bindings): self
3✔
74
    {
75
        return $this->where("AND {$where}", ...$bindings);
3✔
76
    }
77

78
    public function orWhere(string $where, mixed ...$bindings): self
3✔
79
    {
80
        return $this->where("OR {$where}", ...$bindings);
3✔
81
    }
82

83
    /** @return self<TModelClass> */
NEW
84
    public function whereField(string $field, mixed $value): self
×
85
    {
NEW
86
        $field = $this->modelDefinition->getFieldDefinition($field);
×
87

NEW
88
        return $this->where("{$field} = :{$field->name}", ...[$field->name => $value]);
×
89
    }
90

91
    /** @return self<TModelClass> */
92
    public function bind(mixed ...$bindings): self
3✔
93
    {
94
        $this->bindings = [...$this->bindings, ...$bindings];
3✔
95

96
        return $this;
3✔
97
    }
98

NEW
99
    public function toSql(): string
×
100
    {
NEW
101
        return $this->build()->getSql();
×
102
    }
103

104
    public function build(array $bindings = []): Query
9✔
105
    {
106
        return new Query($this->count, [...$this->bindings, ...$bindings]);
9✔
107
    }
108

109
    private function resolveTable(string|object $model): TableDefinition
11✔
110
    {
111
        if ($this->modelDefinition === null) {
11✔
112
            return new TableDefinition($model);
10✔
113
        }
114

115
        return $this->modelDefinition->getTableDefinition();
1✔
116
    }
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc