Pregunta

I have input values from a HTML textarea element that cannot be inserted into MySQL table because it contains the apostrophe(') character eg: 'Adam's garden'. So I used PDO::prepare() function as advised by the PHP documentaion but I am still unable to insert this data into a table, but when I remove the apostrophe to get 'Adams garden' instead, the value is inserted successfully

I thought the PDO::prepare() function was supposed to take care of quotes and escaping special characters for SQL statements. The PHP documentation did say to use PDO::prepare() with bound-parameters but I am not bounding my php variables to query-parameters. Is the bound parameters absolutely necessary or it is just stated because that is the usual way of using PDO::prepare() function?

How else do I quote and escape special characters in my input variables?

EDIT: I am using string concatenation to do multiple SQL INSERT. The apostrophe is found in the $evData['Description'] field of the sample code below.

$evQuery ="INSERT INTO ep_events
        VALUES(NULL, '" .$evData['Title'] ."', '" .$evData['Venue'] ."', '" .$evData['Address'] ."', '" .$evData['Description'] ."')";


$tkQuery ="INSERT INTO ep_tickets VALUES";
foreach ($tkData as $ref =>$tkObj){
    for($i=0; $i<$tkObj['Quantity']; $i++){
        $tkQuery .='(NULL, LAST_INSERT_ID(), "' .$tkObj['Name'] .'", "' .$tkObj['Price'] .'"),';
    }
}

$tkQuery =rtrim($tkQuery, ',');

$query ='START TRANSACTION;' .$evQuery ."; " .$tkQuery .';' .'COMMIT;';
$stm =$db->prepare($query);     
$stm->execute();

This is the PHP documentation segment:

PDO::quote() places quotes around the input string (if required) and escapes special >characters within the input string, using a quoting style appropriate to the underlying >driver.

If you are using this function to build SQL statements, you are strongly recommended to use PDO::prepare() to prepare SQL statements with bound parameters instead of using PDO::quote() to interpolate user input into an SQL statement. Prepared statements with bound parameters are not only more portable, more convenient, immune to SQL injection, but are often much faster to execute than interpolated queries, as both the server and client side can cache a compiled form of the query. http://www.php.net/manual/en/pdo.quote.php

¿Fue útil?

Solución

PDO::prepare only creates a prepared statement. The query has to be properly parameterized and you have to send arguments to execute (or otherwise bind them) for them to be properly escaped. For example:

$ta = $_REQUEST['textarea'];
$stmt = $pdo->prepare("INSERT INTO t1 VALUES (?)");
$stmt->execute(array($ta));

What you are probably doing is

$pdo->prepare("INSERT INTO t1 VALUES ('" . $_REQUEST['ta'] . "')")->execute();

The input does not get escaped in that case.

Otros consejos

An SQL statement is code. When you build an SQL query with concatenation (or something else) you are doing code generation. And this code generation has the same problems when you generating php code (eval ("echo '$variable';");) or HTML code (<h1><?= $header?></h1>). There is no "data" in generated code, only code itself.

There are several ways to attempt to avoid unwanted behaviour.

  1. Packing/unpacking: use base64_encode/FROM_BASE64 for data variable for database, use base64_encode/base64_decode for eval, and htmlentities for html.

  2. Escaping: $PDO::quote() for data variable for database, some function for eval (for example return '\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $var) . '\'';)

  3. (bad) Removing 'dangerous' construction:(for example `$v = preg_replace('/UNION(?:\s+ALL)?\s+SELECT/i', '--', $a);) for database, strip_tags for HTML.

  4. Separate data from code: prepared statements for database, generate function and pass data to it for eval, using Document Object Model for building HTML.

So, the main idea of prepared statements is in separation data from a code. Therefore you must specify directly where the data is and where the code is.

The simplest way to insert with prepared statement is

$pdo->prepare('INSERT INTO `table` (`text`) VALUES(?);')->execute(array($text));

Remember, that prepared statements is prefered way to avoid troubles. If you could use prepared statements -- use it.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top