TransWikia.com

Alternativa de fetchAll

Stack Overflow en español Asked by Cesar Reyna on November 21, 2020

tengo este código donde mando a llamar a una fila con datos de una prenda (nombre,cantidad,color,etc), y quiero saber si hay una manera de que no use un foreach por que estoy usando un FetchAll, anteriormente usaba PDO para traer el valor de la columna en la fila de manera que antes era algo asi: echo $variable[0][1];

Estoy abierto a sugerencias y comentarios de este pequeño problema que tengo, gracias.

<?php 
include 'bd/conexion.php';
$sql = "SELECT * FROM Productos INNER JOIN Detalle_Producto WHERE idProducto = '" . $_GET['btnmodificar'] . "'";



if (isset($_GET['btnmodificar'])) {
    echo '<script>console.log("Funcionando");</script>';
    $sentencia = $PDO->prepare($sql);
    $sentencia->execute();
    $resultado = $sentencia->fetchAll();
    // var_dump($resultado);

} 
else{
    echo '<script>alert("Ha ocurrido un error");</script>';
}


?>


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <?php foreach ($resultado as $item) : ?>
        <h2>
            <?php echo $item['Nombre_Producto']; ?>
        </h2>
    <?php endforeach ?>
</body>

</html>

One Answer

El problema es que fetchAll() te devuelve un array y dentro de ese array varios sub-arrays por cada fila, de modo que al hacer esto:

$resultado = $sentencia->fetchAll();

Todas las filas estarán en el índice 0 de $resultado.

PDO tiene varias alternativas, según la necesitad que tengas.

Se espera una sola fila

En ese caso, optimiza la consulta SQL agregando al final LIMIT 1 y accede a los datos mediante el método fetch:

#Cambiaremos a consultas preparadas (ver al final)
$sql = "SELECT * FROM Productos INNER JOIN Detalle_Producto WHERE idProducto = :idProducto LIMIT 1";
$resultado = $sentencia->fetch(PDO::FETCH_ASSOC);

Aquí $resultado será la fila única que esperas y luego podrás acceder a cada columna con algo como $resultado["laColumna"] simplemente.

Se espera una sola fila/columna

Entonces puedes usar fetchColumn():

$sql = "SELECT columnaUnica FROM Productos INNER JOIN Detalle_Producto WHERE idProducto = :idProducto LIMIT 1";
$resultado = $sentencia->fetchColumn();

Aquí $resultado será el valor en sí de la columna única que esperas de una fila única**.

Se esperan varias filas

Entonces el bucle es obligatorio de cualquier modo. En este caso hay que decidir varias cosas:

a. Si esperas muchas filas/columnas evita el uso de fetchAll(), porque este método vuelca de golpe el conjunto de resultados. Si son muchas filas y la capacidad de memoria es excedida el script bloqueará/causará un crash. En ese caso es mejor usar fetch

b. Si decides usar fetch, y los datos se necesitan in situ, entonces abre un bucle que recorra el puntero de los resultados y velos mostrando/concatenando en una variable (por ejemplo cuando construyes una tabla o lista usando la información).

c. Si decides usar fetch y los datos necesitan ser devueltos a otra parte, entonces llena un array desde el bucle donde lees con fetch y devuelve ese array.

#El LIMIT 1 desaparece porque se esperan varias filas
$sql = "SELECT columnaUnica FROM Productos INNER JOIN Detalle_Producto WHERE idProducto = :idProducto";

while ($row = $sentencia->fetch(PDO::FETCH_ASSOC)) {
  #Aquí imprimes o guardas cada fila según necesidad explicadas en (b) y (c)
  # (b) echo $row["laColumna"] ....  o concatenar a una variable
  # (c) $elArrayADevolver[]=$row;
}

NOTA IMPORTANTE, pasa siempre a fetch y a fetchAll de forma explícita el método en que debe organizar los datos. En este caso estamos pasando siempre: PDO::FETCH_ASSOC, si no lo haces usará el método por defecto, que es PDO::FETCH_BOTH el cual devuelve un array indexado tanto por nombre de columna, como numéricamente con índice de base 0 tal como fue devuelto en el conjunto de resultados. Eso puede ser trágico para la memoria cuando manejas muchos datos.


Sobre la seguridad de tu código

Tu código es altamente vulnerable a ataques de inyección SQL. Estás usando mal el método prepare, porque tu instrucción SQL no es preparada, pasas el dato directamente. Debes poder un marcador y pasar el dato con bindParam (ver aquí para más detalles).

$idProducto=!empty($_GET['btnmodificar']) ? $_GET['btnmodificar'] : NULL;
if ($idProducto) {
    echo '<script>console.log("Funcionando");</script>';
    $sql = "SELECT * FROM Productos INNER JOIN Detalle_Producto WHERE idProducto = :idProducto";
    $sentencia = $PDO->prepare($sql);
    $sentencia->bindParam(':idProducto', $idProducto, PDO::PARAM_INT);
    $sentencia->execute();
    #Usar el fetch que más te convenga

} 

Correct answer by A. Cedano on November 21, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP