Jump to content

Recommended Posts

Hey, I am trying to create a a form which then saves the collected data into my database, i followed a tutorial and had it working, it would collect username, email and password then submit it fine, but i want to collect more data such as first name, surname for example and when i added these into the code i keep getting this error "Undefined index: First Name in C:\wamp\www\index.php" i know this is probably a really simple issue and i'm just missing something, but i cant find it and i'm relatively new to using php and SQL.

Thanks in advance, 
 
Ash.

index.php

config.php

Edited by Ash1391
Link to comment
https://forums.phpfreaks.com/topic/298661-help-needed-with-signuplogin-page/
Share on other sites

Don't use spaces within field names, and don't mix lowercase and uppercase letters. While this is theoretically possible, you'll run into a lot of trouble. PHP seems to convert those spaces into underscores.

 

The field name isn't supposed to be pretty. It's should be unambiguous, so make it all-lowercase and use underscores to avoid any confusion:

first_name
Edited by Jacques1

Issue one query to get all the information you need based on that username.

If username already exists, issue that error and nothing more.

If the username passes but the email matches, issue the email error etc.

Edited by hansford

No, you shouldn't do any SELECT query to check the uniqueness of a value. This is naïve, unnecessary and simply doesn't work when multiple PHP processes run at the same time (which is very common in a web application).

 

If two processes simultaneously check a name which hasn't been taken yet, they both come to the conclusion that they can use it, so they'll both run the INSERT query with the same name. This will either lead to a duplicate name or a database error, depending on whether you have a UNIQUE constraint in your database. In any case, this is a problem.

 

Only the database system can and should enforce unique values. Make sure the name, e-mail etc. columns are either a primary key or have a UNIQUE constraint, and then simply try to insert the new user with no prior checks. If that fails due to a constraint violation, you know the name is already taken. This approach will not only save you a lot of code. It's also reliable, because everything happens in a single atomic operation which cannot interfere with other processes.

 

As an example:

 

The database schema

CREATE TABLE users (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  public_name VARCHAR(100) NOT NULL UNIQUE,
  password_hash CHAR(60) NOT NULL CHECK (LENGTH(password_hash) = 60)
);

The database connection

<?php

const DB_HOST = 'localhost';
const DB_USER = 'root';
const DB_PASSWORD = '';
const DB_NAME = 'test';
const DB_CHARSET = 'UTF8';

// MySQL error codes
const MYSQL_ER_DUP_ENTRY = '23000';



/*
 * Set up the database connection
 * - the character encoding *must* be defined in the DSN string, not with a SET NAMES query
 * - be sure to turn off "emulated prepared statements" to prevent SQL injection attacks
 * - turn on exceptions so that you don't have to manually check for errors
 */
$dSN = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHARSET;
$databaseConnection = new PDO($dSN, DB_USER, DB_PASSWORD, [
    PDO::ATTR_EMULATE_PREPARES => false,                 // activate real prepared statements
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,         // activate exceptions
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,    // fetch associative arrays by default (this isn't critical)
]);

The registration logic

<?php

// test data
$username = 'foo';
$passwordHash = '$2y$12$Yo1zXvPWXLuxMku2rOnrpeEvCJssXQ44fHR2rj.uTBps3SA3sjX8q';

$registrationStmt = $databaseConnection->prepare('
    INSERT INTO
      users (public_name, password_hash)
    VALUES
      (:public_name, :password_hash)
');

/*
 * Try to insert the new user.
 *
 * If the name is already taken, this will violate the UNIQUE constraint of the public_username column and trigger
 * an exception. We can catch this exception and tell the user that they need to choose a different name.
 */
$nameIsAlreadyTaken = false;
try
{
    $registrationStmt->execute([
        'public_name' => $username,
        'password_hash' => $passwordHash,
    ]);
}
catch (PDOException $registrationException)
{
    // Was the exception caused by a constraint violation? Then catch it; otherwise propagate it.
    if ($registrationException->getCode() == MYSQL_ER_DUP_ENTRY)
    {
        $nameIsAlreadyTaken = true;
    }
    else
    {
        throw $registrationException;
    }
}

if ($nameIsAlreadyTaken)
{
    echo 'Sorry, this name is already in use. Please choose a different name';
}

If you have multiple unique columns, things get a bit more complicated. You have to use the above try statement, and within the error handling procedure, you need to perform a SELECT query to check which one the values already exists in the database.

 

Note that you should never tell arbitrary users that a particular e-mail address already exists in your database, because this is private information. Instead, send an e-mail to that address saying something like “You or somebody else has tried to register at our website with this e-mail address, but the address already exists in our database. If you forgot your password ... etc.”.

  • Like 1

@Jacques1,

I see that you are setting the charset in the connection. 

 

Per the manual:

Ideally a proper character set will be set at the server level

http://php.net/manual/en/mysqlinfo.concepts.charset.php

 

The manual continues that doing it that way is an alternative.

 

The DB is where I have always set it. What can you tell me about this?

I've used

charset=UTF8

on PDO connection before and let me tell you something. It doesn't even insert the proper character encodes. All it does is insert a bunch of ?????? in place of the characters. You can use

charset=UTF8

if you want foreign characters to be inserted as a bunch of ??????. Just telling you now.

There are multiple encodings involved when PHP interacts with MySQL.

 

On the one hand, there's the encoding of the stored data. This is determined by the CHARACTER SET declaration within a CREATE TABLE or CREATE DATABASE query.

 

Then there's the connection encoding which affects a particular database session. That's what the charset attribute in the PDO DSN string is for. The connection encoding may be different from the storage encoding. For example, the client may prefer to send and receive UTF-16 encoded strings while the database uses UTF-8 for its data. It's theoretically possible to define a default connection encoding in the MySQL configuration, but in my experience, most people do not do this. In that case, MySQL will fall back to Latin-1 (aka ISO 8859-1). Since you can't always rely on the default setting, it's a good idea to explicitly declare it in your DSN string.

 

And of course there's the encoding of the PHP strings.

 

All three have to be compatible. Otherwise you'll end up with weird characters or question marks.

 

 

 

@Jacques1,

I see that you are setting the charset in the connection. 

 

[...]

 

The DB is where I have always set it.

 

Are you talking about the storage encoding or the connection encoding?

Storage.

 

Then you actually have to use the PDO charset attribute, or else MySQL will use Latin-1 as the connection encoding (which is incompatible with any Unicode encoding).

 

Alternatively, you can set the default-character-set in the MySQL configuration.

 

 

 

Also what would be the considerations between sending data as  UTF-16 vs  UTF-8?

 

Since your data already is stored UTF-8 and your application supports UTF-8 as well, it makes no sense to transcode everything to UTF-16.

My "storage" answer may have not been correct. See the attached image. Doesn't this say the the database itself is UTF8 and therefore would not need it in the connection string?

 

 

Edit* Just noticed it says character_set_server = latin

post-179806-0-19946600-1445458369_thumb.jpg

Edited by benanamen

The character_set_server setting is only the default value for the storage encoding. If you've explicitly declared the storage encoding of your database as UTF-8, that setting is irrelevant.

 

Since the default connection encoding is UTF-8 as well, you don't necessarily have to declare it with PDO.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.