0

I have a referral application where an ID can only have 2 direct referrals. I am trying to find IDs which appear less than 2 times in the ID_REF field with the code below.

$stmt = $conex->prepare("SELECT id FROM tb_modules WHERE count(id_ref) < ? ORDER BY id DESC LIMIT 1"); $stmt->bind_param("s", $n); $n = 2; $stmt->execute(); $stmt->store_result(); $numrows = $stmt->num_rows; $stmt->bind_result($id); //$stmt->fetch(); $stmt->close(); //echo $id.' '.'oi'; while ($stmt->fetch()) { echo $id; } 

enter image description here

10
  • Thanks @showdev I could not find it yet. May be something wrong with my logic. =/ Commented Jun 15, 2015 at 23:36
  • Are you using MySQLi? It might be helpful to see if any error messages are generated. See mysqli_error. Commented Jun 15, 2015 at 23:40
  • I'd say the $conex handle should be tossed into var_dump(). That will tell you what kind of datatype PHP sees it as being. Commented Jun 15, 2015 at 23:52
  • conex is ok but the var_dump($stmt) is returning false Commented Jun 16, 2015 at 0:25
  • 1
    WHERE is applied before the group, so you need to use GROUP BY id HAVING COUNT(id_ref) < ? rather than invoking WHERE. Commented Jun 16, 2015 at 1:03

3 Answers 3

1

You aren't checking for any errors, that is completely bad development. You should start by ensuring that your prepare() is actually preparing the query correctly and not failing...

$stmt = $conex->prepare("SELECT id FROM tb_modules WHERE count(id_ref) < ? ORDER BY id DESC LIMIT 1"); // now check if(!$stmt) { die($conex->error); // or mysqli_error($conex); } else { $stmt->bind_param('s', $n); } 

Back to other matters. You seem to be trying to compare count(id_ref) which would be a number (int) against $n (which is an int too) but you're trying to pass it as a string.....?

You'll need to change that bind of yours to something like:

$stmt->bind_param('i', $n); 

Also note, you can't set the $n variable after you call it.... that's going to throw an error.

Sign up to request clarification or add additional context in comments.

Comments

0

Do the following:

var_dump($conex); $stmt = $conex->prepare("SELECT id FROM tb_modules WHERE count(id_ref) < ? ORDER BY id DESC LIMIT 1"); var_dump($stmt) 

This should shed some light on the matter. I'm betting the $stmt variable is bool or null.

4 Comments

That's obvious. You could've posted that as a comment. You should alternatively edit your answer to attempt to answer the question. I.e. - if(!$stmt) { echo 'the error...'; } else { bind the query.... }
I'll keep that in mind, but I think teaching robust coding techniques is beyond the scope. If not, why stop there? Tell him to set the mysqli_options so that only exceptions are thrown? Then it can be done with try\catch\finally.
Remember, you're here to answer the question, not tell him how to debug it ;-) But i completely understand where you are coming from. If people followed the manual, they'd see how to achieve this properly!
Thankfully, I don't have to care about opinions of the sheep while answering.
0

Your code isn't checking whether prepare returned successfully.

If the prepare encounters an error, it returns FALSE. instead of a statement object.

And a boolean FALSE value (the return from prepare) does not have a method/function bind_param.

 $stmt = $conex->prepare("..."); if(!$stmt) { echo "error in prepare ". mysqli_error($conex) ; } else { // prepare returned a statement object so we can do a bind_param $stmt->bind_param(...); 

To fix a syntax issue in the SQL statement that's causing an error in prepare, replace they keyword WHERE with keyword HAVING.

The predicates (conditions) in the WHERE clause are evaluated when rows are accessed. So the result of an aggregate function (e.g. COUNT() is not going to be available at the time those conditions in the WHERE are check. There's no way for that condition to be evaluated until after the rows are accessed, and the aggregate functions are evaluated. Predicates (conditions) in the HAVING clause get evaluated later, so it's valid to reference aggregates in a HAVING clause.

Just making that change to the SQL statement isn't likely going to get you the result you are looking for. Without a specification, we're just guessing what you are trying to return.

3 Comments

Implement using exceptions only. It's more elegant that way. :-)
@AnthonyRutledge: Implement using ORM, Spring framework Java. It's more elegant that way. :-)
Stay close to true knowledge. Be strong. Resist framework debauchery. ;-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.