Ash1391 Posted October 18, 2015 Share Posted October 18, 2015 (edited) 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 October 18, 2015 by Ash1391 Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted October 18, 2015 Share Posted October 18, 2015 (edited) 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 October 18, 2015 by Jacques1 Quote Link to comment Share on other sites More sharing options...
benanamen Posted October 18, 2015 Share Posted October 18, 2015 Whats with all the selects? Your logic is very bad. Also, you don't put spaces in form/variable names and they should always be lowercase. At least your using PDO so thats a good start. Quote Link to comment Share on other sites More sharing options...
hansford Posted October 18, 2015 Share Posted October 18, 2015 (edited) 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 October 18, 2015 by hansford Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted October 18, 2015 Share Posted October 18, 2015 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.”. 1 Quote Link to comment Share on other sites More sharing options...
benanamen Posted October 21, 2015 Share Posted October 21, 2015 @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? Quote Link to comment Share on other sites More sharing options...
lush_rainforest Posted October 21, 2015 Share Posted October 21, 2015 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. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted October 21, 2015 Share Posted October 21, 2015 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? Quote Link to comment Share on other sites More sharing options...
benanamen Posted October 21, 2015 Share Posted October 21, 2015 (edited) Are you talking about the storage encoding or the connection encoding? Storage. Also what would be the considerations between sending data as UTF-16 vs UTF-8? Edited October 21, 2015 by benanamen Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted October 21, 2015 Share Posted October 21, 2015 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. Quote Link to comment Share on other sites More sharing options...
benanamen Posted October 21, 2015 Share Posted October 21, 2015 (edited) 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 Edited October 21, 2015 by benanamen Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted October 22, 2015 Share Posted October 22, 2015 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.