-2

I'm trying to retrieve all records from a sql table and return it as json, however it keep return nothing, even though the sql query return several rows in phpMyAdmin. I've even tried inside the loop to just output all the $id which work fine however when I return it as an array it just return an empty page. I don't know if this can be caused by the $image, which in the database is a blob.

<?php
error_reporting(-1);
ini_set('display_errors', 'On');

include('config.php');
$stmt = $db->prepare('SELECT * FROM camps');
$stmt->execute();
$stmt->bind_result($id, $title, $body, $long, $lat, $img);

$rows = array();
while ($stmt->fetch()) {
  $rows[] = array(
    'id' => $id,
    'title' => $title,
    'body' => $body,
    'long' => $long,
    'lat' => $lat,
    'image' => $img
  );
  echo $img;
}

$stmt->close();
$db->close();
echo json_encode($rows);
?>
t.niese
  • 39,256
  • 9
  • 74
  • 101
Peter Pik
  • 11,023
  • 19
  • 84
  • 142
  • You have exactly 6 columns in your table? It would be better to list the column names explicitly in your `select` statement. – trincot May 15 '16 at 19:54
  • I think your problem might be with `json_encode`. Do you get an output if you just `print_r ($rows);`? – trincot May 15 '16 at 20:00
  • the manual does have a `SELECT *` method example http://php.net/manual/en/mysqli-stmt.bind-result.php but not like you're trying to use it here. Look under where it starts off as *"lot of people don't like how bind_result works with prepared statements!..."* – Funk Forty Niner May 15 '16 at 20:04
  • Have you tried to show every fields except the image one? Just to be sure it's not a problem with the blob. You could try with base64_encode() aswell. – nanocv May 15 '16 at 20:05
  • 1
    @Terry, what makes you say that? From what I see, all the used methods are (also) exposed by `mysqli`, but maybe I am missing something? – trincot May 15 '16 at 20:14
  • @trincot looking at the OP's code again, am under the impression that it could be as simple as their closing too early when they're trying to `echo json_encode($rows);` which should be above the closing `$stmt->close(); $db->close();` – Funk Forty Niner May 15 '16 at 20:19
  • I was actually thinking of a character encoding problem, because `json_encode` can return `false` in that case, and that would render as the empty string. But like often, we're having a nice discussion here ... without the OP :D – trincot May 15 '16 at 20:21
  • @trincot I just tested OP's code in my server and got back `Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement in...` yet I did get a JSON output. So my answer is partially correct. So whoever dv me, needs to retract it. I'm not saying it's you ;-) – Funk Forty Niner May 15 '16 at 20:27
  • Tell us Peter, where are you in all this? Everybody else is saying something in regards to my answer but getting downvoted it *lol*. I'm not deleting my answer because I know I'm right about it. – Funk Forty Niner May 15 '16 at 20:32
  • @r3wt what they have now is valid syntax, I've tried it just a few minutes ago. Just not for the image column. – Funk Forty Niner May 15 '16 at 22:05
  • @Fred-ii- i stand corrected. i'm apalled by how obviously wrong this is. it should not be possible for mysqli to declare variables into the scope of the while loop, thats very dangerous. what about the case where a column name is the same as an already defined variable? how about the case where a column has a dash or dot in its name. – r3wt May 15 '16 at 22:10
  • 1
    @r3wt I agree. Well... I'm almost ready to give up on the question seeing that I've gotten no response from the OP; just comments and a downvote by others. Oh well, what can you do except try to help. *"C'est la vie"*. – Funk Forty Niner May 15 '16 at 22:12

1 Answers1

1

Edited: You can't bind on a SELECT * statement unless the number in the bind_result() matches the total number of columns you have in your database. Otherwise, you must choose all the columns and to match the number of columns in your query as in your bind_result(). Also consult the link below on how to show images from a database.

