Skip to content
Language guides Reviewed 2026-09-12

PHP secure coding

PHP applications need clear boundaries around request variables, database operations, file paths and HTML output. This guide uses PHP 8, PDO and MySQL. The same review applies to raw SQL in Laravel or Symfony applications even when most queries use a framework abstraction.

Use a prepared query

Assume $pdo is a configured PDO connection, $name is a length-validated string, and exceptions are handled without displaying database details. Configure PDO's driver options deliberately; for MySQL, native prepares can be selected with PDO::ATTR_EMULATE_PREPARES => false.

Unsafe: put request data into SQL text.

$stmt = $pdo->query(
    "SELECT id FROM customers WHERE name = '" . $name . "'"
);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Safer: use a named placeholder.

$stmt = $pdo->prepare(
    'SELECT id FROM customers WHERE name = :name'
);
$stmt->execute(['name' => $name]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

The value is bound independently of the query structure. A placeholder represents a complete value, not an arbitrary fragment of SQL. Table names and sort expressions need a server-owned allowlist. See the PHP manual for PDO::prepare.

A correct query still needs ownership or tenant constraints. Do not return a customer record solely because its identifier was guessed correctly. Use a database account with limited permissions and avoid logging credentials or raw sensitive request bodies.

Check the fix

In a disposable database, create a record named O'Reilly and another named Demo Shop. Confirm that each lookup returns only its matching record and that an unknown name returns no results. Verify that a connection error becomes the application's controlled error response rather than a stack trace in HTML.

For templates, choose output escaping for the exact context. Treat file include paths and calls to unserialize() as separate high-risk boundaries; parameterizing SQL does not protect them. Review SQL injection, XSS, file path injection and insecure deserialization. OWASP's SQL guidance explains additional protections.

These samples illustrate targeted fixes. Framework, driver and scanner settings affect the checks applicable to a particular project.