Deploy: 2026-05-21 01:58:32
This commit is contained in:
@@ -12,12 +12,42 @@ abstract class BaseModel
|
||||
protected static string $table = '';
|
||||
protected static string $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Validate table, primary key, and column names to prevent SQL injection.
|
||||
*/
|
||||
protected static function getSafeTable(): string
|
||||
{
|
||||
$table = static::$table;
|
||||
if (!preg_match('/^[a-zA-Z0-9_]+$/', $table)) {
|
||||
throw new \InvalidArgumentException("Invalid table name: {$table}");
|
||||
}
|
||||
return $table;
|
||||
}
|
||||
|
||||
protected static function getSafePrimaryKey(): string
|
||||
{
|
||||
$primaryKey = static::$primaryKey;
|
||||
if (!preg_match('/^[a-zA-Z0-9_]+$/', $primaryKey)) {
|
||||
throw new \InvalidArgumentException("Invalid primary key: {$primaryKey}");
|
||||
}
|
||||
return $primaryKey;
|
||||
}
|
||||
|
||||
protected static function validateColumns(array $columns): void
|
||||
{
|
||||
foreach ($columns as $column) {
|
||||
if (!preg_match('/^[a-zA-Z0-9_]+$/', $column)) {
|
||||
throw new \InvalidArgumentException("Invalid column name: {$column}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all records
|
||||
*/
|
||||
public static function all(): array
|
||||
{
|
||||
$table = static::$table;
|
||||
$table = static::getSafeTable();
|
||||
return Database::select("SELECT * FROM {$table}");
|
||||
}
|
||||
|
||||
@@ -29,22 +59,27 @@ abstract class BaseModel
|
||||
*/
|
||||
public static function find($id): ?array
|
||||
{
|
||||
$table = static::$table;
|
||||
$primaryKey = static::$primaryKey;
|
||||
// Enforce integer conversion or validate to prevent type misuse
|
||||
$id = is_numeric($id) ? (int)$id : $id;
|
||||
$table = static::getSafeTable();
|
||||
$primaryKey = static::getSafePrimaryKey();
|
||||
return Database::selectOne("SELECT * FROM {$table} WHERE {$primaryKey} = :id LIMIT 1", ['id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new record
|
||||
*
|
||||
* @param array $data Assocation array of columns and values
|
||||
* @param array $data Association array of columns and values
|
||||
* @return string Last inserted primary key ID
|
||||
*/
|
||||
public static function create(array $data): string
|
||||
{
|
||||
$table = static::$table;
|
||||
$columns = implode(', ', array_keys($data));
|
||||
$placeholders = ':' . implode(', :', array_keys($data));
|
||||
$table = static::getSafeTable();
|
||||
$columnKeys = array_keys($data);
|
||||
static::validateColumns($columnKeys);
|
||||
|
||||
$columns = implode(', ', $columnKeys);
|
||||
$placeholders = ':' . implode(', :', $columnKeys);
|
||||
|
||||
$sql = "INSERT INTO {$table} ({$columns}) VALUES ({$placeholders})";
|
||||
return Database::insert($sql, $data);
|
||||
@@ -59,11 +94,15 @@ abstract class BaseModel
|
||||
*/
|
||||
public static function update($id, array $data): int
|
||||
{
|
||||
$table = static::$table;
|
||||
$primaryKey = static::$primaryKey;
|
||||
$id = is_numeric($id) ? (int)$id : $id;
|
||||
$table = static::getSafeTable();
|
||||
$primaryKey = static::getSafePrimaryKey();
|
||||
|
||||
$columnKeys = array_keys($data);
|
||||
static::validateColumns($columnKeys);
|
||||
|
||||
$sets = [];
|
||||
foreach (array_keys($data) as $column) {
|
||||
foreach ($columnKeys as $column) {
|
||||
$sets[] = "{$column} = :{$column}";
|
||||
}
|
||||
$setSql = implode(', ', $sets);
|
||||
@@ -81,8 +120,9 @@ abstract class BaseModel
|
||||
*/
|
||||
public static function delete($id): int
|
||||
{
|
||||
$table = static::$table;
|
||||
$primaryKey = static::$primaryKey;
|
||||
$id = is_numeric($id) ? (int)$id : $id;
|
||||
$table = static::getSafeTable();
|
||||
$primaryKey = static::getSafePrimaryKey();
|
||||
|
||||
$sql = "DELETE FROM {$table} WHERE {$primaryKey} = :id";
|
||||
return Database::execute($sql, ['id' => $id]);
|
||||
|
||||
Reference in New Issue
Block a user