14

I would like to get the complete result of a prepared statement as an array (key/value pairs) in order to later use it in a str_replace() function.

My table has three columns, an index and the fields "x1" and "x2". I used the following successfully:

$db = new mysqli("servername", "username", "pw", "dbname");

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) {
  $ps1->execute();
  $ps1->bind_result($search, $replace);
    $result = array();
    while ($ps1->fetch()) {
      $result[$search] = $replace;
    }
    $ps1->close();
}

However, I am thinking that there must be a simpler way, without a while loop, getting the complete result, not added up from single rows one by one.

I looked at other questions, and I came up with the following, but it doesn't work ("Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result"):

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) {
  $ps1->execute();
  $result = mysqli_fetch_assoc($ps1);
  return $result;
  $ps1->close();
}

I also tried $result = mysqli_fetch_all($ps1); with no success ( getting "Call to undefined function mysqli_fetch_all()").

BTW, I am using PHP 5.6.


ADDITION after some answers and discussion in comments concerning MYSQLND:

phpinfo() displays the following information in its mysqlnd section:

Loaded plugins: mysqlnd,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password,auth_plugin_sha256_password

Nimeshka Srimal
  • 8,012
  • 5
  • 42
  • 57
Johannes
  • 64,305
  • 18
  • 73
  • 130
  • 1
    Not sure why you get that error. You should use the OOP the whole way though. That function though, http://php.net/manual/en/mysqli-result.fetch-assoc.php, only returns 1 row still. Might try http://php.net/manual/en/mysqli-result.fetch-all.php. – user3783243 Jul 13 '18 at 12:21
  • Does http://php.net/manual/en/mysqli.error.php give any more information about why `$ps1` isn't a result object? – user3783243 Jul 13 '18 at 12:29
  • @user3783243 Thanks for answering! I tried `$result = mysqli_fetch_all($ps1);` with no success (" Call to undefined function mysqli_fetch_all()"). Sorry, I'm slow on this one. Would you have a piece of code that you could suggest? – Johannes Jul 13 '18 at 12:35
  • What PHP version are you using? Additionally I think you're still going to have issues with `$ps1` because based on that error it isn't a result object, try `printf("Errormessage: %s\n", $ps1->error);`. – user3783243 Jul 13 '18 at 12:41
  • 1
    I'm more a PDO user some this is leaving my area of expertise but looking at other forums/threads it appears `mysqlnd` needs to be configured – user3783243 Jul 13 '18 at 12:54
  • If I'm getting it right, on a query like this: `SELECT 'foo', 'bar'` you are expecting to get `$result['foo'] = 'bar'`? – Julio Jul 20 '18 at 12:01
  • As I wrote, as a result I would want an array containing key/value pairs consisting of x1 and x2 (all rows) – identical to the `$result` array in my first (working) code example, just without having to use a `while` loop. Apparently - as some answers already pointed out - this is not possible without the mysqlnd extension. So basically, I already have an answer, it's just not applicable in my case, since I have no access to the server configuration. – Johannes Jul 20 '18 at 19:23
  • I believe you have to use `$ps1->get_result()->fetch_all();`. Please see my answer :) – Nimeshka Srimal Jul 23 '18 at 14:55
  • Thanks to everybody who answered! To sum it up: Since I cannot use the mysqlnd extension/driver (which I can't install since I have no access to the server), the only possible solution for me is the code with the while loop which I already posted in my question. There was more than one answer telling me this, but the one who was first pointing that out (also in the comments) was @IVO GELOV , so that's who I awarded the bounty to. – Johannes Jul 24 '18 at 13:27

7 Answers7

2

There is indeed a simpler way. Please consider using array_column :

$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT x1, x2 FROM my_table";

if ($stmt = mysqli_prepare($link, $query)) {

    /* execute statement */
    mysqli_stmt_execute($stmt);

    /* get result object */
    $rows = mysqli_fetch_all(mysqli_stmt_get_result($stmt), MYSQLI_ASSOC);

    /* get formatted object */
    $result = array_column($rows, 'x2', 'x1');

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);

EDIT : updated answer to use procedural mysqli functions

JesusTheHun
  • 1,217
  • 1
  • 10
  • 19
1

Did you try something like this ?

$db = new mysqli("servername", "username", "pw", "dbname");

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) {
  $ps1->execute();
  $result = $ps1->fetchAll(PDO::FETCH_NAMED);
  $ps1->close();
}

