1 | <?php |
||||||
2 | |||||||
3 | namespace Sfneal\Builders; |
||||||
4 | |||||||
5 | use Illuminate\Database\Eloquent\Builder as EloquentBuilder; |
||||||
6 | use Illuminate\Database\Eloquent\Collection; |
||||||
7 | use Illuminate\Database\Eloquent\Model; |
||||||
8 | use Illuminate\Database\Query\Builder; |
||||||
9 | use Sfneal\Builders\Traits\CountAndPaginate; |
||||||
10 | |||||||
11 | class QueryBuilder extends EloquentBuilder |
||||||
12 | { |
||||||
13 | use CountAndPaginate; |
||||||
14 | |||||||
15 | /** |
||||||
16 | * @var string Declare a custom MySQL select string to be used by selectRawJson() |
||||||
17 | */ |
||||||
18 | protected $selectRawJson; |
||||||
19 | |||||||
20 | /** |
||||||
21 | * @var Model |
||||||
22 | */ |
||||||
23 | protected $targetModel; |
||||||
24 | |||||||
25 | /** |
||||||
26 | * @var string Name of the User model's table |
||||||
27 | */ |
||||||
28 | protected $tableName; |
||||||
29 | |||||||
30 | /** |
||||||
31 | * @var string Name of the User model's primary key |
||||||
32 | */ |
||||||
33 | protected $primaryKeyName; |
||||||
34 | |||||||
35 | /** |
||||||
36 | * UserBuilder constructor. |
||||||
37 | * |
||||||
38 | * @param Builder $query |
||||||
39 | */ |
||||||
40 | public function __construct(Builder $query) |
||||||
41 | { |
||||||
42 | $this->setTableAndKeyNames(); |
||||||
43 | parent::__construct($query); |
||||||
44 | } |
||||||
45 | |||||||
46 | /** |
||||||
47 | * Set the $tableName & $primaryKeyName properties. |
||||||
48 | * |
||||||
49 | * @return void |
||||||
50 | */ |
||||||
51 | private function setTableAndKeyNames(): void |
||||||
52 | { |
||||||
53 | // Only declare table & pk if the target model is declared |
||||||
54 | if (isset($this->targetModel)) { |
||||||
55 | $this->tableName = $this->targetModel::getTableName(); |
||||||
0 ignored issues
–
show
|
|||||||
56 | $this->primaryKeyName = $this->targetModel::getPrimaryKeyName(); |
||||||
0 ignored issues
–
show
It seems like
$this->targetModel::getPrimaryKeyName() can also be of type Illuminate\Database\Eloquent\Builder . However, the property $primaryKeyName is declared as type string . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||||||
57 | } |
||||||
58 | } |
||||||
59 | |||||||
60 | /** |
||||||
61 | * Retrieve a concatenation string that combines two columns in a table into a single column. |
||||||
62 | * |
||||||
63 | * @param string $column1 |
||||||
64 | * @param string $column2 |
||||||
65 | * @param string $delimiter |
||||||
66 | * @return string |
||||||
67 | */ |
||||||
68 | protected function concatColumns(string $column1, string $column2, string $delimiter = ' '): string |
||||||
69 | { |
||||||
70 | // Prepend table name if its been declared |
||||||
71 | $column1 = (isset($this->tableName)) ? "{$this->tableName}.{$column1}" : $column1; |
||||||
72 | $column2 = (isset($this->tableName)) ? "{$this->tableName}.{$column2}" : $column2; |
||||||
73 | |||||||
74 | // Return concatenate the two columns using the delimiter |
||||||
75 | return "concat({$column1}, '{$delimiter}', {$column2})"; |
||||||
76 | } |
||||||
77 | |||||||
78 | /** |
||||||
79 | * Retrieve a MySQL if statement that can be used within a query. |
||||||
80 | * |
||||||
81 | * @param string $condition |
||||||
82 | * @param string $expr_true |
||||||
83 | * @param string $expr_false |
||||||
84 | * @return string |
||||||
85 | */ |
||||||
86 | protected function ifStatement(string $condition, string $expr_true, string $expr_false): string |
||||||
87 | { |
||||||
88 | return "if({$condition}, {$expr_true}, {$expr_false})"; |
||||||
89 | } |
||||||
90 | |||||||
91 | /** |
||||||
92 | * Wildcard where like query to determine if any part of the value is found. |
||||||
93 | * |
||||||
94 | * @param string $column |
||||||
95 | * @param $value |
||||||
96 | * @param bool $leadingWildcard |
||||||
97 | * @param bool $trailingWildcard |
||||||
98 | * @return $this |
||||||
99 | */ |
||||||
100 | public function whereLike(string $column, $value, bool $leadingWildcard = true, bool $trailingWildcard = true): self |
||||||
101 | { |
||||||
102 | $this->where( |
||||||
103 | $column, |
||||||
104 | 'LIKE', |
||||||
105 | ($leadingWildcard ? '%' : '').$value.($trailingWildcard ? '%' : '') |
||||||
106 | ); |
||||||
107 | |||||||
108 | return $this; |
||||||
109 | } |
||||||
110 | |||||||
111 | /** |
||||||
112 | * Wildcard or where like query to determine if any part of the value is found. |
||||||
113 | * |
||||||
114 | * @param string $column |
||||||
115 | * @param $value |
||||||
116 | * @param bool $leadingWildcard |
||||||
117 | * @param bool $trailingWildcard |
||||||
118 | * @return $this |
||||||
119 | */ |
||||||
120 | public function orWhereLike(string $column, $value, bool $leadingWildcard = true, bool $trailingWildcard = true): self |
||||||
121 | { |
||||||
122 | $this->orWhere( |
||||||
123 | $column, |
||||||
124 | 'LIKE', |
||||||
125 | ($leadingWildcard ? '%' : '').$value.($trailingWildcard ? '%' : '') |
||||||
126 | ); |
||||||
127 | |||||||
128 | return $this; |
||||||
129 | } |
||||||
130 | |||||||
131 | /** |
||||||
132 | * Retrieve a flat, single-dimensional array of results without keys. |
||||||
133 | * |
||||||
134 | * @param string $column |
||||||
135 | * @return array |
||||||
136 | */ |
||||||
137 | public function getFlatArray(string $column): array |
||||||
138 | { |
||||||
139 | return array_map(function ($collection) use ($column) { |
||||||
140 | return $collection[$column]; |
||||||
141 | }, $this->distinct()->get($column)->toArray()); |
||||||
0 ignored issues
–
show
The method
distinct() does not exist on Sfneal\Builders\QueryBuilder . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
142 | } |
||||||
143 | |||||||
144 | /** |
||||||
145 | * Retrieve raw query results formatted for Ajax select2 form inputs. |
||||||
146 | * |
||||||
147 | * @param string|null $raw |
||||||
148 | * @return $this |
||||||
149 | */ |
||||||
150 | public function selectRawJson(string $raw = null): self |
||||||
151 | { |
||||||
152 | $this->withoutGlobalScopes(); |
||||||
153 | $this->selectRaw($raw ?? $this->selectRawJson); |
||||||
0 ignored issues
–
show
The method
selectRaw() does not exist on Sfneal\Builders\QueryBuilder . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
154 | |||||||
155 | return $this; |
||||||
156 | } |
||||||
157 | |||||||
158 | /** |
||||||
159 | * Order query results by the 'created_at' column. |
||||||
160 | * |
||||||
161 | * @param string $direction |
||||||
162 | * @return $this |
||||||
163 | */ |
||||||
164 | public function orderByCreatedAt(string $direction = 'desc'): self |
||||||
165 | { |
||||||
166 | $this->orderBy('created_at', $direction); |
||||||
0 ignored issues
–
show
The method
orderBy() does not exist on Sfneal\Builders\QueryBuilder . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
167 | |||||||
168 | return $this; |
||||||
169 | } |
||||||
170 | |||||||
171 | /** |
||||||
172 | * Retrieve the 'next' Model in the database. |
||||||
173 | * |
||||||
174 | * @param int|null $model_id |
||||||
175 | * @return QueryBuilder|Collection|Model|null |
||||||
176 | */ |
||||||
177 | public function getNextModel(int $model_id = null) |
||||||
178 | { |
||||||
179 | return $this->find($this->getNextModelId($model_id)); |
||||||
180 | } |
||||||
181 | |||||||
182 | /** |
||||||
183 | * Retrieve the 'previous' Model in the database. |
||||||
184 | * |
||||||
185 | * @param int|null $model_id |
||||||
186 | * @return QueryBuilder|Collection|Model|null |
||||||
187 | */ |
||||||
188 | public function getPreviousModel(int $model_id = null) |
||||||
189 | { |
||||||
190 | return $this->find($this->getPreviousModelId($model_id)); |
||||||
191 | } |
||||||
192 | |||||||
193 | /** |
||||||
194 | * Retrieve the 'next' Model's ID. |
||||||
195 | * |
||||||
196 | * @param int|null $model_id |
||||||
197 | * @return mixed |
||||||
198 | */ |
||||||
199 | public function getNextModelId(int $model_id = null) |
||||||
200 | { |
||||||
201 | return $this |
||||||
202 | ->where($this->model->getKeyName(), '>', $model_id ?? $this->model->getKey()) |
||||||
203 | ->min($this->model->getKeyName()); |
||||||
0 ignored issues
–
show
The method
min() does not exist on Sfneal\Builders\QueryBuilder . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
204 | } |
||||||
205 | |||||||
206 | /** |
||||||
207 | * Retrieve the 'previous' Model's ID. |
||||||
208 | * |
||||||
209 | * @param int|null $model_id |
||||||
210 | * @return mixed |
||||||
211 | */ |
||||||
212 | public function getPreviousModelId(int $model_id = null) |
||||||
213 | { |
||||||
214 | return $this |
||||||
215 | ->where($this->model->getKeyName(), '<', $model_id ?? $this->model->getKey()) |
||||||
216 | ->max($this->model->getKeyName()); |
||||||
0 ignored issues
–
show
The method
max() does not exist on Sfneal\Builders\QueryBuilder . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
217 | } |
||||||
218 | } |
||||||
219 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.