(I've got broad shoulders and will admit my mistake. Nobody learns anything without making any, and I for one have learned something today).

Reference:

Having checked for errors in your query, would have thrown you something about it, should it be the case.

The manuals states:

Note that all columns must be bound after mysqli_stmt_execute() and prior to calling mysqli_stmt_fetch(). Depending on column types bound variables can silently change to the corresponding PHP type.

So, what am I not getting here? Maybe they should rewrite it then since they came up with it.


Edit: test

After testing what the OP posted for code on my own server running under PHP Version 5.6.21, got back:

Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement in...

when using SELECT * FROM table

yet did give back a JSON result.

Using SELECT col1, col2 FROM table did not throw that error.

Also, you're trying to echo an image from your database; you can't do that with JSON, you need to use a different method.

See the following question on Stack about how to echo an image from db:

So your $img would look something like:

echo '<img src="data:image/jpeg;base64,'.base64_encode( $img ).'"/>';

which is something that I have successfully tested with.

  • There is something you need to know though, and that is to make sure that each of those rows has an image for them, otherwise there stands to be broken image icons for the ones that don't contain an image (blob).

If that's the case, you would need to limit it to a WHERE clause then.

NOTA: Using blobs can dramatically increase the size of your database. Ideally, saving the files in a folder and its path to it in the database is a method preferred by many. However, that choice is entirely yours.


Consult the comments under the answer.

There isn't anything I can add to this.

Community
  • 1
  • 1
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
  • Are you sure about that? I think `select *` can be used with result binding. – trincot May 15 '16 at 19:59
  • Actually you can. I do it every time and it's absolutely correct. – nanocv May 15 '16 at 19:59
  • @trincot I am 100% sure of it. – Funk Forty Niner May 15 '16 at 19:59
  • @nanocv Funny that, I never saw one that worked before. So why don't you post your own answer then? – Funk Forty Niner May 15 '16 at 20:00
  • @trincot http://stackoverflow.com/questions/37242960/mysqli-prepare-wont-output-as-json#comment62014830_37242960 you even said it yourself lol – Funk Forty Niner May 15 '16 at 20:00
  • Because I just don't know where is the error in the code, but this is not at all – nanocv May 15 '16 at 20:00
  • 1
    @Fred-ii-, I merely wanted to exclude the risk of a column count mismatch. It was not because I thought `*` was not allowed. I even see user comments on the PHP page that use it. That is no guarantee of course. I cannot test it myself for the moment... NB: I did not dv. – trincot May 15 '16 at 20:02
  • @trincot I did see a `SELECT *` method in the manual but not used like the OP's doing here, which is entirely a different animal here. – Funk Forty Niner May 15 '16 at 20:06
  • 1
    @Fred-ii-, [here](http://stackoverflow.com/a/750686/5459839) is a better example that strongly suggests it works. – trincot May 15 '16 at 20:07
  • @trincot Oh for sure and I agree because they're using a prepared statement and a WHERE clause and as per what I saw in the example from the one that worked in the manual, the OP isn't which is what is different here, but somebody disagrees with me. *sigh* – Funk Forty Niner May 15 '16 at 20:09
  • 1
    I build a test case using php 7 , a `$db->prepare('SELECT * FROM camps');` and `$stmt->bind_result($id, $title, $body, $long, $lat, $img);` and it works without any problem. So `bind_result` with `SELECT * FROM` is not a problem. At least not in php 7. – t.niese May 15 '16 at 20:12
  • @t.niese If there's something different in PHP 7 and lets us do that, then I am unaware of it and unable to test that under that environment unfortunately. You say it works, I believe you. However if that method isn't supported in previous versions, then the OP may need to use a prepared statement with a WHERE clause. If I'm completely wrong about what I have said so far and edited my answer about that, I will gladly delete my answer. – Funk Forty Niner May 15 '16 at 20:14
  • [Here](http://stackoverflow.com/questions/22823284/how-to-use-bind-result-instead-of-get-result-in-php) are some people who agree with you. :-) – trincot May 15 '16 at 20:19
  • @nanocv You're going to need to show proof of that, because my recent testing on this proved otherwise, as per my **Edit**. So.. if you have something to share that we/I don't know about, you will need to put your money where your mouth is *lol* (it's just an expression) to "show us the money" ;-) – Funk Forty Niner May 15 '16 at 20:34
  • @t.niese Same here as I made an edit to that effect. Yet, the OP's nowhere to be found here and have no idea where to throw myself here *lol*. Oh well, I'll leave this up for a while till the OP comes out of wherever they are. If the img blob is the issue, then they'll need to elaborate on their question. There's nothing really that I can add to my answer/commments, not till I know where that guy is. Edit: You deleted your comment I was responding to. – Funk Forty Niner May 15 '16 at 20:39
  • 1
    Out of curiosity I tested it with 5.4 and 5.5 and on two different OS, and there it also works. Only if variable count does not match the column count then I get the error `Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement` error. But if the variable count matches then it is valid. So `You can't bind on a SELECT * statement, you must choose all the columns` is wrong, you can bind to `SELECT *` but only if the variables match the column count. Anyhow binding on `SELECT * ` is a bad idea because of that. – t.niese May 15 '16 at 20:40
  • @t.niese Ah I see, thank you. Leave your comment here and see if the OP sees it. I'm doing my best to help out as you and others do and really like to get this one resolved, *cheers* – Funk Forty Niner May 15 '16 at 20:43
  • @t.niese You were right about your last comment (just tested that now) and I for one have learned something today. I've made an edit to the answer to that regard. Thanks again for your input. – Funk Forty Niner May 15 '16 at 22:02
  • @Fred-ii- It turns out I was right and your "Funny that" was a bit rude, don't you think so? We all are humans and sometimes everybody can be wrong... and it's ok. I commented your answer because I do it everytime and it works! You just have to be sure the number of your database columns matches with the bind_result variables number. – nanocv May 15 '16 at 22:39
  • 1
    @nanocv why do you say I was rude? I've went through the comments and can honestly say I wasn't. But yes, you and everyone else who made a comment about that were right and I have admitted to my mistake ;-) Nobody learns anything without making them, as human as we all are. Show me someone who never made a mistake and I'll show you someone who never learned a thing. This doesn't just apply to coding, but to the whole spectrum of our daily lives ;-) – Funk Forty Niner May 15 '16 at 22:43
  • Great Explanation `:)` – Nana Partykar May 17 '16 at 13:51