I am writing a basic CRUD application to get my head around PHP. I am a little confused as to what exactly the following code is doing. I understand the general concept of it but I am not 100% sure of the logic going on.
I am hoping someone might be able to help me understand it a bit better?
This is my script
<?php
//Establish connection to db
require_once 'includes/db.php';
//Array for validation
$errors = array();
//Sanitize the fields to ensure db integrity.
$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_STRING);
$release_date = filter_input(INPUT_POST, 'release_date', FILTER_SANITIZE_NUMBER_INT);
$publisher = filter_input(INPUT_POST, 'publisher', FILTER_SANITIZE_STRING);
$system = filter_input(INPUT_POST, 'system', FILTER_SANITIZE_STRING);
$rating = filter_input(INPUT_POST, 'rating', FILTER_SANITIZE_NUMBER_INT);
$num_players = filter_input(INPUT_POST, 'num_players', FILTER_SANITIZE_NUMBER_INT);
if($_SERVER['REQUEST_METHOD']=='POST'){
//Validate the form
if(empty($title)){
$errors['title'] = true;
}
if(empty($release_date)){
$errors['release_date'] = true;
}
if(empty($publisher)){
$errors['publisher'] = true;
}
if(empty($system)){
$errors['system'] = true;
}
if(empty($rating)){
$errors['rating'] = true;
}
if(empty($num_players)){
$errors['num_players'] = true;
}
//If no errors
if(empty($errors)){
//Build SQL Statement
$sql = $db->prepare("INSERT INTO videogames SET title = :title, release_date = :release_date, publisher = :publisher, system = :system, rating = :rating, num_players = :num_players");
//Bind values
$sql -> bindValue(':title', $title, PDO::PARAM_STR);
$sql -> bindValue(':release_date', $release_date, PDO::PARAM_STR);
$sql -> bindValue(':publisher', $publisher, PDO::PARAM_STR);
$sql -> bindValue(':system', $system, PDO::PARAM_STR);
$sql -> bindValue(':rating', $rating, PDO::PARAM_INT);
$sql -> bindValue(':num_players', $num_players, PDO::PARAM_INT);
//Execute SQL
$sql -> execute();
//Redirect back to homepage
header('Location: index.php');
exit();
}
}
?>
I am a little confused as to what this line of code is doing:
$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_STRING);
Is it assigning the value in the input field of the form to the $title variable?
Also this line:
$sql -> bindValue(':title', $title, PDO::PARAM_STR);
I read in the documentation that this
Binds a value to a corresponding named or question mark placeholder in
the SQL statement that was used to prepare the statement.
If I am storing the data already in the $title variable then is there another way to prepare my SQL statement?
I'd appreciate any help, as I am trying to expand my knowledge of PHP. Many thanks!
Question 1 - filter_input
I am a little confused as to what this line of code is doing:
$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_STRING);
Is it assigning the value in the input field of the form to the $title variable?
Yes.
filter_input was introduced in PHP 5. What this line of code is doing is grabbing the input variable ($_POST['title']), and then applying a SANITIZE method on it, that is; "Strip tags, optionally strip or encode special characters."
Question 2 - bindValue
Also this line:
$sql -> bindValue(':title', $title, PDO::PARAM_STR);
If I am storing the data already in the $title variable then is there another way to prepare my SQL statement?
I don't actually understand this question, however I'll try my best.
This is a PDO method to bind a value to a prepared query. Effectively, it does this:
Hey MySQL, here's a query I need you to run
Query these tables
Get these columns back
MySQL does this
Hey MySQL, remember that query I asked you to run? Here's the values to filter the result set
You can read more about preparing and binding here: http://use-the-index-luke.com/sql/where-clause/bind-parameters
Another way in which you could prepare the query is the use of mysqli, but the logic is the same.
This question was asked a year ago. I didn't revive it, OP edited his question and it was bumped. I see nothing wrong answering a question if OP still shows interest in an answer (by bumping) no matter the age of the question
Related
I want to save the data with $_POST method to the database using PDO with PHP. I wrote the code, but it gave me an error. Is there anyone who can figure this out?
macex.php
function daireekle($daire_no,$dpass,$daire_statu,$daire_adi,$daire_soyadi){
$sql ="insert into users (KULLANICIADI,SIFRE,TIPI,ADI,SOYADI) values ('$daire_no','$dpass','$daire_statu','$daire_adi','$daire_soyadi')";
$insert =$this->connection->query($sql);
}
Blok.html
<?php
$sinif = new macex();
if ($_POST) {
$daire_no = $_POST['daireno'];
$daire_adi = $_POST['daireadi'];
$daire_soyadi = $_POST['dairesoyadi'];
$daire_statu = $_POST['statu'];
$dpass = $_POST['dpass'];
$sinif->daireekle('users', ['KULLANICIADI', 'SIFRE', 'TIPI', 'ADI', 'SOYADI'], [$daire_no, $dpass, $daire_statu, $daire_adi, $daire_soyadi]);
}
?>
Your code is a bit difficult to understand, in terms of structure, but you're definitely misusing PDO by injecting unsanitized POST data.
If I were to attempt to convert your sample into something workable, I would suggest the following amendments:
(Note: Assuming $this->connection-> is your PDO object)
Blok.html
(not sure why you've called this PHP file Blok.html)
<?php
$sinif = new macex();
if ($_POST) {
$sinif->daireekle( $_POST );
}
?>
macex.php
function daireekle( $postArray ){
// Parameterised PDO will mostly prevent SQL Injection, but it's still best practice
// to validate and sanitize your inputs, especially if they are coming from the user
$daire_no = $postArray ['daireno'];
$daire_adi = $postArray ['daireadi'];
$daire_soyadi = $postArray ['dairesoyadi'];
$daire_statu = $postArray ['statu'];
$dpass = $postArray ['dpass'];
// Define the query with positional params
$sql = 'INSERT INTO users (KULLANICIADI, SIFRE, TIPI, ADI, SOYADI) VALUES (?,?,?,?,?)';
// Create an array of your params in the order they apply to the query
$paramsArray = array('$daire_no','$dpass','$daire_statu','$daire_adi','$daire_soyadi');
// Prepare the parameterised query
$query = $this->connection->prepare($sql);
// Execute the INSERT query with the parameters
$query->execute($paramsArray);
}
You could of course use different variations on the above, included named parameters, but it's conciser to explain as per the above.
The code below makes a query and then loops through those results. I am having a hard time understanding what "?" is in that query and how to make "?" dynamic.
It assume that name = "?". I have changed ? to a variable I added in the function $ad_id and that still does not work. I basically need to query the DB only WHERE name = a variable. But this simple solution does not work. The commented line is what I replaced.
Any help will be greatly appreciated. Incase you are wondering this is the code I am trying to make dynamic and not just pulling all images in the table:
https://github.com/blueimp/jQuery-File-Upload/wiki/PHP-MySQL-database-integration
protected function set_additional_file_properties($file) {
parent::set_additional_file_properties($file);
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$ad_id = '1';
//$sql = 'SELECT `id`, `type`, `title`, `description` FROM `'
//.$this->options['db_table'].'` WHERE `name`=?';
$sql = 'SELECT id, type, title, description FROM '.$this->options['db_table'].' WHERE name = '.'$ad-id'.';
$query = $this->db->prepare($sql);
$query->bind_param('s', $file->name);
$query->execute();
$query->bind_result(
$id,
$type,
$title,
$description
);
while ($query->fetch()) {
if ($description == $ad_id){
$file->id = $id;
$file->type = $type;
$file->title = $title;
$file->description = $description;
};
}
}
}
In this example, the SQL query is using bound parameters. This means that you create the string for the SQL query, and put a placeholder in for each variable - the placeholder is the '?' character you mentioned. Then the following two lines:
$query = $this->db->prepare($sql);
$query->bind_param('s', $file->name);
The first line sends the query to the database, and the second line sends the parameters that need to be bound into the placeholder sites (where those question marks were in the query string). So if you want to change the variable that is inserted into the query, you should change the bind_param call.
Check out the documentation for bind_param, but basically the 's' specifies a string parameter, and the second argument is the variable itself.
Hopefully that gives you enough insight into what is going on here to change the code to do exactly what you want.
I have been getting an error with this code.
$Database = new Database('localhost','root','password','Db');
$Statement = $Database->prepare("INSERT INTO User VALUES(:ID,:FirstName,:MiddleName:LastName,:RegisteredDate")
$Array_Bind = array(
'ID'=>$ID,
'FirstName'=>$FirstName,
'MIddeName'=>$MiddleName,
'LastName'=>$LastName
'RegisteredDate'=>$Date
)
foreach($Array_Bind AS $Key=>$value){
$Statement->bindParam(':' .$Key, $value)
}
if($Statement->execute()){
echo 'Successfully inserted into the database';
}else{
echo 'could not insert into database';
};
The following have been noted IF the $ID (PrimaryKey) is NOT by DEFAULT an AUTO-INCREMENTING value in the MySQL Database.
ALL Fields except DATETIME Fields gets the value of the last element in the array when inserted into the database.
i.e.
ID = $LastName
FirstName = $LastName
MiddleName = $LastName
LastName = $LastName
RegisteredDate = $RegisteredDate
The same error is outputted when bindValue is used.
So I ended up using
if($Statement->execute($Array_Bind)){
echo 'Successfully inserted into the database';
}else{
echo 'could not insert into database';
};
QUESTIONS
It is recommended to use execute($array_Bind) assuming all data have been sanitize as against using bindParam or bindValue in this scenario?
If Not is there a way to use bindParam or bindValue and arrays?
Is this a bug or wrong coding architecture.
I noticed you had a typo in the placeholder name. Don't know if this will sort the problem
$Statement = $Database->prepare("INSERT INTO User VALUES(:ID,:FirstName,:MiddleName:LastName,:RegisteredDate")
$Array_Bind = array(
'ID'=>$ID,
'FirstName'=>$FirstName,
'MIddeName'=>$MiddleName,
'LastName'=>$LastName
'RegisteredDate'=>$Date
)
You use a placeholder MIddeName but in your query you use MiddleName
Change this
'MIddeName'=>$MiddleName,
to this
'MiddleName'=>$MiddleName,
You need to check your premises. Then double check. Then check documentation.
with bindParam it is not a bug but essential feature.
with bindValue it never happen
of course passing array into execute() is preferred, due to overall sanity and amount of code compared to other methods.
I know this topic has been discussed a lot in stackoverflow but I've read all topics I couldn't find a solution.
I've got this function which should update a mysql database. It justs do not do nothing, and do not show any errors. As you see I use PDO. I've seen lots of question similar to mine in stackoverflow, and tried their solution but none of them seems to work.
I've checked that all variables that I pass to this function arrive and are correct.
public function updateValues($coreID, $table, $name, $time){
if ($this->databaseConnection()) {
$query_edit_user_name = $this->db_connection->prepare("UPDATE :tableT SET time = :timeT, name = :nameT WHERE id = :coreID");
$query_edit_user_name->bindValue(':coreID', trim($coreID), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':tableT', trim($table), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':nameT', trim($name), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':timeT', trim($time), PDO::PARAM_INT);
$query_edit_user_name->execute();
}
}
I've been trying to add´´ or '' to different rows names or values but didn't worked. The only way it "works" is if there isn't a single PDO parameter:
$query_edit_user_name = $this->db_connection->prepare("UPDATE table1 SET time = '55', name = 'name1' WHERE id = 'core2'");
Any ideas?
You can't use a bind value or parameter for a table name.
$query_edit_user_name = $this->db_connection->prepare("UPDATE :tableT SET time...
^^^^^^^
Try this instead:
public function updateValues($coreID, $table, $name, $time){
if ($this->databaseConnection()) {
$query_edit_user_name = $this->db_connection->prepare("UPDATE `$table` SET time = :timeT, name = :nameT WHERE id = :coreID");
$query_edit_user_name->bindValue(':coreID', trim($coreID), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':nameT', trim($name), PDO::PARAM_STR);
$query_edit_user_name->bindValue(':timeT', trim($time), PDO::PARAM_INT);
$query_edit_user_name->execute();
As has been pointed out in the comments, a dynamic table name is open to a possible injection, depending on where the table name is derived from.
Either, escape the table name before preparing the statement with something like:
$table = str_replace(array('\\',"\0" ,'`'), '', $table);
Or, use a whitelist method:
$allowed = array('table1', 'table2');
if (in_array($table, $allowed)) {
// prepare and execute query
}
A few keep telling me that my code for updating data in my mysqli query is extremely insecure. Actually, several people on this site. So I would like to know what they say would secure my code below so it is secure when updating my database. I would like to know how the would secure my mysqli query.
Okay, in my code for my database entries, this is what I do. Let me start by saying that I always send via POST method to avoid browser url complications.
When I get the POST data, this is my code.
$ID = 1;
$DATA = htmlentities(addslashes($_POST['data']));
$FIELD = "lifename";
$DBQUERY = "UPDATE `lifetable` SET `$FIELD` = '$DATA' WHERE `id` = $ID";
$DBRESULT = $MYSQLI->query($DBQUERY);
I am currently using this on my local site.
How is this unsafe if I have escaped all quotes, all slashes, all ampersands (from javascript through ajax) and all semi colons? How is this vunerable?
So can you tell me what I should change when adding information to my database.
Thanks
PS ... I am using mysqli and will continue to use it. Thanks
A few suggested that I change from mysqli to pdo, but I am not willing to completely 100% change how I access data from my databases. Someone posted another link before about prepare and bind_param and this is what I am going to use. So thank you.
This is now my code, and binding params is supposed to make it so that each param is only for the one part of my query and can not be for anything else, nothing else at all.
$DBQUERY = "UPDATE `lifetable` SET `lifename` = ? WHERE `id` = ?"; // EACH ? IS A PART OF bind_param BELOW IN ORDER AFTER TYPE.
$STMT = $MYSQLI->prepare($DBQUERY);
$STMT->bind_param('si', $DATA, $ID); // THIS MAKES SURE THAT THE VARIABLES ARE ONLY USED FOR THERE PLACE HERE AND NOTHING ELSE. ? in order.
$DATA = htmlentities($_POST['data']); // I STILL USE MY CODE HERE TO REMOVED ANY OTEHR CHARACTERS, JUST INCASE. AND BEFORE IT GETS HERE, IT USES encodeURIComponent TO OUTPUT FROM AJAX.
$ID = $COLUMN[1];
$STMT->execute();
$STMT->close();
My code worked before and it works now, just more secure, or so I am told.
Use PDO Class like:
$db = new PDO('mysql:host=localhost;dbname=<SOMEDB>', '<USERNAME>', 'PASSWORD');
$query = $db->prepare('UPDATE `lifetable` SET :FIELD = :DATA WHERE `id` = :ID');
$query->execute(array(
':FIELD' => $field,
':DATA' => $data,
':ID' => $id
));
$query->commit();
For more info Are there good tutorials on how to use PDO?
i think your security lies in the SQL injection, and the best way i know to make the query secure is using mysql_real_escape_string on the var. Here an example taken from php.net
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$city = $mysqli->real_escape_string($city);
$mysqli->query("INSERT into myCity (Name) VALUES ('$city')")
you can apply the same procedure to your query
$ID = 1;
$DATA = $MYSQLI->real_escape_string($_POST['data']));
$FIELD = "lifename";
$DBQUERY = "UPDATE `lifetable` SET `$FIELD` = '$DATA' WHERE `id` = $ID";
$DBRESULT = $MYSQLI->query($DBQUERY);
I edited the above because I forgot the quotes for lifename in my question. They should be there as they are in my original code.
now tour query should be secure :D
here the reference to php.net documentation :
http://cn2.php.net/manual/en/mysqli.real-escape-string.php