0

What I'm trying to do is as the title implies inserting date into created table.

I've done my research. I considered following topics:

and others.

However nothing really helped to solve this. The $dob variable is in there on purpose. I need to make sure that it will change as users will change as well.

This is my php code:

$firstName = $middleName = $lastName = $mobileNumber = $dob = $address = "";
$firstName0 = $middleName0 = $lastName0 = $mobileNumber0 = $dob0 = $address0 = "";
$dobErr = $addressErr = $mobilenumErr = $emailErr = $passwordErr = "";
$email = $password = $fnameErr = $mnameErr = $lnameErr = $conn = $data = "";
$email0 = $password0 = "";

require_once 'login.php';
$conn = new mysqli($hn, $un, $pw, $db);
if($conn->connect_error) die($conn->connect_error);

function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}

if(isset($_POST['submit'])) {
    // input validation

    if ($_SERVER["REQUEST_METHOD"] == "post") {
        if (empty($_POST["firstName"])) {
            $fnameErr = "Name is required";             
        } else {
            $firstName0 = test_input($_POST["firstName"]);              
        }
        if (empty($_POST["lastName"])) {
            $lnameErr = "Last name is required";        
        } else {
            $lastName0 = test_input($_POST["lastName"]);                
        }
        if (empty($_POST["dob"])) {
            $dobErr = "Date of birth is required";              
        } else {
            $dob0 = test_input($_POST["dob"]);              
        }
        if (empty($_POST["address"])) {
            $addressErr = "Address is required";                
        } else {
            $address0 = test_input($_POST["address"]);              
        }
        if (empty($_POST["mobileNumber"])) {
            $mobilenumErr = "Mobile number is required";                
        } else {
            $mobileNumber0 = test_input($_POST["mobileNumber"]);                
        }
        if (empty($_POST["email"])) {
            $emailErr = "Email is required";                
        } else {
            $email0 = test_input($_POST["email"]);
        }
        if (empty($_POST["password"])) {
            $passwordErr = "Password is required";              
        } else {
            $password0 = test_input($_POST["password"]);            
        }
    }
    if ($_SERVER["REQUEST_METHOD"] == "post") {
        // sanitizing the input
        $firstName = test_input($_POST["$firstName0"]);
        if (!preg_match("/^[a-zA-Z]*$/",$firstName)) {
            $nameErr = "Only letters are allowed";          
        }
        $middleName = test_input($_POST["$middleName0"]);
        $lastName = test_input($_POST["$lastName0"]);
        $dob = test_input($_POST["$dob0"]);
        $address = test_input($_POST["$address0"]);
        $mobileNumber = test_input($_POST["$mobileNumber0"]);
        $email = test_input($_POST["$email0"]);
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $emailErr = "Invalid email format";         
        }
        $password = test_input($_POST["$password0"]);   
    }

    // sending valid data to the database   
    $query = "insert into details values" . "("$firstName","$middleName","$lastName",STR_TO_DATE("$dob","%Y/%m/%d"),"$address","$mobileNumber","$email", "$password")";
    $result = $conn->query($query);
    if(!$result) {
        echo 'Insert failed: $query<br>' . $conn->error . '<br><br>';
    } else { 
        echo 'Data saved !';
    }
}

I'm getting this error:

Insert failed: insert into details values('','','',STR_TO_DATE("","%Y/%m/%d"),'','','', '') Incorrect datetime value: '' for function str_to_date

Community
  • 1
  • 1
  • It seems that all your string variables are empty. Also, in MySQL date should be in format `%Y-%m-%d`. – Michael May 03 '17 at 16:30
  • 2
    Your code is subject to SQL Injection. Please use parameterized queries. – Sloan Thrasher May 03 '17 at 16:31
  • Originally I had dashes as delimiters in the date, however in MySQL manual I read that MySQL might misinterpreted as arithmetic operator (minus) and substract the value instead of converting it into date format. –  May 03 '17 at 16:33
  • I'll edit the question so you can see the whole thing. –  May 03 '17 at 16:34
  • Also, Instead of single quotes you can use screened double quotes: `\"`, because this may be a cause of variables being "invisible"/ – Michael May 03 '17 at 16:36
  • Thanks for tip Michael O. I swapped quotes over and now just getting error: Parse error: syntax error, unexpected '%' in /var/www/html/submittedForm.php on line 86 At least I moved little bit. –  May 03 '17 at 16:43
  • Echo your query and see what's wrong with it. – Michael May 03 '17 at 16:47
  • I echoed the query and this is all I got: `insert into details values("$firstName","$middleName","$lastName",STR_TO_DATE("$dob","%Y/%m/%d"),"$address","$mobileNumber","$email","$password")` which is just the query with data that supposed to be inserted into table. –  May 03 '17 at 16:50
  • Well, you're wrong again. You shouldn't "swap" quotes, you have to use double quotes for echo and screened double quotes for values in query. Everything in single quotes doesn't substitute. – Michael May 03 '17 at 16:53
  • I edited my code. Quotes should be okay now. Sadly getting this now: `Parse error: syntax error, unexpected '$firstName' (T_VARIABLE)` PHP isn't accepting my variables –  May 03 '17 at 17:03
  • See the answer. – Michael May 03 '17 at 17:20

2 Answers2