UPDATE

I mean like this (in case you have installed the mysqlnd driver)

<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 150,5";

if ($stmt = mysqli_prepare($link, $query)) {

    /* execute statement */
    mysqli_stmt_execute($stmt);

    /* get result object */
    $result = mysqli_fetch_all(mysqli_stmt_get_result($stmt));

    /* close statement */
    mysqli_stmt_close($stmt);
}

/* close connection */
mysqli_close($link);
?>
IVO GELOV
  • 13,496
  • 1
  • 17
  • 26
  • 1
    Well: Your code uses PDO (which I don't), so I get `Call to undefined method mysqli_stmt::fetchAll() in ...` – Johannes Jul 17 '18 at 15:11
  • If you do not use PDO - then you have to iterate over the result set by yourself - exactly as shown in the official manual http://php.net/manual/en/mysqli-stmt.fetch.php – IVO GELOV Jul 17 '18 at 15:21
  • You mean like in the code I posted in the first part of my question?... – Johannes Jul 17 '18 at 15:25
  • Re: Your edit: That works for printing the result, but it's like in the first code example in my question (where I had to use a while loop to populate a new array): It doesn't give me an array with all key/value pairs in it which I can later use in a subsequent function. – Johannes Jul 17 '18 at 15:46
  • Does it suit now ? – IVO GELOV Jul 17 '18 at 15:52
  • `Fatal error: Call to undefined function mysqli_fetch_all()` – Johannes Jul 17 '18 at 15:57
  • I didn't write anything like that – Johannes Jul 17 '18 at 16:07
  • So you want to avoid the `while` loop - hence you need the `mysqli_fetch_all` function but it is only available for the `mysqlnd` driver. It seems a binary outcome to me - either install the driver or continue using a `while` loop like most of the other developers. – IVO GELOV Jul 17 '18 at 16:14
  • Unforunately, I have no rights to install anything on that server (shared webspace), I have to work with the given configuration and the few options it offers... – Johannes Jul 17 '18 at 16:17
  • Then apparently you have an answer to your question - the simpler way without a `while` loop requires the `mysqlnd` driver. – IVO GELOV Jul 17 '18 at 16:20
  • which unfortunately isn't possible in my case, but anyway: Thanks a lot for trying to help me! – Johannes Jul 17 '18 at 16:31
  • Out of curiosity - what is the problem with `while` ? Is it too slow or requires too much memory ? – IVO GELOV Jul 17 '18 at 16:41
  • There's no big problem. I don't have much experience (doing mainly frontend stuff), and I simply thought that since the result of a query probably is an array (is it?), there should be some way to directly get that array. Turns out it's more complicated than I thought... – Johannes Jul 17 '18 at 16:46
  • 1
    Complexity is often subjective :)) Even if the underlying connector library provides a way to get all the results at once - it is not necessarily available to the high-level language. It is a standard practice to iterate over the result set - just like we iterate over HTML table rows and cells. – IVO GELOV Jul 17 '18 at 17:28
1

This is how I fetch_all the results with prepared statements using mysqli

$stmt = $db->prepare("SELECT x1, x2 FROM my_table")
$stmt->execute();
$result = $stmt->get_result();
$allRows = $result->fetch_all(MYSQLI_ASSOC);
Accountant م
  • 6,975
  • 3
  • 41
  • 61
  • This gives me `Fatal error: Call to undefined method mysqli_stmt::get_result()...` – Johannes Jul 17 '18 at 15:54
  • 1
    @Johannes you probably don't have `mysqlnd driver` installed. Check this [answer](https://stackoverflow.com/questions/45001819/php-fatal-error-call-to-undefined-function-mysqli-stmt-get-result) – Accountant م Jul 17 '18 at 16:10
  • Unforunately, I have no rights to install anything on that server (shared webspace), I have to work with the given configuration and the few options it offers... – Johannes Jul 17 '18 at 16:17
  • In this case, and if your only concern is a "simpler code", why not include that fetching loop in a function and call it in your main code. May be there is other solutions but I'm sorry this is all I know – Accountant م Jul 17 '18 at 16:25
