Question

I am new to PHP and PDO. I have a very basic question about PDO and escaping of single quotes. I have assumed that escaping is not necessary but I still have had some problems.

For example...the following method in my database class creates a new object in the database. It is abstracted and all my class extend the database class.

public function  create() {
    $attributes = $this->attributes();
    $question_marks = array();
    foreach ($attributes as $key => $value) {
        $question_marks[] = "?";
    }
    $place_holder = array_intersect_key($attributes, get_object_vars($this));
    $place_holder = array_values($place_holder);
    $sql = "INSERT INTO ".static::$table_name." (";
    $sql .= join(", ", array_keys($attributes));
    $sql .= ") VALUES (";
    $sql .= join(", ", array_values($question_marks));
    $sql .= ")";
    $query = $handler->prepare($sql);
    $query->execute($place_holder);
}

If I create say for example a new User. I can enter the name James O'Reilly into the database without difficulty...

But when I want to use my update method....

public function update() {
   $attributes = $this->attributes();
   print_r($attributes);
    $attribute_pairs = array();
    foreach($attributes as $key => $value) {
      if(isset($value))
      $attribute_pairs[] = "{$key}='{$value}'";
    }
    $sql = "UPDATE ".static::$table_name." SET ";
    $sql .= join(", ", $attribute_pairs);
    $sql .= " WHERE id=". $this->id;
    $query = $handler->prepare($sql);
    $query->execute(array());
}

It fails. If I manually remove the quote from the name in the database, this Update method works so its this quotation which I expected to be escaped that seems to be the issue.

Is it completely unecessary to escape single quotes when using PDO, and if so have I set my update method up as shown above incorrectly.

To add to these problems I can't seem to get my error outout to work right...this is my set up which from reviewing the excellent Wiki here, I think is correct... but of course feel free to flame.

$opt = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,   PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);
$handler = new PDO('mysql:host=localhost;dbname=lung', 'root', 'fidelio', $opt);
Was it helpful?

Solution

Merely using prepare() does not automatically quote all your variables appropriately. All prepare() sees is a string, after you have interpolated variables into it. There is no way for it to tell what part of the string came from a variable and what part came from literal strings in your code.

You must use parameters for all values, instead of interpolating them into the string.

public function update() {
    $attributes = $this->attributes();
    print_r($attributes);
    $attribute_pairs = array();
    $attribute_values = array();
    foreach($attributes as $key => $value) {
        if(isset($value)) {
            $attribute_pairs[] = "`{$key}`=?"; // use parameter placeholders
            $attribute_values[] = $value; // collect the corresponding values
        }        
    }
    $sql = "UPDATE `".static::$table_name."` SET ";
    $sql .= join(", ", $attribute_pairs);
    $sql .= " WHERE id=?"; // use a placeholder here too
    $attribute_values[] = $this->id; // and add to the collected values
    $query = $handler->prepare($sql);
    $query->execute($attribute_values); // pass the values here
}

Note I also put your table name and column names in back-ticks to help delimit them in case you use reserved words or special characters in your SQL identifiers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top