1

Warning: count(): Parameter must be an array or an object that implements Countable in C:\xampp\htdocs\try\process.php on line 30.

That's what my code says. it seems so fine but when I press edit, this error shows. I don't understand. can someone point me out what happened in line 30?

here is my process.php

<?php
require("1password.php");
$id = 0;
$update = false;
$username='';
$password='';

 if (!session_id()) { session_start(); }
    $mysqli = new mysqli("localhost","root","","id7508046_isalon") or die(mysqli_error($mysqli));
    if(isset($_POST['save'])){
        $username = $_POST['username'];
        $password = $_POST['password'];
        $passwordHash = password_hash($password, PASSWORD_DEFAULT);
        $mysqli->query("INSERT INTO isalonusers (username, password) values ('$username', '$passwordHash')") or die($mysqli->error);
        $_SESSION['message'] = "New account saved!";
        $_SESSION['msg_type'] = "success"; 
        header("location: userlist.php");
    }
    if(isset($_GET['delete'])){
        $id = $_GET['delete'];
        $mysqli->query("DELETE FROM isalonusers WHERE user_id=$id") or die($mysqli->error());
        $_SESSION['message'] = "User Account Deleted!";
        $_SESSION['msg_type'] = "danger";
        header("location: userlist.php");
    }
    if(isset($_GET['edit'])){
        $id = $_GET['edit'];
        $update = true;
        $result = $mysqli->query("SELECT * FROM isalonusers WHERE user_id=$id") or die($mysqli->error());
        if(count($result)==1){
            $row = $result->fetch_array();
            $username = $row['username'];
            $password = $row['password'];
        }

    }
    if(isset($_POST['update'])){
        $id = $_POST['id'];
        $username = $_POST['username'];
        $password = $_POST['password'];
        $passwordHash = password_hash($password, PASSWORD_DEFAULT);
        $mysqli->query("UPDATE isalonusers SET username ='$username', password='$passwordHash' WHERE user_id=$id") or die($mysqli->error());
        $_SESSION['message'] = "User Account has been updated!";
        $_SESSION['msg_type'] = "warning";

        header("location: userlist.php");
    }

?>
Dharman
  • 30,962
  • 25
  • 85
  • 135
