Logic for inserting form with/without optional inputs into MySQL - php

Using: Brackets Html editor, MySQL Workbench
Simplified, I have a database with these tables
(main table) person
idperson PK NN UN AI
*fk_job NN UN (foreign key refering to idjob)
fn NN
ln NN
job
idjob PK NN UN AI
jobname NN
adress
idadress PK NN UN AI
*fk_person NN UN (foreign key refering to idperson)
adress NN
and this form. In the form it is required to fill on one adress, and optional to fill in a second one.
<?php
$con = new mysqli("localhost","user","password","database");
if ($con->
connect_error) {
die('Error : ('. $con->connect_errno .') '. $con->connect_error .'');
}
$job_sql = "SELECT idtype, typename FROM type;";
$job_data = $con->query($job_sql);
//insert if(isset()) here
$con->close();
?>
<form method="post">
<select name="typeSlc" required>
<option disabled selected>_</option>
<?php while($row = mysqli_fetch_array($job_data)) { ?>
<option value="<?php echo $row['jobid'];?>"><?php echo $row['jobname'];?></option>
<?php } ?>
</select>
<input name="fnTxt" required type="text">
<input name="lnTxt" required type="text">
<input name="adressTxt" required type="text">
<input name="cityTxt" required type="text">
<input name="opt_adressTxt" type="text">
<input name="opt_cityTxt" type="text">
<input name="submit" value="submit" type="submit">
</form
Issue:
I want to send a transaction with one batch of queries to the server when 'opt_adress' isset and another when it is not, namely:
if(isset($_POST['submit'])) {
if(isset($_POST['opt_adress'])) {
$sql = sprintf ("BEGIN;
INSERT INTO person (fk_job, fn, ln)
VALUES (%s, '%s', '%s');
SELECT LAST_INSERT_ID() INTO #id;
INSERT INTO adress (fk_person, adress)
VALUES (#id, '%s');
INSERT INTO adress (fk_person, adress, city)
VALUES (#id, '%s', '%s');
COMMIT;",
$con->real_escape_string($_POST['jobSlc']),
$con->real_escape_string($_POST['fnTxt']),
$con->real_escape_string($_POST['lnTxt']),
$con->real_escape_string($_POST['adressTxt']),
$con->real_escape_string($_POST['cityTxt']),
$con->real_escape_string($_POST['opt_adressTxt']),
$con->real_escape_string($_POST['opt_cityTxt']))
;
} else {
$sql = sprintf ("BEGIN;
INSERT INTO person (fk_job, fn, ln)
VALUES (%s, '%s', '%s');
INSERT INTO adress (fk_person, adress, city)
VALUES (LAST_INSERT_ID(), '%s', '%s');
COMMIT;",
$con->real_escape_string($_POST['jobSlc']),
$con->real_escape_string($_POST['fnTxt']),
$con->real_escape_string($_POST['lnTxt']),
$con->real_escape_string($_POST['adressTxt']),
$con->real_escape_string($_POST['cityTxt']))
;
}
$con->query($sql);
header("Location: samepage.php");
When I try to run the query it does not go through to the database (I am using MySQL Workbench). There are no error messages, yet the query is unsuccesful.
I want to insert batches if queries in a transaction if there are existing values in the optional inputs. Is this the correct string for that? Or is there a sleeker code I can use?
The form and database in this question is a simplified version on the one I use in reality.
Thanks in advance, -burrdie

You have to understand the difference between a query and a batch of queries.
Since you have to execute several separate queries, you have to make several separate query() calls as well.
So change your code like this
$con->query("BEGIN");
$con->query(sprintf ("INSERT INTO person (fk_job, fn, ln)...");
$con->query("SELECT LAST_INSERT_ID() INTO #id");
// ...so on
and you'll be set.
Besides, it will let you write sleeker code, as you will be able to add your condition in the middle of the execution, thus not duplicating the code.

Related

Problem with query to update foreign key column

I am working on a cms for properties/ads in oop php for learning purposes. I have three tables that are connected with pivot table.
photos (id, name, extension),
property_photo (id, property_id, photo_id),
properties (id, title, description, main_photo_id)
I have a gallery of photos for every property and I am trying to be able to insert main photo (one of existing photos in gallery) for each property through foreign key (main_photo_id) and display that photo on a different page. I am having trouble writing function (query) in model. Any help is much appreciated. Here is some of my code:
AdModel:
public function MainPhotoInsert($id)
{
$this->db->query('INSERT INTO properties (main_photo_id) VALUES (:main_photo_id) SELECT id FROM PHOTOS WHERE id = :id LIMIT 1');
$this->db->bind(':id', $id);
$row = $this->db->single();
return $row;
}
AdsController:
public function galleryAction()
{
if (!isset($_GET['id'])) {
$photo_id = $_SESSION['photo_id'];
} else {
$photo_id = $_GET['id'];
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
if(isset($_POST['radio']))
{
$this->AdModel->MainPhotoInsert($photo_id);
redirect('ads/index');
}
}
$data = $this->AdModel->getPhotosForProperty($photo_id);
$data1 = $this->AdModel->MainPhotoData($photo_id);
$this->view->render('ads/gallery', $data, $data1);
}
gallery.php:
<form action="/ads/gallery?id=<?php echo $_GET['id']; ?>" method="POST">
<?php foreach ($data as $key => $value) : ?>
<img src="<?php echo '/public/photos/'.$value->name.'.'.$value->extension ?>" class="img-fluid img-thumbnail" width="250" height="250">
<input type="radio" name="radio" value="<?php echo $value->photo_id; ?>" >Make main
<br>
<?php endforeach; ?>
<br>
<br>
<button type="submit" name="submit" value="submit" class="btn btn-success form-control">Submit</button>
</form>
You shouldn't have a select clause in your insert statement (at least not for what you are trying to do). IF you only ever need to set it once then you need to tweak the query to include the other two values (title and description) or they will always be blank. It should end up looking something like this:
INSERT INTO properties (main_photo_id, title, description) VALUES (:main_photo_id, : title, : description)
More likely, you want an upsert (update if a relevant row already exists, insert if one doesn't). In MySQL the syntax is insert ... on duplicate key update. This means you are going to need a primary key on the properties table (it's unclear if you already have one). The syntax is pretty similar to the insert above but without knowing the exact structure of the table I can't give you the exact query.
Update:
The on duplicate key syntax would look something like this (it depends on how you have your primary key set up on the table, e.g. if main_photo_id is the primary key then this likely won't work):
INSERT INTO properties
(id, main_photo_id, title, description)
VALUES
(:id, :main_photo_id, : title, : description)
ON DUPLICATE KEY UPDATE
main_photo_id = :main_photo_id,
title = :title,
description = :description
Side note:
gallery.php is also going to produce a separate HTML form for each image with one radio button on the form which isn't really what you want. You should move the form to wrap around the entire foreach loop so that you have one form. Then you should put the image ID as the value for the radio button.

How do I use AES_Decrypt

I know this question has been asked a billion times as I've spent the last 2 weeks looking at all the previously asked questions and answers
but none of them actually have an understandable answer. So my question is this, I have a form that I'm passing the data input by users into a mysql
database and a portion of that data is encrypted with AES_Encrypt. When I check the database I can see the data has been encrypted so I'm good on the encryption part.
My issue lies in the decryption part. I've tried multiple variations from previous questions asked with no success, This is what I have so far,
//ENCRYPTING DATA
require 'path to key.php';
$sql = "INSERT INTO applications "(fname, lname, dob, ssn) VALUES ('$fname', '$lname', '$dob', AES_ENCRYPT('$ssn', '".$aeskey."')";
The code above works fine to encrypt the string.
This is where I'm confused, I'm wanting to select all the data associated with the ID for a record and decrypt the encrypted data for that record as well,
for example I have a search form that pulls up all the records in the database, you can then select to view a record and the results display in a form similar to the form used
to input the information.
So in my form to view records I have the following code.
//DECRYPT DATA
require 'path to key.php';
$conn = new mysqli($servername, $username, $password, $dbname);
$data = "SELECT * FROM $tbl_name where ID = $id";
$query = mysqli_query($conn, $data);
$data2 = mysqli_fetch_array($query);
<input type = "text" name="fname" value="<?php echo $data2['fname']?>"/>
<input type = "text" name="lname" value="<?php echo $data2['lname']?>"/>
<input type = "text" name="dob" value="<?php echo $data2['dob']?>"/>
<input type = "text" name="ssn" value="<?php echo $data2['ssn']?>"/><-----This will display the encrypted data in the encrypted form
So do I need to decrypt the encrypted data from the input box like
<input type = "text" name="ssn" value=<?php echo [AES_DECRYPT('ssn', '$aeskey')]?>"/> <---Doesn't work
or do I need to do something like this:
$sql SELECT * FROM $tbl_name (AES_DECRYPT('ssn', '$aeskey')) WHERE ID=$id;
Or am I totally wrong in how I think AES_DECRYPT should be used?
In the INSERT you use AES_ENCRYPT (of MySQL); then you have in your SELECT apply AES_DECRYPT; ejem:
SELECT fname, lname, dob, AES_DECRYPT(ssn, yourAESKey) as ssn
FROM applications [wHERE ... and other more that you require]
See that AES_DECRYPT have alias to return of result.
EDITED
Only change in $data the string with the SQL:
$data= "SELECT fname, lname, dob, AES_DECRYPT(ssn, yourAESKey) as ssn
FROM applications [WHERE ... and other more that you require]"
You line: <input type = "text" name="ssn" value="<?php echo $data2['ssn']?>"/><-----This will display the encrypted data in the encrypted form not change; unless instead of ssn (all in lowercase) in the alias you change some letter or all the letters to capital letters, you assign another alias name to the decrypted text; In order not to be ssn (in lower case).

How to select tables from MySQL Database in php?

I am trying to create a form in PHP with MySQL involved.
The theme of this form, form.php, is all about drinks. There are thirteen tables -each table named after type of drink (Belgian beer, wine, soda, rum, ...) that all include only three columns: Id of the drink(PRIVATE KEY AUTO_INCREMENT), the name of the drink and the price (in char). The rest of the columns in other tables are the same, the values are different.
I want to create a dropdown that allows you to select tables from MySQL to add/delete data to the columns within the selected table.
Some names of tables, columns and form elements are named in Dutch.
Click here to see resources
These are the things I do know:
1)Php code to add data to database
<?php
if ( ! empty($_POST))
{
$mysqli = new mysqli('localhost','root','','welkom');
if ($mysqli ->connect_error)
{
die('connect error: '. $mysqli->connect_errno . ': ' . $mysqli->connect_error);
}
$sql = "INSERT INTO abdijbieren (naam, prijs) VALUES ('{$mysqli->real_escape_string($_POST['naam'])}','{$mysqli->real_escape_string($_POST['prijs'])}')";
$insert = $mysqli->query($sql);
if ($insert)
{
echo "Success! Row ID: {$mysqli->insert_id}";
}
else
{
die("Error: {$mysqli->errno} : {$mysqli->error}");
}
$mysqli->close();
}?>
2)Form
<form method="post" action="check.php"> <!--check.php is not made yet but when that happens it should be used to automatically update the selected table and auto-return to form.php -->
<input name="naam" type="text" placeholder="naam drank/snack" required><br>
<input name="prijs" type="text" placeholder="prijs" required><br>
<input type="submit" value="Submit form">
</form>
All I can do with it is to add data to one certain column.
If you know how I can solve this, you are my hero.
You can select table names like this:
SHOW TABLES FROM <your_database>
Also to select columns from a table:
SHOW COLUMNS FROM <your_table>

prevent insert data to database if specific atribute already exist

I want to prevent duplicate values into a database table from a form using PHP.
I have a table data on database that have atribute dataid(auto increment as primary key), data1, data2.
And I have a simple form like this
<h2>Enter your data</h2>
<form action="script.php" method="post">
Data 1:<input type="text" name="data1" /></p>
Data 2:<textarea name="data2"></textarea></p>
<input type="submit" name="submit" value="Add Data" />
</form>
It's script.php for inserting data to database
<?php
if(isset($_POST['submit']))
{
//connect to the database
$conn = mysql_connect('host', 'username', 'password', 'dbname') or die(mysql_error());
//insert results from the form input
$query = "INSERT INTO data(data1, data2) VALUES('$_POST[data1]', '$_POST[data2]')";
$result = mysql_query($conn, $query) or die(mysql_error());
}
?>
but it will insert any data from the form to database.
How can I prevent insert data to database if data1 already exist?
The solution to your problem is to make the column unique so the database takes care of enforcing this constraint. You can do this by creating a unique index or constraint:
alter table data add constraint unq_data_data1 unique (data1);
You can then use this in an insert to ignore duplicates by using on duplicate key update:
INSERT INTO data(data1, data2)
VALUES('$_POST[data1]', '$_POST[data2]')
ON DUPLICATE KEY UPDATE data1 = VALUES(data1);
The ON DUPLICATE KEY part doesn't really do anything. It is a no-op.
Also, you should parameterize your queries, so you are not subject to SQL injection and so the query plans can be cached. But that is another matter.
make column data1 unique
ALTER TABLE `data` ADD UNIQUE (`data1`);
change your query like this to ignore insert when data exist
$query = "INSERT IGNORE INTO data(data1, data2) VALUES('$_POST[data1]', '$_POST[data2]')";

Posting from dynamic form (Multiple rows)

I have a form that creates form rows (fields) dynamically (add-delete) up to seven. Each additional form row has an incrimental number appended to it (ie: name="product" next is name="product2".. "Product3" etc.). So I thought I would just use isset to see what is posted and only insert what is posted but my lack of skills has led to this not working. See my code below:
mysql_select_db("inventory", $con);
$sql="INSERT INTO shipped (id, type, client, product, color, quantity)
VALUES ('$_POST[productid]','$_POST[type]','$_POST[client]','$_POST[product]','$_POST[color]','$_POST[quantity]')";
if( isset($_POST['productid2']) ) {
"INSERT INTO shipped (id, type, client, product, color, quantity)
VALUES ('$_POST[productid2]','$_POST[type2]','$_POST[client2]','$_POST[product2]','$_POST[color2]','$_POST[quantity2]')";
}
I planned to just add "isset" for each product but as it turns out this will only insert one of the set of post values and not both. I am going to have up to product7 (so seven inserts at max). Any help?
You would use the array in input fields
<input type="text" name="productid[]" />
<input type="text" name="type[]" />
<input type="text" name="client[]" />
<input type="text" name="product[]" />
<input type="text" name="color[]" />
<input type="text" name="quantity[]" />
At server side:
foreach($_POST['product'] as $k => $v){
$sql="INSERT INTO shipped (id, type, client, product, color, quantity) VALUES
($_POST['productid'][$k],$_POST['type'][$k],$_POST[client][$k]','$v','$_POST[color][$k]','$_POST[quantity][$k]')";
}
Ok so I did like the other answer as it seemed much more elegant than the solution I ended up using - but the fact is the other answer just did not work. So my solution just ended up just checking if the next form set of form fields is set, and if it is it displays the proper inserts. See the first part here:
mysql_select_db("inventory", $con);
if( !isset($_POST['productid2']) ) {
$sql="INSERT INTO shipped (id, type, client, product, color, quantity)
VALUES ('$_POST[productid]','$_POST[type]','$_POST[client]','$_POST[product]','$_POST[color]','$_POST[quantity]')";
}
if( isset($_POST['productid2']) ) {
$sql="INSERT INTO shipped (id, type, client, product, color, quantity)
VALUES ('$_POST[productid]','$_POST[type]','$_POST[client]','$_POST[product]','$_POST[color]','$_POST[quantity]'),
('$_POST[productid2]','$_POST[type2]','$_POST[client2]','$_POST[product2]','$_POST[color2]','$_POST[quantity2]')";
}
if( isset($_POST['productid3']) ) {
$sql="INSERT INTO shipped (id, type, client, product, color, quantity)
VALUES ('$_POST[productid]','$_POST[type]','$_POST[client]','$_POST[product]','$_POST[color]','$_POST[quantity]'),
('$_POST[productid2]','$_POST[type2]','$_POST[client2]','$_POST[product2]','$_POST[color2]','$_POST[quantity2]'),
('$_POST[productid3]','$_POST[type3]','$_POST[client3]','$_POST[product3]','$_POST[color3]','$_POST[quantity3]')";
}
Like this another four times... adding the other values each time. This works for me because my form fields can only be added a max of seven times so it doesn't need to be infinite. So if you are only allowing a small amount of form fields to be added this will work well.

Categories