PHP Error in Kevin Yank Book Novice to Ninja PHP & MySQL, Chapter 7

Chapter 7 page has this code on page 274;

function updateJoke($pdo, $fields) {
    $query = ' UPDATE `joke` SET ';
    foreach ($array as $key => $value) {
        $query .= '`' . $key . '` = :' . $key . ','
}
    $query = rtrim($query, ',');
    $query .= ' WHERE `id` = :primaryKey';
    // Set the :primaryKey variable
    $fields['primaryKey'] = $fields['id'];
    query($pdo, $query, $fields);
}

When I refresh my page, I get an error. When I remove this line;

 foreach ($array as $key => $value) {
        $query .= '`' . $key . '` = :' . $key . ','
}

Page loads normal. I was told to put a semi-colon at the end of the query ie;

 foreach ($array as $key => $value) {
        $query .= '`' . $key . '` = :' . $key . ',';
}

The page loads correctly but when I then try to use the code to update my form like;

updateJoke($pdo, [
            'id' => $_POST['jokeid'], 
            'joketext' => $_POST['joketext'],
            'aid' => $_POST['authorId']
            ]);

I get this error;

Invalid parameter number: number of bound variables does not match number of tokens in…

Please what am I doing wrong?

What is the error?

That semi-colon isn’t at the end of the query, it’s at the end of the line of PHP code. If you wanted to put it at the end of the query, you’d need to edit this line and put it inside the quotes, but I don’t think MySQL needs it:

$query .= ' WHERE `id` = :primaryKey';

What is in $query and $fields when you dump them for debugging?

Bruh, am now learning this thing :grinning: what is dump them for debugging? :laughing:

When I refresh my page, there’s no php related error, just the usual page cannot be displayed error.

This is the full code

function query($pdo, $sql, $parameters = []) {
    $query = $pdo->prepare($sql);
    $query->execute($parameters);
    return $query;
}

function updateJoke($pdo, $fields) { 
    $query = ' UPDATE joke SET '; 
    foreach ($array as $key => $value) { $query .= '' . $key . ' = :' . $key . ',' }
    $query = rtrim($query, ','); 
    $query .= ' WHERE id = :primaryKey'; 
    // Set the :primaryKey variable 
    $fields['primaryKey'] = $fields['id']; 
    
    query($pdo, $query, $fields); 
}

The error I get initially is

" This page isn’t working
localhost is currently unable to handle this request.
HTTP ERROR 500"

        /* Initialize an array */
        $attribute_pairs = [];

        /* Create the prepared statement string */
        foreach ($fields as $key => $value)
        {
            if($key === 'id') { continue; } // Don't include the id:
            $attribute_pairs[] = "{$key}=:{$key}"; // Assign it to an array:
        }

        /*
         * The sql implodes the prepared statement array in the proper format
         * and updates the correct record by id.
         */
        $sql  = 'UPDATE joke SET ';
        $sql .= implode(", ", $attribute_pairs) . ' WHERE id =:id';

        /* Normally in two lines, but you can daisy chain pdo method calls */
        $pdo->prepare($sql)->execute($fields);

        return true;

I think the first problem is you’re not setting the proper array $array ? $fields (I think it might be an infinite loop cause the HTTP ERROR 500?) and I would do everything in one function like the above. I don’t know if the above will work as I haven’t tested it out, but I think it should. I just thought I would give you some think about?

HTH John

That’s probably not helping - the function brings in an array called $fields, but the code uses an array called $array. But I wouldn’t expect that to cause an infinite loop, I’d expect either an error message, or for foreach() to just do nothing as there is no array or object to loop through. When I test it, I just get no fields in the query.

Have a look at the print_r() and var_dump() functions which will show you the contents of variables or arrays at the point that you call those functions. Sometimes it’s as easy to call echo, but you can’t do that on an array.

Prefix both functions with echo ‘<pre>’; because it adds linefeeds instead outputting the results in a single long string.

surely that should be $key and $value, not $key and $key…are you sure you’re copying the code correctly?

Which version of Novice to Ninja are you reading? The fact that you’re calling it “Kevin Yank Book” implies its no later than Version 5…

No, I think that’s intentional. The intended output for each is:

columnname = :columnname

so that when the array is passed in to query, the parameters work.

1 Like

oh sorry, 4AM, missed the colon. thought he was passing the whole “:columname” as key.

Makes more sense then. Still a dangerous way to formulate a query, but…

Hey, so am reading version 6? With Tom Butler. And interestingly after a couple more examples posted in the book, Tom/Kevin himself corrected the error but didn’t even speak about it so it’s quite confusing.

The book has a lot of errors and fixes which I don’t think even Kevin/Tom saw or knew about because they don’t talk about them. Am attaching two images to show you what I mean.

As you can see from the image above, the problem I was facing earlier has been corrected. In that, the code that was giving me the error

foreach ($array as $key => $value) { $query .= '`' . $key . '` = :' . $key . ',' }

has been corrected, albeit without any explanation;

foreach ($fields as $key => $value) { $query .= '`' . $key . '`,'; }

So I copy the full code but I get the same error again, so I read further to see if they correct this error and lo and behold they did and again didn’t acknowledge it. As you can see, the line;

$query = 'INSERT INTO `joke` ('

is missing a semi-colon. But when I scrolled down further, I see on page 261, that they have added the semi-colon to the code and everything works now.

It’s quite frustrating to say the least. But I guess I’ll just have to ignore errors as they happen and continue reading hoping they fix the error in their next code post.

I wonder if @TomB is around to comment …

It is frustrating, but it’s also quite an easy fix - you’ll be aware that virtually no line in PHP wouldn’t need a semi-colon on the end, so if you see one missing, you know it’s almost certain that it should have one.

Well, not for beginners. But thankfully this platform is there with brainiacs like yourself to assist. Thank you.

1 Like

Look at it this way - a missing semi-colon line end marker will almost certainly never catch you out again. :slight_smile:

2 Likes