My Error:Trying to access array offset on value of type null

Getting this error: Warning : Trying to access array offset on value of type null in

C:\www\login.php on line 42

My code :

$dsn = 'mysql:host=localhost;dbname=getitweb';

$dbUser = 'root';

$dbPassword = 'n.)3pKTZHwIbr2_o';

try {

    $connection = new PDO($dsn, $dbUser, $dbPassword);

    $connection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

} catch (PDOException $e) {

    $_SESSION['messages'] [] = 'Connection failed: ' . $e->getMessage();

    header('string: Location: index.php');

}

$statement = $connection->prepare("SELECT * FROM members WHERE username = ?");

//var_dump($statement);

$statement->execute([$username]);

$result = $statement->fetchAll(fetch_style:PDO::FETCH_ASSOC);

$nFind = $result["bob"] ?? null;

if (empty($result)) {

    $_SESSION['messages'] [] = 'Incorrect username or password!';

    header( 'string: Location: index.php');

}

    $user = array_shift( $result);

    var_dump($user);

if ($user['username'] === $username) {

    $_SESSION['messages'] [] = 'User not Registered!';

     header( 'string: Location: index.php');

}

elseif ($user['username'] === $username && $user['password'] === $password) {

    echo 'You have

You access the results before you check if it exists. That is one error.
Next, it is nice you told us the error is in line 42, but, which line is number 42?

Where does $username and $password magically come from?

line 42: if ($user[‘username’] === $username) {

line 46: elseif ($user[‘username’] === $username && $user[‘password’] === $password) {

username and password is coming from a form

The select query is not finding any records so the array is empty or I guess null

It is not good programming to set variables inside of IF statements. You have no way to validate the item.
Normally, you would get the posted info from the form and assign it to a variable. Then, you would validate it to insure they did not put hacker code in the value using filter-input validation or other code. Then, you would run the query to see if their username and password exists. Then, you check if you got any records back and if not, throw out an error message stating that either the username or password is invalid. If invalid, you can do a second query to see if it is the username that is missing or not. That will tell the user which one is incorrect. Hope that helps.

There is no need to assign the POST value to a variable before you have done anything with it or to do a second query. Additionally, it is a security risk to specifically verify to the user whether it was the password or username that was incorrect. You would be validating 50% of the credentials by doing that. It is known as a Username Enumeration attack. :smile:

Thank you all for your input, I do appreciate the tips and will be implementing those standards, if and when I publish a website publicly. I was just trying to see how PDO prepare and execute work.

In case the OP is still working on this. Code without useful validation and error handling won’t tell you why it isn’t working. You won’t know which step caused it to fail.

The NULL value you are getting is either because the query didn’t match a row of data and your unusual and unnecessary use of fetchAll/array_shift (gives a NULL output for both a false input or an empty array input) OR because the query failed due to an error and you don’t have any error handling to tell you if/why the query failed.

Here’s a laundry list of items in the posted code -

  1. You should not use the root user in an application. Create a specific user with only those permissions that your application needs.
  2. I hope that’s not your actual db password that got posted here. If so, you need to change it.
  3. There’s no good reason to catch and display information about a connection error since the visitor on a site cannot do anything about it. Yes, you, as the programmer/developer, want to know about connection errors, but the visitor/hacker on your site doesn’t need to know anything at all about any errors that have occurred. Also, by only using the exception message, you are losing the file/line number information about the error.
  4. The session variables and redirects indicate that your form and form processing code are on separate pages. If you put them on the same page, you will eliminate a lot of code and provide a better User eXperience (UX.) The only redirect you will end up with is one to the same url of the current page upon successful completion of the form processing code.
  5. The connection code should ALSO set the error mode to exceptions (this will give you error handling for all the rest of the PDO statements that can fail) and set emulated prepared queries to false (you want to run true prepared queries.)
  6. Every header() redirect needs an exit statement after it to stop code execution.
  7. You haven’t shown where the $username and $password variables are being assigned values, and they won’t automatically be set as they were in old versions of php. Also, without any validation of the inputs, you could be using empty values, which won’t match any data.
  8. Don’t use fetchALL() for a query that will match at most one row of data. You would just use fetch().
  9. Don’t specify the fetch mode in each fetch statement. That’s why you set the default fetch mode when you made the connection.
  10. When/after you have fetched the data, you would test if there was/was not data to fetch. This would have told you if the username did/didn’t match a row in the database table. You would not then need to test again if the username matched the fetched data.
  11. After you have determined that the query matched a row of data, meaning that the username was found, you would verify the password. You should be using php’s password_hash() and password_verify().

Again. I want to say thank you to all who replied. All those tip were very helpful in expanding my knowledge.

Sponsor our Newsletter | Privacy Policy | Terms of Service