Jump to content

mysqli_fetch_assoc returns only 1 result


Go to solution Solved by Barand,

Recommended Posts

Hey. I'm making a log in form and it creates a query that checks the database for any records with the inputted email by the user. That query looks like this: "SELECT uid FROM users WHERE email='$valid_email'"


I store that in a variable called $sql. I then perform the function mysqli_query, and store it in $result. Then I check for it having at least 1 row (email has been found in the database). If it has at least one row, now my thinking is to hash the password the user entered and then match it against the hashed one in the database. So, I need to retrieve the already hashed password in the database. I went ahead and done some googling and found mysqli_fetch_assoc, which returns an associative array for the result row. Sounds good, so i did: $row = mysqli_fetch_assoc($result); By my understanding, and other examples on the web, I should now be able to do $row['password'] to access the 'password' field in that record. Though, for some reason, when debugging this $row using a foreach loop it ONLY shows the UID. Also, when trying to use $row['password'] PHP gives me an error like this: Notice: Undefined index: password


So, I tried to debug this code. I created a separate file just to test out queries and such. It still doesn't work, and I get the same Undefined index: password error, or if I substitue 'password' for another field e.g 'email' or 'username', it's the same error though it says undefined index: username or whatever. The ONLY thing that works is $row['uid']; 


Here's that debug code:



<?php
$sql = "SELECT uid FROM users WHERE email='examplar@gmail.com'";
$result = mysqli_query($link, $sql);
$row = mysqli_fetch_assoc($result);

// Undefined Index: username
echo $row['username'] . '<br>';
// Undefined Index: password
echo $row['password'] . '<br>';
// Shows '7' - which is the CORRECT uid! so this works..
echo $row['uid'] . '<br>';

mysqli_free_result($result);
?>


Edited by MattL019

Hmm, I did think that myself however when looking at other examples they all did the same thing. I figured the mysqli_fetch_assoc just grabbed the row/record the value is in and turned it into an associative array. What should I be doing?

 

Nevermind, I've been having a massive brainfart. Changed it to this:

SELECT * FROM users WHERE email='examplar@gmail.com'

Now works! Thank you for helping me

Edited by MattL019

Never ever put variables in a query. You need to use Prepared Statements. I recommend you use PDO. Do not SELECT *, explicitly specify the columns you want. And of course, you have already set the email column as unique right? Right?

The email column is not unique but my signup form does not allow you to sign up with the same email twice. I am not sure what a prepared statement is, so I am going to check out the link you provided (thank you). Why shouldn't I input variables into a query?

I suggest you post your signup form. Whatever you are doing, you are doing it wrong. Variables in the query can be vulnerable to SQL Injection. A Prepared Statement protects you from it.

 

You need to set a unique constraint on the database. You attempt the insert and capture the duplicate error. You do not check the DB if the email exists first. That will create a Race Condition where simultaneous requests will both get the OK to insert. In your case, you would end up with duplicate emails.

I suggest you post your signup form. Whatever you are doing, you are doing it wrong. Variables in the query can be vulnerable to SQL Injection. A Prepared Statement protects you from it.

 

You need to set a unique constraint on the database. You attempt the insert and capture the duplicate error. You do not check the DB if the email exists first. That will create a Race Condition where simultaneous requests will both get the OK to insert. In your case, you would end up with duplicate emails.

Alright. Keep in mind, I'm very new to PHP, and made this sign-up form from reading scraps from the PHP documentation and random bits of tutorials. I'm fully aware I'm doing some stuff the wrong way.

 

signup form = https://pastebin.com/CkY7GWx0

I will start from the top down.

 

All the Php should be at the top, All the Html below that.

 

Remove the form action completely

 

The errors should be an array which you would initialize one time with an empty array. $error = [];

 

Do not depend on the name of a input for your script to work. Check the server REQUEST METHOD instead.

 

Do not create variables for nothing. You already have the POST array. Just use it.

 

You would be better off using PDO with prepared statements. As previously mentioned you do not check if the email exists. Just attempt the insert in the unique column and capture the duplicate error if any.

 

Do not use md5. You need to use password_hash and password_verify.

 

Variables do not ever go in the query. Use Prepared Statements

 

Feel free to use the short echo syntax. <?= $somevar ?>

 

Your password "validation" is messed up and redundant.

 

When you get down on the basics you should spend some time learning TWIG Templating. At the least, you could put the form portion in a separate file and include it. You will want to learn and understand "Separation of Concerns".

 

Post your code in the forum using the code tags.

Edited by benanamen
  • Like 1

Alright. I'm not too sure if this is entirely what you had meant, however these are the changes I have made.

<?php
$title = "The Last Laugh | Sign Up";

include "inc/header.php";

// Error variables
$errors = [
  'username' => false,
  'username_same' => false,
  'password' => false,
  'email' => false
];

