{"id":5396,"date":"2026-01-20T12:24:56","date_gmt":"2026-01-20T11:24:56","guid":{"rendered":"https:\/\/sutilweb.eu\/?page_id=5396"},"modified":"2026-01-20T12:24:58","modified_gmt":"2026-01-20T11:24:58","slug":"58-inyeccion-sql-en-php","status":"publish","type":"page","link":"https:\/\/sutilweb.eu\/index.php\/lenguajes\/php\/php-practico\/58-inyeccion-sql-en-php\/","title":{"rendered":"58. Inyecci\u00f3n SQL en PHP"},"content":{"rendered":"\n<p>En cap\u00edtulos anteriores hab\u00edamos visto como pod\u00edamos conectarnos a una base de datos, como podemos hacer consultas SQL, y hemos creado cierta cantidad de m\u00e9todos que nos van a permitir hacer consultas a nuestra base de datos de manera m\u00e1s f\u00e1cil.<\/p>\n\n\n\n<p>En este cap\u00edtulo hablaremos de un tema bastante importante y es la inyecci\u00f3n SQL, el cual es un tipo de ciberataque en cubierto, en el cual un hacker inserta c\u00f3digo propio en un sitio web con el fin de quebrantar las medidas de seguridad y acceder a datos protegidos. Este tipo de ataque se va a presentar cuando presentemos formularios en nuestra aplicaci\u00f3n, formularios que le permita escribir c\u00f3digo.<\/p>\n\n\n\n<p>Una de las formas que tenemos de que no se inyecte c\u00f3digo SQL es escapando del c\u00f3digo que pueda insertar un hacker, otra manera es mediante las sentencias preparadas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Consultas preparadas en PHP MySQL<\/h2>\n\n\n\n<p>Para preparar nuestras consultas de posibles inyecciones SQL vamos a trabajar en nuestro archivo Model.php en&nbsp;los m\u00e9todos where() y query(). Os dejamos el archivo con la nueva sintaxis:<\/p>\n\n\n\n<p><em>Models\/Model.php<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Models;\n\nuse mysqli;\n\nclass Model \n{\n  \/\/ Propiedades que recogen los datos de acceso a la BBDD\n  protected $db_host = DB_HOST;\n  protected $db_user = DB_USER;\n  protected $db_pass = DB_PASS;\n  protected $db_name = DB_NAME;\n\n  \/\/ Propiedad que recoge la conexi\u00f3n a la base de datos\n  protected $connection;\n\n  \/\/ Propiedad que recoge la consulta a la BBDD\n  protected $query;\n\n  public function __construct(){\n    $this->connection();\n  }\n\n  \/\/ M\u00e9todo encargado de realizar la conexi\u00f3n\n  public function connection(){\n    \/\/ Conexi\u00f3n con mysqli\n    $this->connection =  new mysqli($this->db_host, $this->db_user, $this->db_pass, $this->db_name);\n\n    if($this->connection->connect_error)\n    {\n      die('Error de conexi\u00f3n: ' . $this->connection->connect_error);\n    }\n  }\n\n  \/\/ M\u00e9todo que hace la consulta a la base de datos\n  public function query($sql, $data = &#91;], $params = null){\n    if($data){\n      if($params == null){\n        $params = str_repeat('s', count($data));\n      }\n\n      \/\/ Creamos una sentencia preparada\n      $stmt = $this->connection->prepare($sql);\n      \/\/ Especificamos el tipo de elemento con 's' y especificamos el valor con $value\n      $stmt->bind_param($params, ...$data);\n      \/\/ Ejecutamos la sentencia\n      $stmt->execute();\n\n      \/\/ Accedemos al resultado de la consulta\n      \/\/ Lo guardamos en la variable $query\n      $this->query = $stmt->get_result();\n    } else {\n      $this->query = $this->connection->query($sql);\n    }\n    return $this;\n  }\n\n  \/\/ M\u00e9todo que recupera el primer registro de la consulta a la base de datos\n  public function first(){\n    return $this->query->fetch_assoc();\n  }\n\n  \/\/ M\u00e9todo que recupera todos los registros de la consulta a la base de datos\n  public function get(){\n    return $this->query->fetch_all(MYSQLI_ASSOC);\n  }\n\n  \/\/ Consultas\n  \/\/ M\u00e9todo que nos devolver\u00e1 todos los registros de una determinada tabla\n  public function all(){\n    $sql = \"SELECT * FROM {$this->table}\";\n    return $this->query($sql)->get();\n  }\n  \n  \/\/ Recuperar determinado registro por su id\n  public function find($id){\n    \/\/ SELECT * FROM contacts WHERE id = 1\n    $sql = \"SELECT * FROM {$this->table} WHERE id = ?\";\n    return $this->query($sql, &#91;$id], 'i')->first();\n  }\n  \n  \/\/ M\u00e9todo para filtrar registros\n  public function where($column, $operator, $value = null){\n    if($value == null){\n      $value = $operator;\n      $operator = '=';\n    }\n\n    \/\/ La sentencia comentada sirve para escapar de posibles ataques SQL\n    \/\/ $value = $this->connection->real_escape_string($value);\n\n    \/\/ SELECT * FROM contacts WHERE name = 'Francisco'\n    $sql = \"SELECT * FROM {$this->table} WHERE {$column} {$operator} ?\";\n\n    $this->query($sql, &#91;$value], 's');\n\n    \/\/ Pedimos que retorne el objeto\n    return $this;\n  }\n\n  \/\/ M\u00e9todo para agregar registros\n  public function create($data){\n    \/\/ INSERT INTO contacts (name, email, phone) VALUES (? ? ?)\n\n    $columns = array_keys($data);\n    $columns = implode(', ', $columns);\n    \n    $values = array_values($data);\n\n    $sql = \"INSERT INTO {$this->table} ({$columns}) VALUES (\" . str_repeat('?, ', count($values) - 1) . \"?)\";\n\n    $this->query($sql, $values);\n\n    $insert_id = $this->connection->insert_id;\n\n    return $this->find($insert_id);\n  }\n\n  public function update($id, $data){\n    \/\/ UPDATE contacts SET name = ?, email = ?, phone = ? WHERE id = 1\n    $fields = &#91;];\n\n    foreach($data as $key => $value){\n      $fields&#91;] = \"{$key} = ?\";\n    }\n\n    $fields = implode(', ', $fields);\n\n    $sql = \"UPDATE {$this->table} SET {$fields} WHERE id = ?\";\n\n    $values = array_values($data);\n    $values&#91;] = $id;\n\n    $this->query($sql, $values);\n\n    return $this->find($id);\n  }\n\n  public function delete($id){\n    \/\/ DELETE FROM contacts WHERE id = 1\n    $sql = \"DELETE FROM {$this->table} WHERE id = ?\";\n\n    \/\/ EJECUTAMOS LA CONSULTA\n    \/\/ NO ES NECESARIO NADA M\u00c1S, NO NECESITAMOS QUE RETORNE NADA\n    $this->query($sql, &#91;$id], 'i');\n  }\n}<\/code><\/pre>\n\n\n\n<p>Las consultas preparadas van a ser sobretodo \u00fatiles cuando dentro de nuestra consulta tenemos m\u00e1s de un valor.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En cap\u00edtulos anteriores hab\u00edamos visto como pod\u00edamos conectarnos a una base de datos, como podemos hacer consultas SQL, y hemos [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":4518,"menu_order":57,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-5396","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Sutil Web","author_link":"https:\/\/sutilweb.eu\/index.php\/author\/sutilweb\/"},"uagb_comment_info":0,"uagb_excerpt":"En cap\u00edtulos anteriores hab\u00edamos visto como pod\u00edamos conectarnos a una base de datos, como podemos hacer consultas SQL, y hemos [&hellip;]","_links":{"self":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/5396","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/comments?post=5396"}],"version-history":[{"count":2,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/5396\/revisions"}],"predecessor-version":[{"id":5398,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/5396\/revisions\/5398"}],"up":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/4518"}],"wp:attachment":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/media?parent=5396"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}