MySQL’s Shielded Data Transformation
There’s one big flaw in our previous MySQL insert statement: it’s open to SQL Injection Attacks. Prepared statements virtually eliminate that concern. You tell the SQL server what you’re intending to do and then you give it the data. For example, you can tell the server that you’re planning on inserting data. If you send a delete
statement disguised in your insert
statement, that doesn’t make sense and will not have the same kind of effect that it would without prepared statements.
https://blog.devgenius.io/php-p85-mysql-insert-51a9e3bfedd3
https://medium.com/geekculture/cybersecurity-p9-sql-injections-471de647e8d7
Recap
Our Author
class had an insert statement that accepted data and inserted it into the authors
table.
<?php
namespace Authors;
require_once("DB.php");
use Database\DB;
class Author
{
public function insert( array $data )
{
$sql = "INSERT INTO authors (first_name, last_name, email)
VALUES (
'" . $data['first_name'] . "',
'" . $data['last_name'] . "',
'" . $data['email'] . "')";
$db = new DB;
$status = $db->insert($sql);
$db->close();
echo $status;
}
}
Prepared Statement
Let’s see the anatomy of the prepared insert statement.
INSERT INTO authors (first_name, last_name, email) VALUES (?, ?, ?)
Those question marks aren’t accidental. This is the syntax for the prepared statement. It’s saying that we have three fields, first_name
, last_name
, and email
, and each of those fields will receive some data. It’s important to have three question marks to signify that there will be data bound to those three fields.
The steps are easy:
- Connect to the database
- Prepare the query
- Bind variables (data) to the query
- Execute the query
- Close the connection
<?php
namespace Authors;
require_once("DB.php");
use Database\DB;
class Author
{
public function insert( array $data )
{
$sql = "INSERT INTO authors (first_name, last_name, email)
VALUES (?, ?, ?)";
$db = new DB;
$mysqli = $db->_connection;
$statement = $mysqli->prepare( $sql );
$statement->bind_param("sss", $data['first_name'], $data['last_name'], $data['email']);
$statement->execute();
$statement->close();
$db->close();
}
}
Let’s digest it one line of code at a time.
- The
$data
array is passed as an argument. The$data
array has the following three keys:first_name
,$last_name
, and$email
. - The
$sql
statement is created that will be prepared. It’s just a string at this point. It’s just for some clarity and separation from the code below so that it doesn’t become too busy. - Instantiate the
DB
object. TheDB
object instantiates themysqli
object and stores it in the$_connection
property. We’re going to grab that and store it locally in our$mysqli
variable. - The
prepare
method is part of themysqli
object. We’re going to pass it theSQL
string so that it can prepare it. Once it’s prepared, it returns a new object, and we’re going to store that object as astatement
. - It is within this
statement
object that we can use thebind_param
method. Thebind_param
method does not belong to themysqli
object. Be careful of that trap. - The first argument that the
bind_param
method expects is the type of variable that will be bound. Since we’re binding 3 variables, it needs to know what are the types.sss
indicates that there will be three strings that are bound. - The next arguments are the variables that will be bound. This is the data that is sent through the
$data
array. - Finally, we call the
execute
method that’s part of thestatement
object. - We now have two objects that are “open.” We need to close the
statement
object and the$db
object. We can do that through the $db object since we have aclose()
method that states$db->_connection->close();
.
The Full Code
Below you can find the three files that interact with each other. The insert
method in our DB
class can be removed since we’re using prepared statements now. I’ll keep it in for now, but will probably remove it eventually.
<?php
require_once("Author.php");
use Authors\Author;
$data = [
"first_name" => "Sam",
"last_name" => "Johnson",
"email" => "sam@example.com"
];
$author = new Author;
$author->insert($data);
<?php
namespace Authors;
require_once("DB.php");
use Database\DB;
class Author
{
public function insert( array $data )
{
$sql = "INSERT INTO authors (first_name, last_name, email)
VALUES (?, ?, ?)";
$db = new DB;
$mysqli = $db->_connection;
$statement = $mysqli->prepare( $sql );
$statement->bind_param("sss", $data['first_name'], $data['last_name'], $data['email']);
$statement->execute();
$statement->close();
$db->close();
}
}
INFUSING TABLES WITH FRESH DATA ENERGY
When you have a database connection setup, the next logical step is to insert data into the tables. You handle that with the MySQL insert command.
MySQL’s Shielded Data Transformation
PHP – P86: mysql prepared statements
There’s one big flaw in our previous MySQL insert statement: it’s open to SQL Injection Attacks. Prepared statements virtually eliminate that concern.
MYSQL PREPARED STATEMENTS FOR BULK DATA INSERTS
PHP – P87: MYSQL INSERT MULTIPLE WITH PREPARED STATEMENTS
What if you wanted to insert multiple records with prepared statements. Do you need to keep binding variables for each set of data that you’re inserting? No.