diff --git a/maestro.php b/maestro.php index fdef15e..4bc5c87 100644 --- a/maestro.php +++ b/maestro.php @@ -14,17 +14,23 @@ use Maestro\Example\User; -$coreDatabase = new Manager(); -$agrofastDB = new MaestroDb(); -// new User("nickname", "email", "password", true, new Timestamp()); +// $coreDatabase = new Manager(); +// $agrofastDB = new MaestroDb(); +// // new User("nickname", "email", "password", true, new Timestamp()); -// print implode("\n", $coreDatabase->createDatabase($agrofastDB, true)) . "\n"; +// // print implode("\n", $coreDatabase->createDatabase($agrofastDB, true)) . "\n"; -$insert = new Insert(Maestro::SQL_NO_PREDICT, PDOConnection::get()); -$user = new User("nickname'-- drop table", 'John', 'Doe', 'email@example.com', 'password', true, new Timestamp()); -$result = $insert->into($user)->values($user)->returning(['id'])->execute(); -var_dump($result); +// $insert = new Insert(Maestro::SQL_NO_PREDICT, PDOConnection::get()); +// $user = new User("nickname'-- drop table", 'John', 'Doe', 'email@example.com', 'password', true, new Timestamp()); +// $result = $insert->into($user)->values($user)->returning(['id'])->execute(); +// var_dump($result); + +// $delete = new Delete(Maestro::SQL_NO_PREDICT, PDOConnection::get()); +// $delete->from($user)->where(['id' => $result[0]['id']])->execute(); + + +$where = ["teste" => null]; + +var_dump( implode(" teste ", $where), empty($where)); -$delete = new Delete(Maestro::SQL_NO_PREDICT, PDOConnection::get()); -$delete->from($user)->where(['id' => $result[0]['id']])->execute(); diff --git a/src/Abstract/Query.php b/src/Abstract/Query.php index a2a664f..78891e7 100644 --- a/src/Abstract/Query.php +++ b/src/Abstract/Query.php @@ -7,6 +7,7 @@ use Ilias\Maestro\Database\Select; use Ilias\Maestro\Utils\Utils; use InvalidArgumentException, PDO, Exception, PDOStatement; +use function PHPUnit\Framework\isEmpty; abstract class Query { @@ -15,7 +16,7 @@ abstract class Query protected array $where = []; private ?PDOStatement $stmt = null; private bool $isBinded = false; - protected string $query = ''; + protected string $query = ''; public const AND = 'AND'; public const OR = 'OR'; public const EQUALS = '='; @@ -41,8 +42,12 @@ public function __construct( * @param array $conditions An associative array of conditions for the WHERE clause. * @return $this Returns the current instance for method chaining. */ - public function where(string|array $conditions, string $operation = Select::AND, string $compaction = Select::EQUALS, bool $group = false): static + public function where(string|array $conditions, string $operation = Select::AND , string $compaction = Select::EQUALS, bool $group = false): static { + if (empty($conditions)) { + return $this; + } + if (is_array($conditions)) { $where = []; foreach ($conditions as $column => $value) { @@ -52,16 +57,22 @@ public function where(string|array $conditions, string $operation = Select::AND, $where[] = "{$column} {$compaction} {$paramName}"; } $clauses = implode(" {$operation} ", $where); - $this->where[] = ($group ? "({$clauses})" : $clauses); + $conditions = ($group ? "({$clauses})" : $clauses); } - if (is_string($conditions)) { + + if (!empty($conditions)) { $this->where[] = $conditions; } + return $this; } - public function in(string|array $conditions, string $operation = Select::AND, bool $group = false): static + public function in(string|array $conditions, string $operation = Select::AND , bool $group = false): static { + if (empty($conditions)) { + return $this; + } + if (is_array($conditions)) { $where = []; foreach ($conditions as $column => $value) { @@ -75,11 +86,11 @@ public function in(string|array $conditions, string $operation = Select::AND, bo $where[] = "{$column} IN({$inList})"; } $clauses = implode(" {$operation} ", $where); - $this->where[] = ($group ? "({$clauses})" : $clauses); - } - if (is_string($conditions)) { + $this->where[] = ($group ? "({$clauses})" : $clauses); + } elseif (is_string($conditions)) { $this->where[] = $conditions; } + return $this; } diff --git a/src/Abstract/Table.php b/src/Abstract/Table.php index 5c1687a..3924c61 100644 --- a/src/Abstract/Table.php +++ b/src/Abstract/Table.php @@ -149,8 +149,7 @@ public static function generateAlias(array $existingAlias = []): string /** * Fetches all rows from the table based on the given prediction, order, and limit. - * - * @param string|array|null $prediction The prediction criteria for the query. Can be a string or an array. + @param string|array|null $prediction The prediction criteria for the query. Can be a string or an array. * @param string|array|null $orderBy The order by criteria for the query. Can be a string or an array. * @param int|string $limit The limit for the number of rows to fetch. Default is 100. * @return array The fetched rows as an array. @@ -183,8 +182,7 @@ public static function fetchAll(string|array $prediction = null, string|array $o /** * Fetches a single row from the table based on the given prediction and order. - * - * @param string|array|null $prediction The prediction criteria for the query. Can be a string or an array. + @param string|array|null $prediction The prediction criteria for the query. Can be a string or an array. * @param string|array|null $orderBy The order by criteria for the query. Can be a string or an array. * @return mixed The fetched row or null if no row is found. */ diff --git a/src/Database/Delete.php b/src/Database/Delete.php index b187b6e..84862a6 100644 --- a/src/Database/Delete.php +++ b/src/Database/Delete.php @@ -8,6 +8,7 @@ class Delete extends Query { private string $table; + /** Sets the table from which records will be deleted. @param string $table The name of the table. @return Delete Returns the current instance for method chaining./ public function from(string $table): Delete { $this->table = $this->validateTableName($table); diff --git a/src/Database/Insert.php b/src/Database/Insert.php index 861d319..f233a32 100644 --- a/src/Database/Insert.php +++ b/src/Database/Insert.php @@ -28,6 +28,12 @@ private function registerValue($column, $value) $this->values[] = $paramName; } + /** + * Sets the values to be inserted into the database table. + * This method accepts either an instance of the Table class or an associative array where the keys are column names and the values are the corresponding values to be inserted. It registers each value for the corresponding column. + * @param Table|array $data An instance of the Table class or an associative array of column-value pairs. + * @return Insert Returns the current instance of the Insert class for method chaining. + */ public function values(Table|array $data): Insert { foreach ((array) $data as $column => $value) { @@ -38,26 +44,29 @@ public function values(Table|array $data): Insert /** * @deprecated This method does not make anything when used. Since you're building a insert query - * * @param array $conditions An associative array of conditions for the WHERE clause. * @return Insert Returns the current Insert instance. */ - public function where(array $conditions, string $operation = \Ilias\Maestro\Database\Select::AND, bool $group = false): static + public function where(string|array $conditions, string $operation = Select::AND , string $compaction = Select::EQUALS, bool $group = false): static { return $this; } /** * @deprecated This method does not make anything when used. Since you're building a insert query - * * @param array $conditions An associative array of conditions for the WHERE clause. * @return Insert Returns the current Insert instance. */ - public function in(array $conditions, string $operation = \Ilias\Maestro\Database\Select::AND, bool $group = false): static + public function in(string|array $conditions, string $operation = \Ilias\Maestro\Database\Select::AND, bool $group = false): static { return $this; } + /** + * Adds the specified columns to the list of columns to be returned after the insert operation. + * @param array $columns An array of column names to be added to the returning list. + * @return Insert Returns the current instance of the Insert class. + */ public function returning(array $columns): Insert { foreach ($columns as $column) { diff --git a/src/Database/PDOConnection.php b/src/Database/PDOConnection.php index e1e0f6e..976a8f8 100644 --- a/src/Database/PDOConnection.php +++ b/src/Database/PDOConnection.php @@ -22,9 +22,7 @@ public function __wakeup() /** * Retrieves a PDO connection instance. - * * This method returns a singleton instance of the PDO connection. If the connection has not been established yet, it will create a new one using the provided parameters or environment variables. If a PDO mock object is provided, it will be used instead. - * * @param string|null $dbSql The SQL driver (e.g., mysql, pgsql). Defaults to environment variable DB_SQL. * @param string|null $dbName The name of the database. Defaults to environment variable DB_NAME. * @param string|null $dbHost The database host. Defaults to environment variable DB_HOST. @@ -58,7 +56,6 @@ public static function get(string $dbSql = null, string $dbName = null, string $ /** * Get an instance of the PDO connection. - * * @param \PDO|null $pdoMock Optional PDO mock object for testing. * @return \PDO The PDO connection instance. * @deprecated This method is deprecated and will be removed in a future version. Use self::get() directly instead. diff --git a/src/Database/Select.php b/src/Database/Select.php index 17be8fc..a2ddf58 100644 --- a/src/Database/Select.php +++ b/src/Database/Select.php @@ -26,25 +26,14 @@ class Select extends Query private string $limit = ''; private bool $distinct = false; - /** - * Sets the DISTINCT flag for the SELECT statement. - * - * @param bool $distinct Whether to select distinct rows. - * @return Select Returns the current Select instance. - */ + /** Sets the DISTINCT flag for the SELECT statement. @param bool $distinct Whether to select distinct rows. @return Select Returns the current Select instance./ public function distinct(bool $distinct = true): Select { $this->distinct = $distinct; return $this; } - /** - * Sets the table and columns for the SELECT statement. - * - * @param array $table An array containing the table name and alias. It should be provided like `[$alias => $table]`, the `$table` being the schema name and the table name separated by a dot, basically like `"{$schema}.{$table}"`. The `$table` can also be provided as class name from a Table inherited class: `$table = User::class`. - * @param array $columns An array of columns to select, with optional renaming. - * @return Select Returns the current Select instance. - */ + /** Sets the table and columns for the SELECT statement. @param array $table An array containing the table name and alias. It should be provided like `[$alias => $table]`, the `$table` being the schema name and the table name separated by a dot, basically like `"{$schema}.{$table}"`. The `$table` can also be provided as class name from a Table inherited class: `$table = User::class`. @param array $columns An array of columns to select, with optional renaming. @return Select Returns the current Select instance./ public function from(array $table, array $columns = [Select::STAR]): Select { [$name, $alias] = $this->validateSelectTable($table); @@ -65,15 +54,7 @@ public function from(array $table, array $columns = [Select::STAR]): Select return $this; } - /** - * Adds a join clause to the select query. - * - * @param array $table An array containing the table name and alias. It should be provided like `[$alias => $table]`, the `$table` being the schema name and the table name separated by a dot, basically like `"{$schema}.{$table}"`. The `$table` can also be provided as class name from a Table inherited class: `$table = User::class`. - * @param string $condition The join condition. - * @param array $columns Optional. The columns to select from the joined table, specified as an array. Default is an empty array. - * @param string $type Optional. The type of join to perform (e.g., 'INNER', 'LEFT'). Default is 'INNER'. - * @return Select Returns the current Select instance for method chaining. - */ + /** Adds a join clause to the select query. @param array $table An array containing the table name and alias. It should be provided like `[$alias => $table]`, the `$table` being the schema name and the table name separated by a dot, basically like `"{$schema}.{$table}"`. The `$table` can also be provided as class name from a Table inherited class: `$table = User::class`. @param string $condition The join condition. @param array $columns Optional. The columns to select from the joined table, specified as an array. Default is an empty array. @param string $type Optional. The type of join to perform (e.g., 'INNER', 'LEFT'). Default is 'INNER'. @return Select Returns the current Select instance for method chaining./ public function join(array $table, string $condition, array $columns = [], string $type = Select::INNER): Select { [$name, $alias] = $this->validateSelectTable($table); @@ -86,39 +67,52 @@ public function join(array $table, string $condition, array $columns = [], strin return $this; } - + + /** Sets the columns to group the results by. @param array $columns An array of column names to group by. @return Select Returns the current Select instance for method chaining./ public function group(array $columns): Select { $this->group = implode(", ", $columns); return $this; } - public function having(array $conditions, string $operation = Select::AND, $group = false): Select + /** Adds a HAVING clause to the SQL query. @param string|array $conditions The conditions for the HAVING clause. Can be a string or an associative array where the key is the column name and the value is the condition value. @param string $operation The logical operation to combine multiple conditions (e.g., AND, OR). Defaults to Select::AND. @param bool $group Whether to group the conditions in parentheses. Defaults to false. @return Select Returns the current Select instance for method chaining./ + public function having(string|array $conditions, string $operation = Select::AND , $group = false): Select { - $having = []; - foreach ($conditions as $column => $value) { - $columnHaving = Utils::sanitizeForPostgres($column); - $paramName = ":having_{$columnHaving}"; - $this->storeParameter($paramName, $value); - $having[] = "{$column} = {$paramName}"; + if (empty($conditions)) { + return $this; + } + if (is_array($conditions)) { + $having = []; + foreach ($conditions as $column => $value) { + $columnHaving = Utils::sanitizeForPostgres($column); + $paramName = ":having_{$columnHaving}"; + $this->storeParameter($paramName, $value); + $having[] = "{$column} = {$paramName}"; + } + $clauses = implode(" {$operation} ", $having); + $this->having[] = ($group ? "({$clauses})" : $clauses); + } + if (!empty($conditions)) { + $this->having[] = $conditions; } - $clauses = implode(" {$operation} ", $having); - $this->having[] = ($group ? "({$clauses})" : $clauses); return $this; } + /** Adds an ORDER BY clause to the SQL query. @param string $column The column name to order by. @param string $direction The direction of the order, either 'ASC' or 'DESC'. Defaults to 'ASC'. @return Select Returns the current Select instance for method chaining./ public function order(string $column, string $direction = Select::ASC): Select { $this->order[] = "{$column} {$direction}"; return $this; } + /** Sets the offset for the SQL query. @param int|string $offset The offset value to set. @return Select Returns the current Select instance./ public function offset(int|string $offset): Select { $this->offset = "{$offset}"; return $this; } + /** Sets the limit for the number of rows to retrieve. @param int|string $limit The maximum number of rows to retrieve. If a string is provided, it must be numeric. @return Select Returns the current Select instance. @throws \InvalidArgumentException If the provided limit is a non-numeric string./ public function limit(int|string $limit): Select { if (is_string($limit) && !is_numeric($limit)) { diff --git a/src/Database/Transaction.php b/src/Database/Transaction.php index c9a32f9..6daceab 100644 --- a/src/Database/Transaction.php +++ b/src/Database/Transaction.php @@ -4,6 +4,9 @@ use PDO; +/** + * This class provides methods to manage database transactions. + */ class Transaction { private PDO $pdo; @@ -17,6 +20,11 @@ public function __construct(?PDO $pdo = null) $this->pdo = $pdo; } + /** + * Begins a new database transaction. + * @throws \Exception if a transaction is already started. + * @return void + */ public function begin() { if ($this->inTransaction) { @@ -27,6 +35,11 @@ public function begin() $this->inTransaction = true; } + /** + * Commits the current database transaction. + * @throws \Exception if no transaction is started. + * @return void + */ public function commit() { if (!$this->inTransaction) { @@ -37,6 +50,11 @@ public function commit() $this->inTransaction = false; } + /** + * Rolls back the current database transaction. + * @throws \Exception if no transaction is started. + * @return void + */ public function rollback() { if (!$this->inTransaction) { diff --git a/src/Database/Update.php b/src/Database/Update.php index 75f6550..fa59d2c 100644 --- a/src/Database/Update.php +++ b/src/Database/Update.php @@ -10,12 +10,14 @@ class Update extends Query private $table; private $set = []; + /** Sets the table name for the update operation after validating it. @param string $table The name of the table to update. @return Update Returns the current instance for method chaining./ public function table(string $table): Update { $this->table = $this->validateTableName($table); return $this; } + /** Sets the value for a column or multiple columns in the update statement. @param string|array $column The column name as a string or an associative array of column-value pairs. @param mixed $value The value to set for the column. This parameter is ignored if $column is an array. @return Update Returns the current instance of the Update class. @throws \InvalidArgumentException If the column name is an integer or numeric string./ public function set(string|array $column, $value = null): Update { if (is_array($column)) {