15

Where and when do you use the quote method in PDO? I'm asking this in the light of the fact that in PDO, all quoting is done by the PDO object therefore no user input should be escaped/quoted etc. This makes one wonder why worry about a quote method if it's not gonna get used in a prepared statement anyway?

Average Joe
  • 4,521
  • 9
  • 53
  • 81
  • indeed don't worry about the "quote method" (dunno what's that) – dynamic Feb 12 '12 at 16:32
  • 3
    There is no "quote method" in PDO. I have a hard time figuring out what you are asking. – Tomalak Feb 12 '12 at 16:32
  • 1
    I'd say "never". See also the note in the manual, that basically says: if you want to use it, don't. http://php.net/manual/en/pdo.quote.php (@tomalak : I suspect that method is meant?) – Nanne Feb 12 '12 at 16:33
  • @Nanne Ah! I stand corrected. There is a quote method in PDO. It's just that it doesn't make a lot of sense. Now I understand the question, too. – Tomalak Feb 12 '12 at 16:36
  • In the PHP PDO docs for [`prepare`](http://php.net/manual/en/pdo.prepare.php), one user comments: "If you are only submitting one query, using PDO::query() with PDO::quote() is much faster." So at least someone thinks this method makes sense. – Blazemonger Dec 17 '12 at 16:34

4 Answers4

15

When using Prepared Statements with PDO::prepare() and PDOStatement::execute(), you don't have any quoting to do : this will be done automatically.

But, sometimes, you will not (or cannot) use prepared statements, and will have to write full SQL queries and execute them with PDO::exec() ; in those cases, you will have to make sure strings are quoted properly -- this is when the PDO::quote() method is useful.

Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • is it like Ross's code above - where you will not ( and cannot ) use prepared statements? – Average Joe Feb 12 '12 at 19:18
  • 4
    Actually, I don't think that the `quote` method's role is to quote identifiers *(like columns names)* : it's purpose is to quote string values *(for instance : escaping strings that could be in those strings)* – Pascal MARTIN Feb 12 '12 at 19:28
  • not sure what you mean by your last sentence. I think quote is only used where the sql identifies are such as column names, asc, desc keywords, table names etc. – Average Joe Feb 12 '12 at 22:29
  • No : quote is used to quote strings (values) – Pascal MARTIN Feb 13 '12 at 05:28
  • 1
    Downvote because PDO::prepare() does not escape anything passed into it. Parameters are escaped when they are bound with one of the bind...() calls and you can only bind values, not identifiers. – CLo May 30 '12 at 11:24
  • 2
    +1 this is the correct answer. Quote is useful for interpolating string values, but it's usually preferable to use query parameters. – Bill Karwin Aug 18 '13 at 02:19
  • Not true, PDO (ODBC) will crash even when using prepared statements. Searching for O'Neil will crash. – Manny Ramirez Oct 17 '19 at 18:26
  • If you are going for the theoretically safest code possible, it is better to avoid combining `PDO::exec()` with the need to escape strings via `PDO::quote()`. If you need to escape strings, find a way to use prepared statements instead. There is the possibility of a bug in the code that escapes the strings for you. The concept of "properly" escaping strings is fundamentally flawed, there is no way for the library authors to know if they handled all cases properly or not. Using prepared statements does not escape strings for you under the hood, it runs the query in a fundamentally safer way. – still_dreaming_1 Feb 24 '22 at 15:46
0

The PDO system does not have (as far as I can find) any mechanism to bind an array variable in PHP into a set in SQL. That's a limitation of SQL prepared statements as well... thus you are left with the task of stitching together your own function for this purpose. For example, you have this:

$a = array(123, 'xyz', 789);

You want to end up with this:

$sql = "SELECT * FROM mytable WHERE item IN (123, 'xyz', 789)";

Using PDO::prepare() does not work because there's no method to bind the array variable $a into the set. You end up needing a loop where you individually quote each item in the array, then glue them together. In which case PDO::quote() is probably better than nothing, at least you get the character set details right.

Would be excellent if PDO supported a cleaner way to handle this. Don't forget, the empty set in SQL is a disgusting special case... which means any function you build for this purpose becomes more complex than you want it to be. Something like PDO::PARAM_SET as an option on the binding, with the individual driver deciding how to handle the empty set. Of course, that's no longer compatible with SQL prepared statements.

Happy if someone knows a way to avoid this difficulty.

Tel
  • 1
  • Perhaps [this example](https://phpdelusions.net/pdo#in) with an array and `IN` might be useful to handle the task? – Paul T. Jan 23 '18 at 01:05
  • Interesting approach but when you want named parameters (most people do) it starts looking a bit messy and hard to understand and gets down to a foreach loop anyway. Then there's still the special case when the array has count of zero (i.e. empty set).I guess it proves you can avoid PDO::quote() if you really wanted to. – Tel Jan 23 '18 at 04:26
0

While this may not be the only use-case it's the only one I've needed quote for. You can only pass values using PDO_Stmt::execute, so for example this query wouldn't work:

SELECT * FROM tbl WHERE :field = :value

quote comes in so that you can do this:

// Example: filter by a specific column
$columns = array("name", "location");
$column = isset($columns[$_GET["col"]]) ? $columns[$_GET["col"]] : $defaultCol;

$stmt = $pdo->prepare("SELECT * FROM tbl WHERE " . $pdo->quote($column) . " = :value");
$stmt->execute(array(":value" => $value));

$stmt = $pdo->prepare("SELECT * FROM tbl ORDER BY " . $pdo->quote($column) . " ASC");

and still expect $column to be filtered safely in the query.

Ross
  • 46,186
  • 39
  • 120
  • 173
  • +1 for the use case. IMO nobody should ever be in the position to actually need this. Whenever actual user input is used to build SQL there's something massively wrong with the application design anyway. (Corollary: If user input has been thoroughly sanitized there is no need to quote `$column` anymore.) – Tomalak Feb 12 '12 at 16:40
  • @ross. I see. so that's for the other parts of the query – Average Joe Feb 12 '12 at 17:19
  • @tomalak i see your point, but his example could have showcased the order by area which is perfectly normal for users' to modify... (i.e, order by bestprice asc or desc etc ). see my other question which I had started before I got the answer to (this one)[ http://stackoverflow.com/questions/9250821/recommended-way-to-safely-use-a-user-specificed-order-by-in-a-sql-statement] – Average Joe Feb 12 '12 at 17:21
  • @John True. For these cases I usually have a set of well-prepared fixed strings that I put into the query verbatim and a switch statement that chooses from them. No user input ever goes into SQL. – Tomalak Feb 12 '12 at 17:29
  • @Tomalak Yeah, it wasn't an ideal situation at the time, I've updated my answer to include a restricted-column set and an ORDER BY example. – Ross Feb 12 '12 at 17:43
  • @Ross That's exactly my point: Once you've restricted the values to a valid selection, there is no need to quote them. – Tomalak Feb 12 '12 at 17:55
  • @Tomalak In my case I'm writing a data access layer that will not know the database structure until it is called. As I don't know who will be writing the code that uses this, I'm designing it to handle all the escaping internally. – CLo May 30 '12 at 11:30
  • This answer better be deleted. – Your Common Sense Aug 18 '13 at 00:49
  • 17
    -1 This answer is wrong. PDO::quote() does not add identifier delimiters, it adds single-quotes. So it can't be used for table names or column names. It's only for string values or date values. – Bill Karwin Aug 18 '13 at 02:20
  • I've just spent nearly two hours determining what magic incantation I need to make PDO visible in my code. I finally found it, in /vendor/larave/\framework/src/Illuminate/Database/Connectors/Connector.php. Please, folks, call out these use directives when you craft your examples! – David A. Gray Jan 25 '18 at 08:30
-4

A bit late anwser, but one situation where its useful is if you get a load of data out of your table which you're going to put back in later.

for example, i have a function which gets a load of text out of a table and writes it to a file. that text might later be inserted into another table. the quote() method makes all the quotes safe.

it's real easy:

$safeTextToFile = $DBH->quote($textFromDataBase); 
Lan
  • 1,874
  • 2
  • 20
  • 37
  • 1
    it doesn't "make quotes safe". when you insert data into table, use prepared statements – Your Common Sense Aug 18 '13 at 00:50
  • i didn't say it does. im saying if you pass a string through the quote method, it returns the string with the quotes escaped. please remove your down vote. thanks – Lan Aug 18 '13 at 09:59
  • 1
    ` the quote() method makes all the quotes safe.` I can read right above if my eyes don't fail me. And your definition is still wrong, not to mention it is outdated and error-prone. – Your Common Sense Aug 18 '13 at 10:06
  • your first comment said "it doesn't "make quotes safe". when you insert data into table" - i never said to use it WHEN you insert into table. i said it returns a string with the quotes sorted, you can store that string and use it later. thats how i have used it and it works perfectly. im not an expert, so please enlighten us, what it does/used for. but you can try it, open a connection, and run a string through the quote method, it will return the string with the quotes escaped. simple – Lan Aug 18 '13 at 10:42
  • Sorry bud, but " store that string and use it later" makes absolutely no sense. Data have to be formatted right before use and nowhere else. Speaking of "what it used for" the answer is fairly simple - it shouldn't be used at all. But a prepared statement have to be always used instead. – Your Common Sense Aug 18 '13 at 10:51
  • use it kind of instead of addslashes(). i have a function which mimics the mysqldump command. it writes a file will all my data in it. i use quote() to escape the text from the individual rows. so later, if i need to restore my tables with my made backup file, all my inserts are quote safe. – Lan Aug 18 '13 at 11:08