0

I have the following table in mysql database :

CREATE TABLE IF NOT EXISTS `accounts` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(50) NOT NULL,
    `password` varchar(255) NOT NULL,
    `email` varchar(100) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

and a php system to handle the users . I want to add a new field to the register form like a selectable list : Beginner,Intermediate, Advanced, where user can select the status at the time they will fill the register form. How can I handle this new select list based on its values(Beginner,Intermediate, Advanced) in the mysql table and also in php code. Because based on experience I have a profile page that will displayed different information(also based on experience of the user). This is the original document : https://codeshack.io/secure-registration-system-php-mysql/

<form action="register.php" method="post" autocomplete="off">
                        <div class="form-group input-group">
                                <select class="form-control" name="invest">
                                    <option selected="">Investor Experience Level</option>
                                    <option>Beginner</option>
                                    <option>Intermediate</option>
                                    <option>Advanced</option>
                                </select>
                            </div> <!-- form-group end.// -->
                    <label for="username">
                        <i class="fas fa-user"></i>
                    </label>
                    <input type="text" name="username" placeholder="Username" id="username" required>
                    <label for="password">
                        <i class="fas fa-lock"></i>
                    </label>
                    <input type="password" name="password" placeholder="Password" id="password" required>
                    <label for="email">
                        <i class="fas fa-envelope"></i>
                    </label>
                    <input type="email" name="email" placeholder="Email" id="email" required>
                    <p>Already have an account? <a href="login.html">Login here</a>.</p>
                    <input type="submit" value="Register">
                </form>
<?php
// Change this to your connection info.
$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'root';
$DATABASE_PASS = '';
$DATABASE_NAME = 'phplogindb';
// Try and connect using the info above.
$con = mysqli_connect($DATABASE_HOST, $DATABASE_USER, $DATABASE_PASS, $DATABASE_NAME);
if (mysqli_connect_errno()) {
    // If there is an error with the connection, stop the script and display the error.
    die ('Failed to connect to MySQL: ' . mysqli_connect_error());
}

// Now we check if the data was submitted, isset() function will check if the data exists.
if (!isset($_POST['username'], $_POST['password'], $_POST['email'])) {
    // Could not get the data that should have been sent.
    die ('Please complete the registration form!');
}
// Make sure the submitted registration values are not empty.
if (empty($_POST['username']) || empty($_POST['password']) || empty($_POST['email'])) {
    // One or more values are empty.
    die ('Please complete the registration form');
}

