Strings7 min readExamples run on PHP 8.5.10

quotemeta()

Learn how PHP 8.4 quotemeta() puts a backslash before a fixed set of meta characters, what it leaves alone, and why preg_quote() is the safer choice for regular expressions.

Signature

quotemeta(string $string): string

Purpose

quotemeta() returns a copy of a string in which a small, fixed set of "meta" characters is preceded by a backslash. The characters are:

. \ + * ? [ ^ ] ( $ )

The idea is to turn text that contains characters with special meaning in some pattern syntaxes into text that is read literally. It is a simple character-by-character transformation, so it is fast and predictable. It does not know about any particular pattern language, though, and that matters, as the sections below explain.

Signature

Parameters and defaults

  • $string: the input string. There are no other parameters and no default values.

The function is binary-safe, so bytes such as NUL or newlines pass through untouched. Only the eleven listed characters are changed.

Return value and failure cases

The function returns a new string. Every occurrence of a listed character gets one backslash in front of it, which means the result is at least as long as the input. If you pass an empty string you get an empty string back. Before PHP 8.0 this case returned false; since 8.0 the return type is always string.

There is no runtime failure mode for ordinary strings. Passing a value that cannot be coerced to a string, such as an array, throws a TypeError. Passing null to this non-nullable parameter is deprecated in modern PHP, so convert or default values before calling.

Example 1: quoting everyday punctuation

This example shows that the function escapes the plus sign, the question mark, the dollar sign, the dot and the parentheses, while letters, digits, spaces, the equals sign and the colon stay as they are.

Example
<?php

echo quotemeta('1+1=2? Cost: $5.00 (approx.)'), "\n";
Output
1\+1=2\? Cost: \$5\.00 \(approx\.\)

Each quoted character gains exactly one backslash, so 1+1 becomes 1\+1 and (approx.) becomes \(approx\.\).

Example 2: backslashes, brackets and carets

The backslash itself is on the list, so it is doubled. Square brackets and the caret are also escaped.

Example
<?php

$path = 'C:\\dir\\[a^b]';
echo quotemeta($path), "\n";
Output
C:\\dir\\\[a\^b\]

The input holds single backslashes (the PHP literal uses \\ to write one). Each one becomes two in the output, and the [, ^ and ] each get their own backslash.

Example 3: what it does not escape

The set is narrower than what regular expression engines treat as special. Braces, the pipe, the hyphen, the hash sign and the forward slash are all left alone. Compare it with preg_quote(), which is designed for PCRE patterns:

Example
<?php

$text = 'a{2}|b-c/d#e';
echo quotemeta($text), "\n";
echo preg_quote($text, '/'), "\n";
Output
a{2}|b-c/d#e
a\{2\}\|b\-c\/d\#e

The first line is unchanged because none of its characters are on the quotemeta() list. The second line has the quantifier braces, the alternation pipe, the hyphen, the slash delimiter and the hash escaped, so the string is safe to embed in a pattern.

Edge cases

  • Empty input: returns "", never false in PHP 8.x.
  • Already-escaped text: the function does not detect existing backslashes. Quoting twice doubles the backslashes again, so apply it exactly once to raw input.
  • Multibyte text: characters outside the list, including UTF-8 sequences, pass through unchanged. The function works on bytes, and all listed characters are single-byte ASCII, so multibyte sequences are not corrupted.
  • Newlines and NUL bytes: these are not escaped. If your target syntax treats them specially, you need other tools.
  • Length: the output length equals the input length plus the number of listed characters in the input.

Common mistakes

  1. Using it to build regular expressions. Because {, }, |, -, # and the delimiter are not escaped, a user-supplied string can still change the meaning of a pattern. Use preg_quote() and pass the delimiter as the second argument.
  2. Using it for SQL, HTML or shell safety. It is not an escaping function for any of those contexts. Use prepared statements, htmlspecialchars() or proper shell argument handling instead.
  3. Expecting it to undo itself. stripslashes() removes backslashes generally, but it is a blunt tool and will also remove backslashes that were part of the original text. Keep the raw value instead of trying to reverse quoting.
  4. Assuming it adds a trailing or leading backslash. It only inserts a backslash before each listed character; nothing is added at the ends.
  5. Forgetting that the input is read literally in your own source. In a single-quoted PHP literal, \\ is one backslash, which can make test strings look different from what you intended.
  • preg_quote(): escapes characters for PCRE patterns, with an optional delimiter.
  • addslashes(): adds backslashes before quotes, backslashes and NUL.
  • addcslashes(): escapes a caller-chosen character list in C style.
  • stripslashes() and stripcslashes(): remove backslash quoting.
  • htmlspecialchars() and htmlentities(): encode text for HTML output.
  • nl2br(): inserts HTML line breaks before newlines.

Recap

quotemeta() prefixes . \ + * ? [ ^ ] ( $ ) with a backslash and returns the new string. It is binary-safe, returns an empty string for empty input, and leaves every other byte alone. Because its character set is fixed and small, it is not a complete defense for regular expressions or any other injection-prone context. Reach for preg_quote() when you build patterns, and use context-specific escaping elsewhere.

Tested examples

Quoting everyday punctuation
<?php

echo quotemeta('1+1=2? Cost: $5.00 (approx.)'), "\n";
Output
1\+1=2\? Cost: \$5\.00 \(approx\.\)
Backslashes, brackets and carets
<?php

$path = 'C:\\dir\\[a^b]';
echo quotemeta($path), "\n";
Output
C:\\dir\\\[a\^b\]
Comparing quotemeta() with preg_quote()
<?php

$text = 'a{2}|b-c/d#e';
echo quotemeta($text), "\n";
echo preg_quote($text, '/'), "\n";
Output
a{2}|b-c/d#e
a\{2\}\|b\-c\/d\#e