2012-06-19 20 views
16

Estoy usando PDO para volver a escribir una interfaz de sitio web para una base de datos. Solía ​​usar la extensión mysql, pero nunca me había molestado con el manejo de errores, y los pocos manejadores de errores que tenía eran básicamente copiar y pegar.PDO Exception Questions - Cómo atraparlos

Ahora me gustaría hacer esto bien. Sin embargo, tengo problemas para detectar los errores de la forma en que me gustaría (errores como "Entrada duplicada", "Valor nulo", etc. en MySQL). ¿Cuánto de mi declaración debe estar en el bloque de prueba? ¿Debería estar todo allí? Estoy usando un Include() para conectarme a mi DB (que tiene su propio manejo de errores), por lo que solo la ejecución de la consulta tiene errores en este código. No puedo entender por qué no se captura un error al ejecutar el siguiente código:

try { 
    $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)"); 
    $stmt->bindValue(":name", $_POST['name']); 
    $stmt->bindValue(":password", $_POST['password']); 
    $stmt->bindValue(":question", $_POST['question']); 
    $stmt->bindValue(":answer", $_POST['answer']); 
    $stmt->execute(); 
    echo "Successfully added the new user " . $_POST['name']; 
} catch (PDOException $e) { 
    echo "The user could not be added.<br>".$e->getMessage(); 
} 

Así que mis preguntas: ¿Todo eso tiene que estar en el bloque try? ¿Puedo poner la ejecución en el bloque de prueba? Debería detectar el error Duplicate value "John" in key "name", pero en su lugar continúa con el mensaje de éxito. (Al intentar agregar dos usuarios "John"). Revisé en PHPMyAdmin; el índice es único y arroja el error como se esperaba, simplemente no usa este código.

+3

Si aún no lo ha hecho, tendrá que configurar '$ db''s' PDO :: ATTR_ERRMODE' a 'PDO :: ERRMODE_EXCEPTION' para que arroje excepciones en los errores. – FtDRbwLXw6

+0

Debe verificar la documentación o el código fuente y ver qué funciones arrojan la 'PDOException'. Entonces sabrá qué partes del código poner en el bloque try :) –

+0

Me siento tonto ... estableciendo el 'ATTR_ERRMODE' solucionado. Entonces, ¿cuánto de la declaración debería estar en el bloque try? El código podría reutilizarse (solo tal vez algunas declaraciones bindValue() cambiarían, luego la ejecución). ¿Hay algún beneficio en tener la declaración completa en el bloque de prueba o solo es necesario ejecutar()? – StuckAtWork

Respuesta

10

Debería mirar la documentación. Pero si usted no encuentra nada, se puede añadir otro inconveniente:

<?php 
try { 
    $stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)"); 
    $stmt->bindValue(":name", $_POST['name']); 
    $stmt->bindValue(":password", $_POST['password']); 
    $stmt->bindValue(":question", $_POST['question']); 
    $stmt->bindValue(":answer", $_POST['answer']); 
    $stmt->execute(); 
    echo "Successfully added the new user " . $_POST['name']; 
} catch (PDOException $e) { 
    echo "DataBase Error: The user could not be added.<br>".$e->getMessage(); 
} catch (Exception $e) { 
    echo "General Error: The user could not be added.<br>".$e->getMessage(); 
} 
?> 

Esto debe trabajar porque todas las excepciones de PHP plugins herits de la clase nativa de PHP Excepción. (Desde 5.0 si mi memoria está bien).

+1

Me había parecido alrededor, pero supongo que asumí erróneamente que PDO lanzó excepciones por defecto. Resulta que debes hacer lo que dijo @drrcknlsn en el primer comentario. Ninguna versión ('Excepción NOR PDOException') arrojaba errores hasta que se cambió. Sin embargo, esto no es una mala idea (puede haber otros errores) – StuckAtWork

+1

@StuckAtWork: :: bindValue o :: bindParam puede fallar si le envía objetos o matrices. No olvides que usar $ _POST directamente no te previene de la inyección XSS cuando envías una matriz aquí. (PD: ¿Acabo de escribir ese comentario aquí y no arriba porque por algún motivo desconocido, no puedo agregar un comentario en su publicación? _?) Lo siento por eso. – niconoe

+0

¿Cómo debo envolver mi $ _POST para codificarlo correctamente? – StuckAtWork

10

DOP excepción Preguntas - ¿Cómo atraparlos

Como regla -

DO NOT catch them.

Por ejemplo, aquí el código debe escribirse de esta manera

$stmt = $db->prepare("INSERT INTO tbl_user (id, name, password, question, answer) VALUES (NULL, :name, :password, :question, :answer)"); 
$stmt->bindValue(":name", $_POST['name']); 
$stmt->bindValue(":password", $_POST['password']); 
$stmt->bindValue(":question", $_POST['question']); 
$stmt->bindValue(":answer", $_POST['answer']); 
$stmt->execute(); 
echo "Successfully added the new user " . $_POST['name']; 

sin escala try o de captura. Porque no tiene un escenario particular para manejar una excepción aquí (un eco simple apenas cuenta como un escenario de manejo).

En su lugar, permita que suba al manejador de errores de toda la aplicación (no se asuste con el término, PHP ya tiene uno incorporado).

Sin embargo, tengo problemas para detectar los errores de cómo me gustaría (errores como "Duplicate Entry", "Null Value" etc en MySQL).

Sólo en caso de que si usted tiene un determinado escenario , usted tiene que utilizar el operador try-catch, pero hay que comprobar siempre, ya sea el error que tienes es uno que se esperaba. De lo contrario, una excepción que ser re-lanzado:

try { 
    $pdo->prepare("INSERT INTO users VALUES (NULL,?,?,?,?)")->execute($data); 
} catch (PDOException $e) { 
    if ($e->getCode() == 1062) { 
     // Take some action if there is a key constraint violation, i.e. duplicate name 
    } else { 
     throw $e; 
    } 
} 

y por supuesto (como resultó ser el problema Vere para esta pregunta), usted tiene que configurar DOP en el modo de excepción, ya sea en un parámetro de constructor de simplemente agregando el código

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

justo después de conectar.

+0

Creo que '23000' es lo que' getCode() 'devolvería en este ejemplo particular, poblado en' $ e-> errorInfo [0] 'con suerte para todos los controladores (probado MySQL y MS SQL Server). El código '1062' se llenaría en' $ e-> errorInfo [1] 'para MySQL y MS SQL Server poblaría' 2627' en '$ e-> errorInfo [1]' –