parent
0606c3bea8
commit
e71e8330f9
@ -0,0 +1,85 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @author Robert Strutts |
||||
* @copyright (c) 2026, Robert Strutts |
||||
* @license MIT |
||||
*/ |
||||
|
||||
namespace IOcornerstone\Framework\Database\Grammar; |
||||
|
||||
/** |
||||
* Description of Grammar |
||||
* |
||||
* @author Robert Strutts |
||||
*/ |
||||
abstract class Grammar |
||||
{ |
||||
/** |
||||
* Compile an entire SELECT statement. |
||||
*/ |
||||
public function compileSelect($query): string |
||||
{ |
||||
$sql = 'SELECT '; |
||||
$sql .= $query->select; |
||||
|
||||
$sql .= ' FROM '; |
||||
$sql .= $this->wrap($query->table); |
||||
|
||||
$sql .= $this->compileJoins($query); |
||||
|
||||
$sql .= $this->compileWhere($query); |
||||
|
||||
$sql .= $this->compileGroupBy($query); |
||||
|
||||
$sql .= $this->compileHaving($query); |
||||
|
||||
$sql .= $this->compileOrderBy($query); |
||||
|
||||
$sql .= $this->compileLimit($query); |
||||
|
||||
$sql .= $this->compileOffset($query); |
||||
|
||||
return $sql; |
||||
} |
||||
|
||||
|
||||
public function compileLimit(?int $limit): string |
||||
{ |
||||
return $limit !== null ? " LIMIT {$limit}" : ''; |
||||
} |
||||
|
||||
public function compileOffset(?int $offset): string |
||||
{ |
||||
return $offset !== null ? " OFFSET {$offset}" : ''; |
||||
} |
||||
|
||||
protected function compileOrderBy($query): string |
||||
{ |
||||
if (!$query->orders) |
||||
return ''; |
||||
|
||||
$parts = []; |
||||
|
||||
foreach ($query->orders as $order) { |
||||
|
||||
$parts[] = |
||||
$this->wrap($order['column']) |
||||
.' ' |
||||
.$order['direction']; |
||||
|
||||
} |
||||
|
||||
return ' ORDER BY '.implode(',', $parts); |
||||
} |
||||
|
||||
abstract public function wrap(string $identifier): string; |
||||
abstract public function compileDate(string $column): string; |
||||
abstract public function compileTime(string $column): string; |
||||
abstract public function compileYear(string $column): string; |
||||
abstract public function compileMonth(string $column): string; |
||||
abstract public function compileDay(string $column): string; |
||||
abstract public function compileJsonContains(string $column): string; |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @author Robert Strutts |
||||
* @copyright (c) 2026, Robert Strutts |
||||
* @license MIT |
||||
*/ |
||||
|
||||
namespace IOcornerstone\Framework\Database\Grammar; |
||||
|
||||
/** |
||||
* Description of MySQLGrammar |
||||
* |
||||
* @author Robert Strutts |
||||
*/ |
||||
class MySQLGrammar extends Grammar |
||||
{ |
||||
public function wrap(string $column): string |
||||
{ |
||||
return "`{$column}`"; |
||||
} |
||||
|
||||
public function compileYear(string $column): string |
||||
{ |
||||
return "YEAR({$this->wrap($column)})"; |
||||
} |
||||
|
||||
public function compileMonth(string $column): string |
||||
{ |
||||
return "MONTH({$this->wrap($column)})"; |
||||
} |
||||
|
||||
public function compileDay(string $column): string |
||||
{ |
||||
return "DAY({$this->wrap($column)})"; |
||||
} |
||||
|
||||
public function compileDate(string $column): string |
||||
{ |
||||
return "DATE({$this->wrap($column)})"; |
||||
} |
||||
|
||||
public function compileTime(string $column): string |
||||
{ |
||||
return "TIME({$this->wrap($column)})"; |
||||
} |
||||
|
||||
public function compileJsonContains(string $column): string |
||||
{ |
||||
return "JSON_CONTAINS({$this->wrap($column)}, ?)"; |
||||
} |
||||
} |
||||
@ -0,0 +1,58 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* @author Robert Strutts |
||||
* @copyright (c) 2026, Robert Strutts |
||||
* @license MIT |
||||
*/ |
||||
|
||||
namespace IOcornerstone\Framework\Database\Grammar; |
||||
|
||||
/** |
||||
* Description of SQLiteGrammar |
||||
* |
||||
* @author Robert Strutts |
||||
*/ |
||||
class SQLiteGrammar extends Grammar |
||||
{ |
||||
public function wrap(string $column): string |
||||
{ |
||||
return "\"{$column}\""; |
||||
} |
||||
|
||||
public function compileYear(string $column): string |
||||
{ |
||||
return "strftime('%Y',".$this->wrap($column).")"; |
||||
} |
||||
|
||||
public function compileMonth(string $column): string |
||||
{ |
||||
return "strftime('%m',".$this->wrap($column).")"; |
||||
} |
||||
|
||||
public function compileDay(string $column): string |
||||
{ |
||||
return "strftime('%d',".$this->wrap($column).")"; |
||||
} |
||||
|
||||
public function compileDate(string $column): string |
||||
{ |
||||
return "date(".$this->wrap($column).")"; |
||||
} |
||||
|
||||
public function compileTime(string $column): string |
||||
{ |
||||
return "time(".$this->wrap($column).")"; |
||||
} |
||||
|
||||
public function compileJsonContains(string $column): string |
||||
{ |
||||
return "EXISTS ( |
||||
SELECT 1 |
||||
FROM json_each(".$this->wrap($column).") |
||||
WHERE value=? |
||||
)"; |
||||
} |
||||
} |
||||
@ -0,0 +1,745 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/* |
||||
* @author Robert Strutts |
||||
* @copyright (c) 2026, Robert Strutts |
||||
* @license MIT |
||||
*/ |
||||
|
||||
namespace IOcornerstone\Framework\Trait\Database; |
||||
|
||||
use IOcornerstone\Framework\Database\Grammar\{ |
||||
MySQLGrammar, |
||||
SQLiteGrammar, |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
* @author Robert Strutts |
||||
*/ |
||||
trait QueryBuilder |
||||
{ |
||||
|
||||
protected $grammar; |
||||
protected array $wheres = []; |
||||
protected array $bindings = []; |
||||
protected array $joins = []; |
||||
protected array $groups = []; |
||||
protected array $havings = []; |
||||
protected array $orders = []; |
||||
protected ?string $orderBy = null; |
||||
protected ?int $limit = null; |
||||
protected ?int $offset = null; |
||||
protected string $select = '*'; |
||||
|
||||
public function select(array $columns): static |
||||
{ |
||||
$this->select = implode(',', $columns); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function where( |
||||
string $column, |
||||
string $operator, |
||||
mixed $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Basic', |
||||
'column' => $column, |
||||
'operator' => $operator, |
||||
'value' => $value |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhere( |
||||
string $column, |
||||
string $operator, |
||||
mixed $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'Basic', |
||||
'column' => $column, |
||||
'operator' => $operator, |
||||
'value' => $value |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereNull(string $column): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Null', |
||||
'column' => $column |
||||
]; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereNull(string $column): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'Null', |
||||
'column' => $column |
||||
]; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereNotNull(string $column): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'NotNull', |
||||
'column' => $column |
||||
]; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereNotNull(string $column): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'NotNull', |
||||
'column' => $column |
||||
]; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereIn( |
||||
string $column, |
||||
array $values |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'In', |
||||
'column' => $column, |
||||
'count' => count($values) |
||||
]; |
||||
|
||||
foreach ($values as $value) |
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereIn( |
||||
string $column, |
||||
array $values |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'In', |
||||
'column' => $column, |
||||
'count' => count($values) |
||||
]; |
||||
|
||||
foreach ($values as $value) |
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereNotIn( |
||||
string $column, |
||||
array $values |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'NotIn', |
||||
'column' => $column, |
||||
'count' => count($values) |
||||
]; |
||||
|
||||
foreach ($values as $value) |
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereBetween( |
||||
string $column, |
||||
mixed $from, |
||||
mixed $to |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Between', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $from; |
||||
$this->bindings[] = $to; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereNotBetween( |
||||
string $column, |
||||
mixed $from, |
||||
mixed $to |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'NotBetween', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $from; |
||||
$this->bindings[] = $to; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereLike( |
||||
string $column, |
||||
string $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Like', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereNotLike( |
||||
string $column, |
||||
string $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'NotLike', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereColumn( |
||||
string $left, |
||||
string $operator, |
||||
string $right |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Column', |
||||
'left' => $left, |
||||
'operator' => $operator, |
||||
'right' => $right |
||||
]; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereRaw( |
||||
string $sql, |
||||
array $bindings = [] |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Raw', |
||||
'sql' => $sql |
||||
]; |
||||
|
||||
foreach ($bindings as $binding) { |
||||
$this->bindings[] = $binding; |
||||
} |
||||
return $this; |
||||
} |
||||
|
||||
public function whereDate( |
||||
string $column, |
||||
string $operator, |
||||
string $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Date', |
||||
'column' => $column, |
||||
'operator' => $operator, |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereTime( |
||||
string $column, |
||||
string $operator, |
||||
string $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Time', |
||||
'column' => $column, |
||||
'operator' => $operator |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereYear( |
||||
string $column, |
||||
string $operator, |
||||
int $year |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Year', |
||||
'column' => $column, |
||||
'operator' => $operator |
||||
]; |
||||
|
||||
$this->bindings[] = $year; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereMonth( |
||||
string $column, |
||||
string $operator, |
||||
int $month |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Month', |
||||
'column' => $column, |
||||
'operator' => $operator |
||||
]; |
||||
|
||||
$this->bindings[] = $month; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereDay( |
||||
string $column, |
||||
string $operator, |
||||
int $day |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'Day', |
||||
'column' => $column, |
||||
'operator' => $operator |
||||
]; |
||||
|
||||
$this->bindings[] = $day; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereBetween( |
||||
string $column, |
||||
mixed $from, |
||||
mixed $to |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'Between', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $from; |
||||
$this->bindings[] = $to; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereNotBetween( |
||||
string $column, |
||||
mixed $from, |
||||
mixed $to |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'NotBetween', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $from; |
||||
$this->bindings[] = $to; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereLike( |
||||
string $column, |
||||
string $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'Like', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orWhereNotLike( |
||||
string $column, |
||||
string $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'OR', |
||||
'type' => 'NotLike', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function whereJsonContains( |
||||
string $column, |
||||
mixed $value |
||||
): static |
||||
{ |
||||
$this->wheres[] = [ |
||||
'boolean' => 'AND', |
||||
'type' => 'JsonContains', |
||||
'column' => $column |
||||
]; |
||||
|
||||
$this->bindings[] = json_encode($value); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function orderBy( |
||||
string $column, |
||||
string $direction = 'ASC' |
||||
): static |
||||
{ |
||||
$direction = strtoupper($direction); |
||||
|
||||
$this->orderBy = "{$column} {$direction}"; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function limit(int $limit): static |
||||
{ |
||||
$this->limit = $limit; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function leftJoin( |
||||
string $table, |
||||
string $left, |
||||
string $operator, |
||||
string $right |
||||
): static |
||||
{ |
||||
$this->joins[] = "LEFT JOIN {$table} |
||||
ON {$left} {$operator} {$right}"; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function join( |
||||
string $table, |
||||
string $left, |
||||
string $operator, |
||||
string $right |
||||
): static |
||||
{ |
||||
$this->joins[] = "INNER JOIN {$table} ON {$left} {$operator} {$right}"; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
private function buildWhere(string $sql): string |
||||
{ |
||||
foreach ($this->wheres as $index => $where) { |
||||
|
||||
if ($index > 0) { |
||||
$sql .= ' ' . $where['boolean'] . ' '; |
||||
} |
||||
|
||||
switch ($where['type']) { |
||||
case 'Null': |
||||
$sql .= "{$where['column']} IS NULL"; |
||||
break; |
||||
|
||||
case 'NotNull': |
||||
$sql .= "{$where['column']} IS NOT NULL"; |
||||
break; |
||||
|
||||
case 'Like': |
||||
$sql .= "{$where['column']} LIKE ?"; |
||||
break; |
||||
|
||||
case 'NotLike': |
||||
$sql .= "{$where['column']} NOT LIKE ?"; |
||||
break; |
||||
|
||||
case 'Between': |
||||
$sql .= "{$where['column']} BETWEEN ? AND ?"; |
||||
break; |
||||
|
||||
case 'NotBetween': |
||||
$sql .= "{$where['column']} NOT BETWEEN ? AND ?"; |
||||
break; |
||||
|
||||
case 'In': |
||||
$sql .= "{$where['column']} IN (" . |
||||
implode(',', array_fill(0, $where['count'], '?')) . ")"; |
||||
break; |
||||
|
||||
case 'NotIn': |
||||
$sql .= "{$where['column']} NOT IN (" . |
||||
implode(',', array_fill(0, $where['count'], '?')) . ")"; |
||||
break; |
||||
|
||||
case 'Column': |
||||
$sql .= "{$where['left']} {$where['operator']} {$where['right']}"; |
||||
break; |
||||
|
||||
case 'Raw': |
||||
$sql .= $where['sql']; |
||||
break; |
||||
|
||||
case 'Basic': |
||||
|
||||
$sql .= $this->grammar->wrap($where['column']); |
||||
|
||||
$sql .= " {$where['operator']} ?"; |
||||
|
||||
break; |
||||
|
||||
case 'Year': |
||||
|
||||
$sql .= $this->grammar->compileYear( |
||||
$where['column'] |
||||
); |
||||
|
||||
$sql .= " {$where['operator']} ?"; |
||||
|
||||
break; |
||||
|
||||
case 'Month': |
||||
|
||||
$sql .= $this->grammar->compileMonth( |
||||
$where['column'] |
||||
); |
||||
|
||||
$sql .= " {$where['operator']} ?"; |
||||
|
||||
break; |
||||
|
||||
case 'Day': |
||||
|
||||
$sql .= $this->grammar->compileDay( |
||||
$where['column'] |
||||
); |
||||
|
||||
$sql .= " {$where['operator']} ?"; |
||||
|
||||
break; |
||||
|
||||
case 'Date': |
||||
|
||||
$sql .= $this->grammar->compileDate( |
||||
$where['column'] |
||||
); |
||||
|
||||
$sql .= " {$where['operator']} ?"; |
||||
|
||||
break; |
||||
|
||||
case 'Time': |
||||
|
||||
$sql .= $this->grammar->compileTime( |
||||
$where['column'] |
||||
); |
||||
|
||||
$sql .= " {$where['operator']} ?"; |
||||
|
||||
break; |
||||
|
||||
case 'JsonContains': |
||||
|
||||
$sql .= $this->grammar->compileJsonContains( |
||||
$where['column'] |
||||
); |
||||
|
||||
break; |
||||
} |
||||
} |
||||
return $sql; |
||||
} |
||||
|
||||
protected function buildSql(): string |
||||
{ |
||||
if ($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'mysql') { |
||||
$this->grammar = new MySQLGrammar(); |
||||
} else { |
||||
$this->grammar = new SQLiteGrammar(); |
||||
} |
||||
|
||||
$sql = "SELECT {$this->select} FROM {$this->table}"; |
||||
|
||||
if ($this->joins) { |
||||
$sql .= ' ' . implode(' ', $this->joins); |
||||
} |
||||
|
||||
if ($this->wheres) { |
||||
$sql = $this->buildWhere($sql . " WHERE "); |
||||
} |
||||
|
||||
if ($this->orderBy) { |
||||
$sql .= ' ORDER BY ' . $this->orderBy; |
||||
} |
||||
|
||||
if ($this->limit) { |
||||
$sql .= ' LIMIT ' . $this->limit; |
||||
} |
||||
|
||||
return $sql; |
||||
} |
||||
|
||||
public function groupBy(string ...$columns): static |
||||
{ |
||||
foreach ($columns as $column) { |
||||
$this->groups[] = $column; |
||||
} |
||||
return $this; |
||||
} |
||||
|
||||
public function having( |
||||
string $column, |
||||
string $operator, |
||||
mixed $value |
||||
): static |
||||
{ |
||||
$this->havings[] = "{$column} {$operator} ?"; |
||||
|
||||
$this->bindings[] = $value; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function offset(int $offset): static |
||||
{ |
||||
$this->offset = $offset; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
private function getRow(): array |
||||
{ |
||||
$stmt = $this->pdo->prepare( |
||||
$this->buildSql() |
||||
); |
||||
|
||||
$stmt->execute($this->bindings); |
||||
|
||||
return $stmt->fetch(\PDO::FETCH_ASSOC); |
||||
} |
||||
|
||||
public function get() |
||||
{ |
||||
$stmt = $this->pdo->prepare( |
||||
$this->buildSql() |
||||
); |
||||
|
||||
$stmt->execute($this->bindings); |
||||
return $stmt; |
||||
} |
||||
|
||||
public function first(): ?array |
||||
{ |
||||
$this->limit(1); |
||||
|
||||
$rows = $this->getRow(); |
||||
|
||||
return $rows ?? null; |
||||
} |
||||
|
||||
public function count(): int |
||||
{ |
||||
$this->select = 'COUNT(' . $this->primaryKey . ')'; |
||||
|
||||
$stmt = $this->pdo->prepare( |
||||
$this->buildSql() |
||||
); |
||||
|
||||
$stmt->execute($this->bindings); |
||||
|
||||
return (int) $stmt->fetchColumn(); |
||||
} |
||||
|
||||
public function sum(string $column): int |
||||
{ |
||||
$this->select = "SUM({$column})"; |
||||
|
||||
$stmt = $this->pdo->prepare( |
||||
$this->buildSql() |
||||
); |
||||
|
||||
$stmt->execute($this->bindings); |
||||
|
||||
return (int) $stmt->fetchColumn(); |
||||
} |
||||
|
||||
public function exists(): bool |
||||
{ |
||||
$this->limit(1); |
||||
|
||||
return $this->count() > 0; |
||||
} |
||||
|
||||
public function toSql(): string |
||||
{ |
||||
return $this->buildSql(); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue