---
title: Seguridad en queries — pSQL y casting
section: database
slug: security
description: "Como escribir queries seguras en PrestaShop: pSQL(), (int) casting, bqSQL(), prevencion de SQL injection y buenas practicas."
keywords: prestashop seguridad query pSQL int bqSQL SQL injection prevencion escaping sanitizacion
last_updated: 2024-12-01
source_url: "https://ayudaprestashop.es/database/security"
---

# Seguridad en queries — pSQL y casting

> Como escribir queries seguras en PrestaShop: pSQL(), (int) casting, bqSQL(), prevencion de SQL injection y buenas practicas.

La regla de oro de seguridad en base de datos es: nunca concatenar datos de usuario en una query sin sanear. PrestaShop no usa prepared statements nativos pero proporciona funciones de escape que deben usarse SIEMPRE.

## Funciones de escape

| Funcion | Uso | Ejemplo |
| --- | --- | --- |
| pSQL($str) | Strings en condiciones WHERE, INSERT, UPDATE | WHERE name = '" . pSQL($name) . "' |
| (int) $val | IDs y enteros | WHERE id_product = " . (int)$id |
| (float) $val | Precios y decimales | SET price = " . (float)$price |
| (bool) $val | Booleanos | SET active = " . (int)(bool)$active |
| bqSQL($table) | Nombres de tablas y columnas | FROM `" . bqSQL($table) . "` |
| intval($arr) | Arrays de IDs con array_map | IN (" . implode(',', array_map('intval', $ids)) . ") |

## Reglas por tipo de dato

*Reglas de escape por tipo de dato*

```php
<?php

// ── IDs (integers) — SIEMPRE casting a int ──
$idProduct  = (int) Tools::getValue('id_product');
$idOrder    = (int) $_GET['id_order'];
$idCustomer = (int) Context::getContext()->customer->id;

// Uso:
$sql = 'WHERE id_product = ' . $idProduct;  // OK

// ── Strings — SIEMPRE pSQL() ──
$name     = pSQL(Tools::getValue('name'));
$search   = pSQL(Tools::getValue('q'));
$email    = pSQL(Tools::getValue('email'));

// Uso:
$sql = "WHERE name = '" . $name . "'";              // OK
$sql = "WHERE email LIKE '%" . $search . "%'";       // OK

// ── Floats/precios — SIEMPRE casting a float ──
$price   = (float) Tools::getValue('price');
$amount  = (float) $_POST['amount'];

// Uso:
$sql = 'SET price = ' . number_format($price, 6, '.', ''); // OK

// ── Arrays de IDs ──
$idList = Tools::getValue('ids');  // puede ser '1,2,3' o [1,2,3]

if (is_array($idList)) {
    $safeIds = implode(',', array_map('intval', $idList));
} elseif (is_string($idList)) {
    $safeIds = implode(',', array_map('intval', explode(',', $idList)));
}

// Uso:
$sql = 'WHERE id_product IN (' . $safeIds . ')';  // OK

// ── Nombres de tablas y columnas ──
$table  = bqSQL(Tools::getValue('table'));
$column = bqSQL(Tools::getValue('sort_by'));

// Uso:
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . $table . '` ORDER BY `' . $column . '`';
```

## Ejemplos correctos vs incorrectos

*Comparacion de queries seguras vs vulnerables*

```php
<?php

// ═══════════════════════════════════════════════
// ❌ VULNERABLE — SQL Injection posible
// ═══════════════════════════════════════════════

$id   = $_GET['id'];         // Sin validar
$name = $_POST['name'];      // Sin escapar

$sql = 'SELECT * FROM ps_product WHERE id_product = ' . $id;
// Payload: id=1 OR 1=1 → SELECT * FROM ps_product WHERE id_product = 1 OR 1=1

$sql = "SELECT * FROM ps_product WHERE name = '" . $name . "'";
// Payload: name='; DROP TABLE ps_product; --

// ═══════════════════════════════════════════════
// ✅ CORRECTO — Queries seguras
// ═══════════════════════════════════════════════

$id   = (int) Tools::getValue('id');      // Casting a int
$name = pSQL(Tools::getValue('name'));    // Escape de string

$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'product` WHERE id_product = ' . $id;
// id=1 OR 1=1 → id_product = 1 (0 si no es numero)

$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'product` WHERE name = \'' . $name . "'";
// name='; DROP TABLE... → name = \'; DROP TABLE...\' (escapado)

// ── DbQuery es mas limpio para queries complejas ──
$products = Db::getInstance()->executeS(
    (new DbQuery())
        ->select('*')
        ->from('product')
        ->where('id_product = ' . (int) $id)
        ->where("name = '" . pSQL($name) . "'")
);
```

## Validacion antes de consultar

*Validar datos antes de usar en queries*

```php
<?php

// ── Validar con la clase Validate de PrestaShop ──
$idProduct = (int) Tools::getValue('id_product');

// Validar que el ID existe antes de usarlo
if (!Validate::isLoadedObject(new Product($idProduct))) {
    // El producto no existe o ID invalido
    Tools::redirect('index.php?controller=404');
}

// ── Validar email antes de query ──
$email = Tools::getValue('email');
if (!Validate::isEmail($email)) {
    throw new \InvalidArgumentException('Email invalido');
}
$safeEmail = pSQL($email);

// ── Lista blanca para ORDER BY (evitar inyeccion en columnas) ──
$allowedSortColumns = ['name', 'price', 'date_add', 'sort_order'];
$sortBy = Tools::getValue('sort_by', 'date_add');

if (!in_array($sortBy, $allowedSortColumns, true)) {
    $sortBy = 'date_add'; // Valor por defecto si no es valido
}

$sortOrder = Tools::getValue('sort_order', 'DESC');
$sortOrder = strtoupper($sortOrder) === 'ASC' ? 'ASC' : 'DESC'; // Solo ASC o DESC

$sql = 'SELECT * FROM ... ORDER BY `' . $sortBy . '` ' . $sortOrder;
```


---

*Fuente: [https://ayudaprestashop.es/database/security](https://ayudaprestashop.es/database/security). Version Markdown generada automaticamente para consumo por LLMs.*
