Compare commits

..

10 Commits

Author SHA1 Message Date
Guillermo Pages
777b531ce7 refactor: replace hardcoded credentials with env vars
- Use getenv() with RuntimeException for missing required vars
- Add .env.example template
- Add .env to .gitignore
- Fix missing return statement in config array
2026-01-14 14:15:28 +01:00
Guillermo Pages
9a83c3b52e fix: Deprecated: Return type ArrayAccess ixed 2023-11-24 16:04:47 +01:00
Guillermo Pages
86b781857f fix: Deprecated: Return type of Bsr\Db\OdbcResultSet::current() should either be compatible with Iterator::current(): mixed 2023-11-24 15:28:28 +01:00
Guillermo Pages
a07065ab8c fix: false < 6 is true 2021-09-27 12:16:42 +02:00
Guillermo Pages
27e80613c7 feat: allow overriding the default output test 2021-09-27 12:06:32 +02:00
Guillermo Pages
e65701fa56 fix: discarding UPDATE OUTPUT 2021-09-27 11:36:32 +02:00
Guillermo Pages
2a6e034f01 fix: only variables should be passed by reference 2021-09-14 09:50:25 +02:00
Guillermo Pages
881693402a fix: bad cursor state 2021-09-13 19:49:50 +02:00
Guillermo Pages
a2a07ceccf fix: [FreeTDS][SQL Server]Invalid cursor state 2021-09-13 18:30:28 +02:00
Guillermo Pages
559558a530 fix: Missing class OdbcResultSet 2021-09-13 18:23:43 +02:00
6 changed files with 141 additions and 10 deletions

4
.env.example Normal file
View File

@@ -0,0 +1,4 @@
# Database configuration
DB_DSN=odbc:Driver=FreeTDS; Server=localhost; Port=1218; Database=mydb
DB_USER=myuser
DB_PASSWORD=changeme

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
vendor
*.lock
.env

View File

@@ -0,0 +1,24 @@
<?php
/**
* Database configuration - credentials loaded from environment variables
*/
$getEnvOrThrow = function(string $name): string {
$value = getenv($name);
if ($value === false || $value === '') {
throw new \RuntimeException("Environment variable {$name} is not set");
}
return $value;
};
return array('db_req' =>
array(
'driver_class' => '\PDO',
'dsn' => $getEnvOrThrow('DB_DSN'),
'driver_params' => array(
'username' => $getEnvOrThrow('DB_USER'),
'password' => $getEnvOrThrow('DB_PASSWORD'),
),
)
);

View File

@@ -23,26 +23,27 @@ class Connection
* @return OdbcResultSet|resource|string
* @throws SqlException
*/
public static function execute($sql, $values = array(), $fetchMode = \PDO::FETCH_ASSOC)
public static function execute($sql, $values = array(), $fetchMode = \PDO::FETCH_ASSOC, $hasOutput = null)
{
$statement = PDOWithFilters::prepare($sql);
$success = $statement->execute(!empty($values) ? $values : null);
if (!$success) {
$statement->closeCursor();
throw new SqlException('SQL There was an error executing the request');
}
$selectPos = strpos($sql, "SELECT");
if ((($selectPos !== false && $selectPos < 6) || strpos($sql, "OUTPUT INSERTED") !== false) && (($hasOutput !== null && $hasOutput !== false) || $hasOutput === null)) {
$rows = $statement->fetchAll($fetchMode);
if (!is_array($rows)) {
$statement->closeCursor();
throw new SqlException('PDO Unable to retrieve the result');
}
return new OdbcResultSet($rows);
}
$statement->closeCursor();
return new OdbcResultSet($rows);
return true;
}
/**

View File

@@ -25,10 +25,10 @@ class DbHelper
ORDER BY text;";
$results = Connection::execute($sql);
$results = Connection::execute($sql)->to_array();
if($withJeunesse) {
array_unshift($results->to_array(), array('code' => 'J', 'text' => 'Jeunesse'));
array_unshift($results, array('code' => 'J', 'text' => 'Jeunesse'));
}
return $results;

101
src/Db/OdbcResultSet.php Normal file
View File

@@ -0,0 +1,101 @@
<?php
namespace Bsr\Db;
class OdbcResultSet implements \Iterator, \ArrayAccess, \Countable
{
public $length;
private $results;
private $error = false;
private $num_fields;
private $num_rows;
private $cursor_index;
public function __construct($resultset)
{
$this->results = $resultset;
$this->num_fields = is_array(current($resultset)) ? count(current($resultset)) : count($resultset);
$this->num_rows = count($this->results);
$this->length = $this->num_rows;
$this->cursor_index = 0;
}
public function get_num_rows()
{
return $this->num_rows;
}
public function is_error()
{
return ($this->error ? true : false);
}
public function get_error()
{
return $this->error;
}
public function get_row()
{
return $this->current();
}
public function to_array()
{
return $this->results;
}
// Implementing Countable
public function count(): int {
return $this->get_num_rows();
}
// Implementing ArrayAccess
public function offsetExists(mixed $offset): bool
{
return !$this->error && $offset < $this->length && $offset >= 0;
}
public function offsetGet(mixed $offset): mixed
{
return $this->offsetExists($offset) ? $this->results[$offset] : false;
}
public function offsetSet(mixed $offset, mixed $value): void
{
if($this->offsetExists($offset)) {
$this->results[$offset] = $value;
}
}
public function offsetUnset(mixed $offset): void
{
throw new \RuntimeException("Unsetting elements is not supported.");
}
// Implementing Iterator
public function current(): mixed
{
return $this->offsetGet($this->cursor_index);
}
public function key(): mixed
{
return $this->cursor_index;
}
public function next(): void
{
++$this->cursor_index;
}
public function rewind(): void
{
$this->cursor_index = 0;
}
public function valid(): bool
{
return $this->offsetExists($this->cursor_index);
}
}