if(isset($_POST['input-username'])) {
  // Username Validation
  if((trim($_POST['input-username']) !== $_POST['input-username']) || strlen($_POST['input-username']) < 5 || strlen($_POST['input-username']) > 20 || preg_match("[\W]", $_POST['input-username'])) {
    $errors['username'] = true;
  }

  $valid_username = mysqli_real_escape_string($link, $_POST['input-username']);
  $sql = "SELECT username FROM users WHERE username='$valid_username'";
  $result = mysqli_query($link, $sql);
  if(mysqli_num_rows($result) == 1) {
    $errors['username_same'] = true;
    $errors['username'] = true;
  }

  // Password Validation
  if((trim($_POST['input-pass']) !== $_POST['input-pass']) || $_POST['input-pass'] !== $_POST['input-repass'] || strlen($_POST['input-pass']) < 5) {
    $errors['password'] = true;
  }

  // Check for existing email...
  $valid_email = mysqli_real_escape_string($link, $_POST['input-email']);
  $sql = "SELECT email FROM users WHERE email='$valid_email'";
  $result = mysqli_query($link, $sql);
  if(mysqli_num_rows($result) == 1) {
    $errors['email'] = true;
  }

  if(!$errors['username'] && !$errors['password'] && !$errors['email']) {
    // No errors
    $valid_pass = password_hash($_POST['input-pass'], PASSWORD_DEFAULT);

    // Set session variables
    $_SESSION['username'] = "$valid_username";
    $_SESSION['email'] = "$valid_email";

    $query = mysqli_query($link, "INSERT INTO users (username, email, password) VALUES ('$valid_username', '$valid_email', '$valid_pass')");
    if($query) {
      header( 'Location: index.php' ) ;
    }

  }
}
?>
<!-- DIV: CONTENT -->

<div class="sign-up-form">
  <h1>Register an account</h1>
  <p>Already have an account? <a id="login-refer" href='login.php'>Log in.</a></p>
  <form method="POST">

    <!-- Username -->
    <label for='label_username'>Username</label><br>
    <input class='<?php if($errors['username']) echo "input-error"?>' type='text' id='label_username' name="input-username" value='<?php if(isset($_POST['input-username'])) echo $_POST['input-username'];?>'><br>
    <p class="input-rule">Must be between 5-20 characters and contain no special characters/spaces.</p>
    <?php if($errors['username_same']) echo '<p class="error-message">That username has been taken.</p>';?>

    <!-- Email -->
    <label for='label_email'>Email</label><br>
    <input class='<?php if($errors['email']) echo "input-error"?>' type='email' id='label_email' name="input-email" value='<?php if(isset($_POST['input-email'])) echo $_POST['input-email'];?>'><br>
    <p class="input-rule">Disposable emails will not work.</p>
    <?php if($errors['email']) echo '<p class="error-message">An account with that email has already been registered. <a id="login-refer" href="login.php">Log in.</a></p>';?>

    <!-- Password -->
    <label for='label_password'>Password</label><br>
    <input class='<?php if($errors['password']) echo "input-error"?>' type='password' id='label_password' name="input-pass" value='<?php if(isset($_POST['input-pass'])) echo $_POST['input-pass'];?>'><br>
    <p class="input-rule">Password must meet the following requirements:
      <ul class="input-rule-list">
        <li>5+ characters</li>
        <li>No special characters or whitespace</li>
      </ul>
    </p>

    <!-- Re-Type Password -->
    <label for='label_repassword'>Re-type Password</label><br>
    <input class='<?php if($errors['password']) echo "input-error"?>' type='password' id='label_repassword' name="input-repass" value='<?php if(isset($_POST['input-repass'])) echo $_POST['input-repass'];?>'><br>
    <p class="input-rule">Passwords must be matching.</p>

    <!-- Submit -->
    <input type='submit' value='Register'>

  </form>
</div>

<!-- END OF DIV CONTENT -->
<?php include "inc/footer.php" ?>

Here is a quick and dirty of some of what I mentioned. There is a bit more to it to do it all correctly. Search the forum for posts by Jaques1 and myself. The detailed info is already in the forum.

<?php

$display_error = false;

if ($_SERVER['REQUEST_METHOD'] == 'POST')
    {
    if (empty($_POST['username']))
        {
        $error['username'] = 'Username Required.';
        }

    if (empty($_POST['email']))
        {
        $error['email'] = 'Email Address Required.';
        }

    if (empty($_POST['password']))
        {
        $error['password'] = 'Password Required.';
        }
    if (empty($_POST['password_confirm']))
        {
        $error['password_confirm'] = 'Confirm Password Required.';
        }
    elseif ($_POST['password'] != $_POST['password_confirm'])
        {
        $error['password_confirm'] = 'Passwords do not match.';
        }

    if ($error)
        {
        $display_error = true;

        }
    else
        {
        //Attempt insert. Capture duplicate email error if any.
        }
    }

if ($display_error)
    {
    foreach ($error as $v)
        {
        echo "$v<br>";
        }
    }
?>
<form method="POST">
<input type="submit" value="Submit">
</form>
  • Like 1
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.