0

I started this little blog project and I think I have just made a mistake by not including fetch_assoc method. This is the code:

$data = new database();
$sql = "SELECT * FROM post ";
 $article = $data->select($sql);
 foreach ($article as  $value) : ?>
 <div class="blog-post">
<h2 class="blog-post-title"><?= $value["blog_title"]; ?></h2>

and this is how the select methode look like:

public function select($sql){
     $result = $this->con->query($sql) or die($this->con->error.__LINE__);
     if ($result->num_rows > 0) {
        return $result;
     }else {
       return false;
     }
}

I want to know why it has worked for me (the title of the blog shows up correctly) although I have forgotten to put the fetch_assoc method?

Dharman
  • 30,962
  • 25
  • 85
  • 135
Fares Ars
  • 7
  • 2

1 Answers1

0

You do not need to use fetch_assoc() most of the time. If you are writing some kind of abstraction class around mysqli then you should never need to use any of mysqli functions directly.

mysqli:query() returns an object of type mysqli_result which is iterable. This means you can use foreach loop to iterate over it.

I need to point out that you are still following some bad programming practices. You should never use or die($this->con->error.__LINE__). This is a terrible coding practice and completely unnecessary. Instead, you should enable proper error reporting. See How to get the error message in MySQLi?

Your select() method should return only an array. This would make your code much easier and less error-prone. So rewrite your select() function to this:

public function select($sql){
    return $this->con->query($sql)->fetch_all(MYSQLI_ASSOC);
}

As you can see the whole functionality is a single line of code, which means your select() method is not very useful. You can replace it with something more generic instead. This way you avoid a lot of code repetition.

public function executeQuery(string $sql, array $params = []): ?array {
    // Prepare/bind/execute
    $stmt = $this->con->prepare($sql);
    if ($params) {
        $stmt->bind_param(str_repeat("s", count($params)), ...$params);
    }
    $stmt->execute();
    // If it was a select query which gives result then return results in an array
    if ($result = $stmt->get_result()) {
        return $result->fetch_all(MYSQLI_BOTH);
    }
    // If it is INSERT/UPDATE then return null instead of array
    return null;
}

Of course this method should not be part of your model. It should be part of a dedicated class for database communication. You can then create a single instance of it in your application and pass it to your model.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • thanks @Dharman for your reply but ,`bind_param(str_repeat("s",count($params)), ...$params) ` we can have other things like integer, so we need **d** instead of **s** and for ``$params`` i think we need a loop for having all the parameters putted as an array in the ``executeQuery methode`` – Fares Ars Jul 04 '20 at 23:44
  • @FaresArs 99.99% of the time you don't need anything other than string. But if you do need to specify the type manually then I recommend reading this short article: https://phpdelusions.net/mysqli/simple – Dharman Jul 04 '20 at 23:46