// We need to check if the account with that username exists.
if ($stmt = $con->prepare('SELECT id, password FROM accounts WHERE username = ?')) {

    if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
    die ('Email is not valid!');
    }

    if (preg_match('/[A-Za-z0-9]+/', $_POST['username']) == 0) {
    die ('Username is not valid!');
    }

    if (strlen($_POST['password']) > 20 || strlen($_POST['password']) < 5) {
    die ('Password must be between 5 and 20 characters long!');
    }

    // Bind parameters (s = string, i = int, b = blob, etc), hash the password using the PHP password_hash function.
    $stmt->bind_param('s', $_POST['username']);
    $stmt->execute();
    $stmt->store_result();
    // Store the result so we can check if the account exists in the database.
    if ($stmt->num_rows > 0) {
        // Username already exists
        echo 'Username exists, please choose another!';
    } else {
        // Username doesnt exists, insert new account
    if ($stmt = $con->prepare('INSERT INTO accounts (username, password, email) VALUES (?, ?, ?)')) {
        // We do not want to expose passwords in our database, so hash the password and use password_verify when a user logs in.
        $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
        $stmt->bind_param('sss', $_POST['username'], $password, $_POST['email']);
        $stmt->execute();
        header('Location: login.html');
        echo 'You have successfully registered, you can now login!';
    } else {
        // Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
        echo 'Could not prepare statement!';
    }
    }
    $stmt->close();
} else {
    // Something is wrong with the sql statement, check to make sure accounts table exists with all 3 fields.
    echo 'Could not prepare statement!';
}
$con->close();
?>
  • 1
    **WARNING**: Writing your own access control layer is not easy and there are many opportunities to get it severely wrong. Please, do not write your own authentication system when any modern [development framework](http://codegeekz.com/best-php-frameworks-for-developers/) like [Laravel](http://laravel.com/) comes with a robust [authentication system](https://laravel.com/docs/master/authentication) built-in. Using canned code from a blog post is not the best plan here, if there's any security issues you will never know. Major platforms offer herd safety. – tadman Apr 22 '19 at 19:46
  • 1
    if you're using user-supplied data you really should update `CHARSET=utf8` to be `CHARSET=utf8mb4` and ensure all column are updated to this as well. [Why?](https://stackoverflow.com/questions/279170/utf-8-all-the-way-through) – Martin Apr 22 '19 at 20:49

2 Answers2

0

First, add a column into your table to hold your value:

ALTER TABLE `mytable` ADD `myselect` TEXT NOT NULL; 

Next, make a select element in your form:

<form action = 'myphppage.php' method='post'>
    <select name='yourselect'>
        <option value='Advanced'>Advanced</option>
        <option value='Intermediate'>Intermediate</option>
        <option value='Beginner'>Intermediate</option>
    </select>
    <button type='submit'>Submit</button>
</form>

When the user clicks submit, the value of your select element will be sent in your $_POST array to 'myphppage.php', with the name of the element as an index.

<?php

   $select = $_POST['yourselect']; 

?>

Now that you have the value as a string, you can use the same methods you've posted above to insert the value into the database.

<?php

    if($stmt = $con->prepare('INSERT INTO `mytable`(`myselect`) VALUES (?)'){
        $stmt->bind_param('s', $select){
            $stmt->execute();
        }
    }

?>

Obviously, you'll need to tailor this to match the specifics of your situation, but this is the idea.

tadman
  • 208,517
  • 23
  • 234
  • 262
Truth
  • 486
  • 7
  • 19
  • And in case of show/hide content based on this status(beginner, intermediate and advanced) is this approach correct using a switch statement? ``` Display content for beginner here"; break; } ?> ``` – Junior.junior Apr 23 '19 at 05:43
  • I don't think that's going to work, and if your user can get access to your session variable you'll be in danger of SQL injection regardless. If you're going to make SQL queries you need to use parameterized queries. https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php – Truth Apr 23 '19 at 13:03
  • In general, my recommendation is that you query the database for your data first, then use PHP to process that data, and then output that data to your user in html. It looks to me like you're just doing it all in one. Also, your select statement looks to be wrongly formatted, unless you just named your column (which I called 'myselect') 'column'. – Truth Apr 23 '19 at 13:06
0

To add a new column to existing table you should run the following SQL command:

ALTER TABLE accounts ADD COLUMN experience ENUM('Beginner','Intermediate','Advanced') NULL DEFAULT 'Beginner' FIRST;

The advantage of enum column is that only the enumeration(1-3) is stored and not the strings.

Then the insert command will be

INSERT INTO accounts (username, password, email,experience ) VALUES (?, ?, ?, ?)

and the value for the experience column can be one of the strings 'Beginner','Intermediate','Advanced' or the corresponding numeric value 1,2,3

Grigory Ilizirov
  • 1,030
  • 1
  • 8
  • 26
  • That's one advantage of an `ENUM`, but the downside is adding a new option is super annoying and requires a database migration. – tadman Apr 22 '19 at 20:05
  • If he wants to use an integer he could just set up an int and give his form values 1, 2, and 3. That would probably be optimal. – Truth Apr 22 '19 at 20:35
  • @tadman really? I have used `ENUM`s extensively and edit them sometimes and never come across this issue. If I edit an `ENUM` and add a new column then it simply accepts a wider choice of text flags, as expected. .... – Martin Apr 22 '19 at 20:51
  • In most production environments you don't just hop on the database server and start editing things like that. You need to carefully roll that out with a migration, and that requires a lot more planning. It's sometimes convenient to have this enforced in your application code so you can iterate on your application and test new implementations in parallel without altering the schema. – tadman Apr 22 '19 at 20:56
  • If you are using an ENUM though it's usually best to use a name that won't change based on whims, that is `beginner` vs. `Beginner`, as the capitalization is purely a cosmetic concern. It's also good to avoid spaces, keep them as terse as practical without impacting readability, like `super_advanced` vs. `Super Advanced`. – tadman Apr 22 '19 at 20:57
  • Honestly in this case what you need is a `TINYINT(1)` where 0=Beginner, 1=Intermediate, 2=Advanced and such. – tadman Apr 22 '19 at 20:58
  • What will be the best approach to update the accounts database from the above html form? I will create a new form like update preferences that will include all the input fields(username, investment experience, password and so on) for updating purpose. I have to check for each preference input if the data exist in database and if not to update for each field right ? – Junior.junior Apr 25 '19 at 19:19