1
$query = "insert into details values ($firstName,$middleName,$lastName,STR_TO_DATE($dob,'%Y/%m/%d'),$address,$mobileNumber,$email, $password)";
Michael
  • 5,095
  • 2
  • 13
  • 35
  • Appreciate the effort Michael O. Firstly, don't get me wrong. I don't question your solution it's just I've got a book about PHP and MySQL and putting backslash as a part of the syntax wasn't anywhere in the book. secondly I'm getting blank quotes again: `Incorrect datetime value: '' for function str_to_date insert into details values("","","",STR_TO_DATE("","%Y-%m-%d"),"","","","")` –  May 03 '17 at 17:27
  • But thanks for trying to help me with this. You're the only one who's showing an interest. –  May 03 '17 at 17:32
  • Going to open the manual to see what book says about `STR_TO_DATE()` Getting this this time: `You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ',,STR_TO_DATE(,'%Y-%m-%d'),,,,)'` –  May 03 '17 at 17:36
  • So your variables are empty. Check if yout POST query is executing correctly, and echo your variables. Also, you're welcome :) We usually have much free time here in Siberia. – Michael May 03 '17 at 17:39
0

With all of those individual string declarations, I think it would be better to processes arrays. PHP has some fantastic array functions to offer. I'll use array_intersect_key(), array_walk(), implode(), and array_keys(). I have left some commented var_export()'s in place so that you can uncomment them and see how the filtering processes work.

If a form submits this $_POST array:

$_POST=array('firstName'=>'Mick','lastName'=>'MacKusa','dob'=>'2017/05/03',
             'address'=>'Home','mobileNumber'=>'v','email'=>'user@email.com',
             'password'=>'v','bogus'=>'Hacktastic');

To this script:

<?php
require_once 'login.php';

$requireds=array('firstName'=>'Name is required','lastName'=>'Last name is required','dob'=>'Date of birth is required','address'=>'Address is required','mobileNumber'=>'Mobile number is required','email'=>'Email is required','password'=>'Password is required');

$inputs=array_intersect_key($_POST,$requireds);  // only handle desired elements in $_POST
// var_export($inputs);  // 'bogus'=>'Hacktastic' has beem removed

// create an array filled with empty elements
array_walk($inputs,function($v,$k)use(&$empties){if(empty($v)){$empties[$k]=$v;}});
// var_export($empties);

if(!is_null($empties)){  // if at least one required value is missing...
    $messages=array_intersect_key($requireds,$empties);  // create an array of "required" messages
    var_export($messages);  // handle this array however you wish
}else{  // all fields have a value
    //var_export($inputs);

    // do any necessary/specific validation or preparation on elements like: 

    // $inputs['password']=hash("sha256",$_POST["password"]); or something
    // never store anyone's unencrypted passwords
    // regarding data security, research AS MUCH AS POSSIBLE

    // check format of $inputs['dob'] and $inputs['email'], etc...

    // I prefer pdo where I can drop the $inputs array into the execute function,
    // but it may be less overwhelming for you to stay with mysqli for the time being

    if(!$conn=new mysqli($hn,$un,$pw,$db)){
        echo "Connection Error: ",$conn->connect_error;  // do not echo when live
    }elseif($stmt=$conn->prepare("INSERT INTO `details` (`".implode('`,`',array_keys($inputs))."`) VALUES (?,?,STR_TO_DATE(?,'%Y/%m/%d'),?,?,?,?)")){
        // to shrink bind_param code, use variadic expression or call_user_func_array
        if($stmt->bind_param('sssssss',$inputs['firstName'],$inputs['lastName'],$inputs['dob'],$inputs['address'],$inputs['mobileNumber'],$inputs['email'],$inputs['password']) && $stmt->execute()){
            echo "Success - New ID# is ",$stmt->insert_id;
        }else{
            echo "Statement Error: ",$stmt->error;  // do not echo when public
        }
        $stmt->close(); 
    }else{
        echo "Prepare Error: ",$conn->error;  // do not echo when public
    }
    $conn->close();
}
?>

And the details table in the database looks like this:

CREATE TABLE `details` (
  `id` int(10) NOT NULL,
  `firstName` varchar(100) NOT NULL,
  `lastName` varchar(100) NOT NULL,
  `dob` date NOT NULL,
  `address` varchar(255) NOT NULL,
  `mobileNumber` varchar(30) NOT NULL,
  `email` varchar(255) NOT NULL,
  `password` varchar(100) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

ALTER TABLE `details`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `details`
  MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

Then the screen output will read:

Success - New ID# is 1

And the database table will look like this:

enter image description here

By doing some light validation and preparation work with array functions and using prepared statements to handle the security aspect, you can skip right to educating yourself about developing a smart/secure login system.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • Thanks for the exhausting answer mickmacusa ! I need to study your code for a bit. It's not that I don't know arrays it's just I haven't considered using arrays for this task for some reason. Although I applied prepared statement to my SQL table to see how that goes. If you're interested you can have a look here https://kobra.io/#/e/-KjGZXs1uoyHetXifpRt –  May 04 '17 at 16:36
  • Are you sure about this line ?`('sssssss',$inputs['firstName'],$inputs['lastName'],$inputs['dob'],$inputs['address'],$inputs['mobileNumber'],$inputs['email'],$inputs['password'])` I'm asking because the field with phone number will be clearly an integer therefore replace appropriate 's' with 'i'. Correct ? –  May 04 '17 at 17:43
  • @MarkUK you can do that if your phone numbers will be without symbols. I am sure my code works because I tested it before posting. – mickmackusa May 04 '17 at 20:35
  • @MarkUK I think it is unadvisable to make your mobileNumber parameter type an integer `i` because your sample number starts with a zero. I fear your integer will loss its leading zeros when you start interacting with your data between the database and your code. I would recommend that you make it a simple VARCHAR and leave the param type as `s`. – mickmackusa May 05 '17 at 06:32
  • @MarkUK and sorry if my answer was _exhausting_ I was shooting for thoughtful, informative, comprehensive, and/or complete. Half of the volume is comments anyhow, so it looks a bigger monster than it really is. If you would like me to explain anything further, just ask. – mickmackusa May 05 '17 at 06:35