shiela mekelele
  • 51
  • 2
  • 10
  • 4
    `$result` is a boolean, which is why count doesn't work and throws that error. – bassxzero Feb 01 '19 at 15:49
  • what should I do sir? I am really new to php. – shiela mekelele Feb 01 '19 at 15:51
  • Try `if($result && count($result)==1)` – Richard87 Feb 01 '19 at 15:51
  • https://secure.php.net/manual/en/mysqli.query.php –  Feb 01 '19 at 15:54
  • 2
    **Warning:** Your code is vulnerable to SQL Injection attacks. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. **Never** insert unsanitised data directly into your SQL. The way your code is written now, someone could easily steal, incorrectly change, or even delete your data. – ADyson Feb 01 '19 at 15:55
  • 1
    Also **never** get your web app to login to the database as root. Root can do whatever it likes, so on top of the SQL injection vulnerabilities this just leaves your database an open book for hackers. Instead create a separate user account specifically for this application which has only the permissions it actually _needs_ in order to work properly. Don't even use the root account as a shortcut during development or testing, because you need to test your account permissions as well - otherwise when you go live you might have unexpected errors relating to the user account setup. – ADyson Feb 01 '19 at 15:55
  • Since you are new to PHP...if you found out how to code the above from some tutorial or examples, I suggest you find a better one which shows properly secure and up to date methods – ADyson Feb 01 '19 at 15:55
  • You have to fetch the result before if you want to apply a count on it; And if you want to access by doing $result["attributes"] you have to use the method fetch_assoc. http://php.net/manual/fr/mysqli-result.fetch-assoc.php – Nico Feb 01 '19 at 15:56
  • Also now would be a great time to [read the manual for mysqli_query()](http://php.net/manual/en/mysqli.query.php) - that method will return either `false` (if the query fails) or a [mysqli_result](http://php.net/manual/en/class.mysqli-result.php) which is an object. Neither of these are things you can count. What is the count of `false`, do you suppose? And how do you count an object? If you want to count the number of rows your query returned, then again, you can [find the correct function in the manual](http://php.net/manual/en/mysqli-result.num-rows.php) – ADyson Feb 01 '19 at 16:00
  • On the other hand, if you're trying to count how many rows were changed by an UPDATE or DELETE or INSERT query (as opposed to how many rows were returned from a SELECT query) you might want a [different function again](http://php.net/manual/en/mysqli.affected-rows.php). So as you can see, all of the information you need to complete your task is already available to you :-) – ADyson Feb 01 '19 at 16:01
  • Welcome on SO. Your error come from PHP 7.2 I guess. Before this version the `count()` function returned 0 if the given parameter was not countable. – Anthony Feb 01 '19 at 16:06
  • @AnthonyB true but you seem to be implying that that would be fine...however it still wouldn't give OP any useful info...they are still counting the wrong thing – ADyson Feb 01 '19 at 16:06
  • @bassxzero actually it's not necessarily `false`, although that's a possibility. Even if it returns a [mysqli result](http://php.net/manual/en/class.mysqli-result.php), that's not Countable either. The error will occur in either case. OP is counting the wrong thing (see the [answer below](https://stackoverflow.com/a/54482906/5947043) for the correct method. – ADyson Feb 01 '19 at 16:07
  • @ADyson I understand that the error is because the OP tried to count the boolean that the query returns. I would tell a bit about PHP 7.2 because if the OP runs its code on a server with PHP 7.0 the code may work. – Anthony Feb 01 '19 at 16:09
  • 1
    @AnthonyB actually according to the [manual](http://php.net/manual/en/migration72.incompatible.php) the only change in 7.2 was to start to emit the warning (note it's a warning not error so the code does't actually crash!)...the behaviour is still to return `1` (not `0` as you stated) if the variable passed into `count()` doesn't implement `Countable` (which has been around since PHP5). It will only output `0` if the value passed in is actually `null` (or of course, if it's an array with 0 items in it!). This is as per http://php.net/manual/en/function.count.php – ADyson Feb 01 '19 at 16:14
  • 1
    I am beginning to understand by looking at the code and really understanding itall in my good sirs. thank you for opening out on me. I have really needed your insights. – shiela mekelele Feb 01 '19 at 16:47

2 Answers2

1

As a matter of fact, you never need to count anything. This step is just redundant.

If you give it a bit of a thought, you can simply fetch your data first and then use it in the condition. What is much more important, you must use a parameterized query. So the code should be

$stmt = $mysqli->prepare("SELECT * FROM isalonusers WHERE user_id=?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
// here goes your problem with "count" 
$row = $result->fetch_array(MYSQLI_ASSOC)
if($row) {
    $username = $row['username'];
    $password = $row['password'];
}

Neither should you use that terrible practice with or die

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
0

How about this way with $result->num_rows?

if(isset($_GET['edit'])){
    $id = $_GET['edit'];
    $update = true;
    $result = $mysqli->query("SELECT * FROM isalonusers WHERE user_id=$id") or die($mysqli->error);
    if(isset($result->num_rows) && $result->num_rows > 0){
        $row = $result->fetch_array(MYSQLI_ASSOC);
        $username = $row['username'];
        $password = $row['password'];
    }
  }

See ref.: http://php.net/manual/en/mysqli.query.php

A l w a y s S u n n y
  • 36,497
  • 8
  • 60
  • 103
  • @shielamekelele [you can already read about it here](http://php.net/manual/en/mysqli-result.num-rows.php). As I've explained in my comments above, `$mysqli->query` just returns a result object (somewhere to hold the results), not the actual results themselves...to get at the results you have to actively fetch them, and to count the results you have to actively run the correct count function (i.e. `$result->num_rows` in this case) against the result object. And of course if `$result` happens to be `false` because the query failed, you can't count that either (and you'd better return an error) – ADyson Feb 01 '19 at 16:03
  • @shielamekelele please follow the link that sir **Adyson** posted on previous comment. Hope you'll understand then. – A l w a y s S u n n y Feb 01 '19 at 16:05