1

Excuse my english

I don't think that's possible because mysqli_fetch_assoc() takes a mysqli_result as an argument whereas mysqli->prepare->execute returns a mysqli_stmt object.

What you could do is use procedural way of JesusTheHun's answer or you can use $ps1 = $db->query($stmt) instead of prepare and execute and then pass it to $ps1->fetch_all(MYSQLI_ASSOC)

Example:

if($ps1 = $db->query("SELECT x1, x2 FROM my_table")) {
  $result = $ps1->fetch_all(MYSQLI_ASSOC);

  $ps1->close();
  return $result;
}

print_r($result);

PHP docs for mysqli

Saleh Mahmood
  • 1,823
  • 1
  • 22
  • 30
0

You may try to extend the mysqli_result class with a function like this:

public function my_fetch_keyval() {
    for ($result = array(); $tmp = $this->fetch_row();) {
        // Expecting 2 columns. 1st = Key; 2nd = Value
        $result[$tmp[0]] = $tmp[1];
    }
    return $result;
}

Then you may use it on your code:

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) {
    $ps1->execute();
    $my_assoc_array = $ps1->my_fetch_keyval();
    $ps1->close();
}
Julio
  • 5,208
  • 1
  • 13
  • 42
0

Edit: I went through your comments and other answers, and it's clear that you do not have the Mysql native driver.

If you do not wish to use mysqlnd, I believe you can't get rid of that while loop ;)

============================================================

It seems like you have missed one thing!

You need to call the get_result() method, and then fetch_all() on that object.

$db = new mysqli("servername", "username", "pw", "dbname");

if($ps1 = $db->prepare("SELECT x1, x2 FROM my_table")) {
    $ps1->execute();
    $result = $ps1->get_result()->fetch_all();
    //return $result;
    $ps1->close();
}

echo '<pre>';
print_r($result);

Also note that I have commented out the return statement as it terminates the execution of the script at that point.

Hope it helps :)

Nimeshka Srimal
  • 8,012
  • 5
  • 42
  • 57
0

From the previous answers (absence of the proper mysqlnd ext - there are two, one for the mysqli, and one for the PDO), we can conclude that you have two options, you can either use the prepared statements with a while loop or a standard query, but which returns your result as an associative array.

Since you don't have any parameters, you can safetly use the plain ole query, because:

a) There is no user input that you have to escape, there are no parameters in your statement, hence there is no security risk

b) Performance gains of the prepared statement are negligent if any because you are using it as a plain ole SQL query. Prepared statements come to shine when you reuse the same statement over and over again changing only the parameter values that you bind to it

So let's cut to the chase:

$conn = mysqli($host, $user, $pass, $dbname);

$query = $conn->query("SELECT x1, x2 FROM your_table");

$result = $query->fetch_assoc();

The result will be in the following format:

[
   'x1' => 'v1',
   'x2' => 'v2'
]

If you need the whole dataset and not just one item, then use the following:

$result = $query->fetch_all(MYSQLI_ASSOC);

The result will look like this:

[
    [
      'x1' => 'v1',
      'x2' => 'v2'
   ],
   [
     'x1' => 'v1',
     'x2' => 'v2'
   ],
   ...
]

UPDATE

Now I see that mysqli::fetch_all throws an error as well for you, then I'm afraid there is no way to fetch the whole dataset without a loop. If you want an alternative to your approach maybe something like this:

$query = $conn->query("SELECT x1, x2 FROM your_table");

$results = [];
for ($i = 0; $i < $query->num_rows; $i++) {
    $row = $query->fetch_assoc();
    $results[$row['x1']] = $row['x2'];
}

Or this:

while($row = $query->fetch_assoc()) {
   $results[$row['x1']] = $row['x2'];  
}

But to be honest, then you might as well go with your initial way, it's the best approach if you don't have the mysqli::fetch_all available

Sasa Blagojevic
  • 2,110
  • 17
  • 22