SQL injection remains one of the most dangerous web vulnerabilities, but Laravel’s built‑in tools make it surprisingly simple to prevent SQL injection in Laravel—if you know the right practices. In this guide, we’ll show you real‑world attack scenarios and how to block them using Eloquent, query builders, and parameter binding. By the end, your database will be safe from even the most crafted malicious inputs.
What Is SQL Injection and Why Laravel Developers Must Care?
SQL injection occurs when an attacker manipulates a query by inserting unintended SQL commands through user inputs. For example, a login form that uses string concatenation can be tricked with ' OR '1'='1. Without proper protection, an attacker can steal, alter, or delete your entire database.
Laravel, by default, protects you—but only when you use its tools correctly. The most reliable way to prevent SQL injection in Laravel is to always use Eloquent ORM or the query builder with parameter binding. Let’s see exactly how.
Real‑World Example 1: The Dangerous Raw Query (What NOT to Do)
Imagine you’re building a search feature for a products table. A junior developer might write:
// VULNERABLE CODE – DO NOT USE
$search = $_GET['search'];
$results = DB::select("SELECT * FROM products WHERE name LIKE '%$search%'");
An attacker could enter ' OR '1'='1' OR name LIKE '% as the search term, turning the query into:
This returns every product in the database. Worse, they could use '; DROP TABLE products; -- to delete your table.
How to fix it: Never use raw concatenation. Laravel’s query builder automatically uses parameter binding. The safe version:
$search = request('search');
$results = DB::table('products')->where('name', 'like', '%'.$search.'%')->get();
Laravel escapes $search automatically. This is your first step to prevent SQL injection in Laravel.
For an external reference on SQL injection patterns, check out OWASP SQL Injection Prevention Cheat Sheet.
Real‑World Example 2: Using Eloquent Safely with User Input
Many developers think using Eloquent alone is always safe. But there’s a catch. Look at this example:
// SAFE – Eloquent with parameter binding
$email = request('email');
$user = User::where('email', $email)->first();
This is safe because Laravel binds $email as a parameter. However, if you ever use DB::raw() inside an Eloquent query, you reintroduce the vulnerability.
The right way to prevent SQL injection in Laravel with Eloquent:
- Always pass user input as values, never as column names or table names.
- If you must use raw expressions, use
DB::raw()only with whitelisted values.
For dynamic column names (e.g., sorting by user input), never concatenate. Instead, validate against a whitelist:
$allowedColumns = ['id', 'name', 'email'];
$sortBy = in_array(request('sort'), $allowedColumns) ? request('sort') : 'id';
$users = User::orderBy($sortBy)->get();
Learn more about secure coding in our Laravel security best practices guide.
Real‑World Example 3: Raw Queries Done Right
Sometimes you need raw SQL for complex reports. Laravel provides a safe way using parameter binding. For example, a dangerous raw query:
// STILL VULNERABLE
DB::select("SELECT * FROM users WHERE age > $age");
Fix it with bindings:
Laravel escapes the :age placeholder automatically. You can also use positional ? bindings:
This method lets you prevent SQL injection in Laravel even when writing custom SQL.
For deeper technical details on PDO bindings (which Laravel uses internally), see PHP PDO Prepared Statements.
Real‑World Example 4: Defending Against Second‑Order Injection
Second‑order injection happens when data is stored safely (e.g., via Eloquent) but later used unsafely in a raw query. Consider this:
- A user registers with the name
Robert'); DROP TABLE sessions; -- - Eloquent inserts it safely (escaped).
- Months later, an admin runs a raw report using that name:
$name = User::find($id)->name; // This value is clean in DB but contains dangerous SQL
DB::statement("DELETE FROM logs WHERE username = '$name'"); // VULNERABLE
Even though the input was originally safe during insertion, the second query concatenates it. Always treat any data from the database as potentially unsafe when used in a raw SQL context.
Fix: Use parameter binding again:
DB::statement("DELETE FROM logs WHERE username = ?", [$name]);
This is a subtle but critical lesson in how to prevent SQL injection in Laravel comprehensively.
Bonus: Validation and Input Sanitization (Defense in Depth)
While parameter binding stops SQL injection, you should still validate inputs. Laravel’s validation rules like string, max, and regex reduce unexpected characters. For example:
request()->validate([
'search' => 'string|max:100|regex:/^[a-zA-Z0-9 ]+$/',
]);
However, remember: validation is not a substitute for parameter binding. It’s an extra layer. Always bind parameters.
For a complete checklist, read our Laravel input validation and security tutorial.
Summary: Your SQL Injection Prevention Checklist
To prevent SQL injection in Laravel in every project, follow these rules:
- Use Eloquent or the query builder for 95% of your database work.
- Never concatenate user input directly into a raw SQL string.
- Use parameter binding (
?or:name) for any raw query. - Whitelist dynamic column/table names – never accept them directly from users.
- Treat stored data as unsafe when used in later raw queries (second‑order prevention).
Conclusion
SQL injection is entirely preventable when you leverage Laravel’s built‑in protections. By always using parameter binding, avoiding raw concatenation, and validating inputs, you can confidently prevent SQL injection in Laravel even in complex, real‑world applications. Start by auditing your existing queries today—your database will thank you.
Secure your Laravel app today and stay one step ahead of attackers. For more details or personalized help, feel free to contact me.
