Search code examples
phpmysqlpdo

Does pdo escape statements or not?


I have this PDO wrapper

private function cleanup($bind) {
    if(!is_array($bind)) {
        if(!empty($bind))
            $bind = array($bind);
        else
            $bind = array();
    }
    return $bind;
}

public function run($sql, $bind="") {
    $this->sql = trim($sql);
    $this->bind = $this->cleanup($bind);
    $this->error = "";
    array_push($this->qs, $sql);

    try {
        $pdostmt = $this->prepare($this->sql);
        if($pdostmt->execute($this->bind) !== false) {
            if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql))
                return $pdostmt->fetchAll(PDO::FETCH_ASSOC);
            elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql))
                return $pdostmt->rowCount();
        }
    } catch (PDOException $e) {
        $this->error = $e->getMessage();
        $this->debug();
        return false;
    }
}

I had no problems with this since I started using it a couple of years back and now I'm getting an error message because a string is not escaped. Maybe I never worked with a scenario like this.

Here's the SQL statement that is causing the problem

$db->run("SELECT region_id FROM region WHERE name = '$name'");

where $name is Hawke's Bay. I was under the impression that PDO escapes strings, seems like I was wrong. Any ideas how I can fix this issue?


Solution

  • There are 2 false assumptions that led you to this question

    1. Escaping is a thing that makes your query correct one.
    2. PDO does this "escaping" whatever "magic" way, knowing somehow what to escape.

    Unfortunately, both assumptions are wrong.

    As a matter of fact, escaping required for the SQL strings only. It has nothing to do with PDO, prepared statements, safety and such. Once you are going to put a string literal into query - it must have special characters escaped.
    But once you aren't - no escaping would be good.

    Regarding PDO, you want it not to "escape" but to process placeholders in your query. This is how the whole thing works. Using placeholders you are telling PDO to format corresponding values properly. While such a formatting involves not just escaping but many more different measures.

    So, it have to be something like this

    $db->run("SELECT region_id FROM region WHERE name = :name", array(':name' => $name));
    

    this way PDO will treat $name as a string and format it accordingly.

    Though I am not sure about "cleanup" function if it works properly and why it is used at all.