-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Outdated 9 Year old Dependencies Solution10 #504
Comments
@coderabbitai what do think about |
Tip For best results, initiate chat on the files or code changes. Let me analyze the usage of Solution10\SQL in the codebase and provide my assessment. @ThomasAFink Based on my analysis, I have several concerns about the usage of Solution10\SQL:
Recommendation:
Would you like me to:
Please let me know which approach you'd prefer to tackle this dependency issue. 🔗 Analysis chainLet me analyze the usage of Solution10\SQL in the codebase. 🏁 Scripts executedThe following scripts were executed for the analysis: Script:
Length of output: 15906 ✏️ Learnings added
|
I like the PDO with prepared statements approach. How would you go about refactoring it @coderabbitai? |
Give me an visual overview on how |
Tip For best results, initiate chat on the files or code changes. Let me analyze the current codebase structure and provide a detailed PDO refactoring approach. @ThomasAFink Here's a comprehensive plan to refactor from Solution10\SQL to PDO with prepared statements:
// src/Zmsdb/Config/DatabaseConfig.php
namespace BO\Zmsdb\Config;
class DatabaseConfig
{
public static function getDSN(): string
{
return sprintf(
"mysql:host=%s;dbname=%s;charset=utf8mb4",
getenv('DB_HOST'),
getenv('DB_NAME')
);
}
public static function getOptions(): array
{
return [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
];
}
}
// src/Zmsdb/Connection/DatabaseManager.php
namespace BO\Zmsdb\Connection;
use BO\Zmsdb\Config\DatabaseConfig;
class DatabaseManager
{
private static ?PDO $instance = null;
public static function getInstance(): PDO
{
if (self::$instance === null) {
self::$instance = new PDO(
DatabaseConfig::getDSN(),
getenv('DB_USER'),
getenv('DB_PASSWORD'),
DatabaseConfig::getOptions()
);
}
return self::$instance;
}
}
// src/Zmsdb/Query/QueryBuilderInterface.php
namespace BO\Zmsdb\Query;
interface QueryBuilderInterface
{
public function select(array $columns = ['*']): self;
public function from(string $table, ?string $alias = null): self;
public function where(string $column, string $operator, $value): self;
public function join(string $table, string $first, string $operator, string $second): self;
public function orderBy(string $column, string $direction = 'ASC'): self;
public function limit(int $limit, int $offset = 0): self;
public function getQuery(): string;
public function getParameters(): array;
}
// src/Zmsdb/Repository/BaseRepository.php
namespace BO\Zmsdb\Repository;
use BO\Zmsdb\Connection\DatabaseManager;
abstract class BaseRepository
{
protected PDO $db;
protected string $table;
public function __construct()
{
$this->db = DatabaseManager::getInstance();
}
protected function execute(string $query, array $params = []): PDOStatement
{
$stmt = $this->db->prepare($query);
$stmt->execute($params);
return $stmt;
}
protected function fetchAll(string $query, array $params = []): array
{
return $this->execute($query, $params)->fetchAll();
}
protected function fetchOne(string $query, array $params = []): ?array
{
$result = $this->execute($query, $params)->fetch();
return $result ?: null;
}
protected function insert(array $data): int
{
$columns = implode(', ', array_keys($data));
$values = implode(', ', array_fill(0, count($data), '?'));
$query = "INSERT INTO {$this->table} ($columns) VALUES ($values)";
$this->execute($query, array_values($data));
return (int)$this->db->lastInsertId();
}
protected function update(array $data, array $conditions): int
{
$set = implode(', ', array_map(fn($col) => "$col = ?", array_keys($data)));
$where = implode(' AND ', array_map(fn($col) => "$col = ?", array_keys($conditions)));
$query = "UPDATE {$this->table} SET $set WHERE $where";
$stmt = $this->execute($query, [...array_values($data), ...array_values($conditions)]);
return $stmt->rowCount();
}
}
// src/Zmsdb/Repository/ProcessRepository.php
namespace BO\Zmsdb\Repository;
class ProcessRepository extends BaseRepository
{
protected string $table = 'buerger';
public function findById(int $id): ?array
{
$query = "
SELECT p.*, s.name as scope_name
FROM buerger p
LEFT JOIN standort s ON p.StandortID = s.StandortID
WHERE p.BuergerID = :id
";
return $this->fetchOne($query, ['id' => $id]);
}
public function findByStatus(string $status, int $scopeId): array
{
$query = "
SELECT p.*
FROM buerger p
WHERE p.StandortID = :scopeId
AND CASE
WHEN p.Name = '(abgesagt)' THEN 'deleted'
WHEN p.StandortID = 0 THEN 'blocked'
WHEN p.vorlaeufigeBuchung = 1 AND p.bestaetigt = 0 THEN 'reserved'
-- ... (rest of the status logic)
END = :status
";
return $this->fetchAll($query, [
'scopeId' => $scopeId,
'status' => $status
]);
}
public function updateStatus(int $processId, string $status): bool
{
$statusMap = [
'called' => ['aufrufzeit' => date('H:i:s')],
'processing' => ['aufruferfolgreich' => 1],
'missed' => ['nicht_erschienen' => 1],
// ... other status mappings
];
if (!isset($statusMap[$status])) {
throw new \InvalidArgumentException("Invalid status: $status");
}
return $this->update($statusMap[$status], ['BuergerID' => $processId]) > 0;
}
}
// Example service class
class ProcessService
{
private ProcessRepository $repository;
public function __construct(ProcessRepository $repository)
{
$this->repository = $repository;
}
public function getProcessDetails(int $processId): array
{
$process = $this->repository->findById($processId);
if (!$process) {
throw new ProcessNotFoundException($processId);
}
return $process;
}
} Benefits of this approach:
Would you like me to:
🔗 Analysis chainLet me analyze the current query patterns to provide a detailed refactoring approach. Let me analyze the query patterns and provide a concrete refactoring plan. @ThomasAFink Here's a detailed approach to refactor from Solution10\SQL to PDO with prepared statements:
class DatabaseConnection {
private static ?PDO $instance = null;
public static function getInstance(): PDO {
if (self::$instance === null) {
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4";
self::$instance = new PDO($dsn, DB_USER, DB_PASSWORD, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]);
}
return self::$instance;
}
}
abstract class BaseQuery {
protected PDO $db;
protected array $params = [];
public function __construct() {
$this->db = DatabaseConnection::getInstance();
}
protected function execute(string $query, array $params = []): PDOStatement {
$stmt = $this->db->prepare($query);
$stmt->execute($params);
return $stmt;
}
protected function fetchAll(string $query, array $params = []): array {
return $this->execute($query, $params)->fetchAll();
}
protected function fetchOne(string $query, array $params = []): ?array {
$result = $this->execute($query, $params)->fetch();
return $result !== false ? $result : null;
}
}
class UserQuery extends BaseQuery {
public function findById(int $id): ?array {
$query = "SELECT * FROM users WHERE id = :id";
return $this->fetchOne($query, ['id' => $id]);
}
public function findByEmail(string $email): ?array {
$query = "SELECT * FROM users WHERE email = :email";
return $this->fetchOne($query, ['email' => $email]);
}
public function create(array $data): int {
$query = "INSERT INTO users (name, email) VALUES (:name, :email)";
$this->execute($query, [
'name' => $data['name'],
'email' => $data['email']
]);
return (int)$this->db->lastInsertId();
}
}
class UserQueryTest extends TestCase {
private UserQuery $query;
protected function setUp(): void {
$this->query = new UserQuery();
}
public function testFindById(): void {
$user = $this->query->findById(1);
$this->assertIsArray($user);
$this->assertArrayHasKey('id', $user);
}
} Benefits of this approach:
Would you like me to:
🏁 Scripts executedThe following scripts were executed for the analysis: Script:
Length of output: 89614 ✏️ Learnings added
🧠 Learnings used
|
Tip For best results, initiate chat on the files or code changes. @ThomasAFink Based on the code analysis, here's a visual overview of how Solution10\SQL is used in the codebase: classDiagram
class Solution10SQL {
+Select
+Insert
+Update
+Delete
+Expression
+ConditionBuilder
}
class Base {
+query: Solution10\SQL\Query
+prefix: string
+name: string
+resolveLevel: int
+__construct()
+addSelect()
+addTable()
+leftJoin()
+getSql()
+getParameters()
#expression()
}
Base --> Solution10SQL : uses
class Process
class Queue
class ProcessStatusArchived
class Provider
class Request
class Useraccount
Base <|-- Process
Base <|-- Queue
Base <|-- ProcessStatusArchived
Base <|-- Provider
Base <|-- Request
Base <|-- Useraccount
note for Base "Abstract base class that\nhandles SQL operations"
note for Solution10SQL "External query builder\nlibrary"
Key usage patterns:
This architecture makes Solution10\SQL deeply integrated into the codebase's data access layer, which explains why replacing it would require significant refactoring. Would you like me to provide a detailed migration plan to PDO with prepared statements? 🔗 Analysis chainLet me gather information about how Solution10\SQL is used in the codebase. Let me analyze the results and create a visual overview. @ThomasAFink Here's a visual overview of how Solution10\SQL is used in the codebase: classDiagram
class Base {
+select()
+insert()
+update()
+delete()
#buildQuery()
#executeQuery()
}
class Solution10SQL {
+select()
+insert()
+update()
+delete()
+where()
+join()
}
Base --> Solution10SQL : uses
Base <|-- Alias
Base <|-- Request
Base <|-- Provider
Base <|-- Queue
Base <|-- Useraccount
Base <|-- Process
Base <|-- ProcessStatusArchived
Base <|-- Availability
note for Base "Abstract base class that\nwraps Solution10\SQL\noperations"
note for Solution10SQL "External library for\nSQL query building"
The architecture follows a pattern where:
This design makes it relatively straightforward to replace Solution10\SQL with PDO prepared statements, as we can:
Would you like me to provide a concrete example of how to refactor one of these query classes to use PDO with prepared statements? 🏁 Scripts executedThe following scripts were executed for the analysis: Script:
Length of output: 76270 🧠 Learnings used
|
What is Solution10 and why is it used to create queries? 8 stars on Github... 9 years no update... for PHP 5.4?
eappointment/zmsdb/src/Zmsdb/Query/Base.php
Line 5 in 9d615f0
https://github.com/Solution10/sql
The text was updated successfully, but these errors were encountered: