1

I'm dealing with a method in my DAO which looks up an ID to an entry. In this case, an author. The user-entered data often contains two names as an author entry (old data migrated over not updated yet) like so:

Berenstain, Stan & Jan

The code works flawlessly when looking up something like this:

Aiger-Clark, Julie

But it fails every time there is an & in the author name. Copying and pasting the author into PhpMyAdmin in a search finds the author.

I've verified that $authorName is actually the correct name:

Berenstain, Stan & Jan

I've verified that this fails in both a prepared statement and a normal query. I've also confirmed that it fails with more than one author entry, the common failure point seemingly being the authors containing the & sign. All other tried lookups succeed.

I'm using a PDO connection. It's failing at the row count return point of this method (I have verified that rowCount works with MySQL).

This is the code as it sits:

public function getAuthorIDByName($authorName) {

    $dbConn = Connectors::pdoDatabaseConnect();

    $sql = "SELECT authorID FROM authors WHERE authorName=?";

    if (!$stmt = $dbConn->prepare($sql)) {
        return false;
    }

    if ($stmt->execute(array($authorName)) === false) {
        return false;
    }

    if($stmt->rowCount() != 1) {
        return false;
    }

    $obj = $stmt->fetch(PDO::FETCH_OBJ);
    return $obj->authorID;

}

I tried the following, and it failed:

$sql = "SELECT authorID FROM authors WHERE authorName = :authorName";

    if (!$stmt = $dbConn->prepare($sql)) {
        Log::logEndMethod();
        return false;
    }

    $stmt->bindParam(':authorName', $authorName, PDO::PARAM_STR);
    if ($stmt->execute() === false) {
       return false;
    }
TRiG
  • 10,148
  • 7
  • 57
  • 107
Dave
  • 592
  • 3
  • 15
  • 1
    This is a shot in the dark, but have you tried $stmt->bindParam(":authorName",$authorName); and then $stmt->execute()? – Rob Jul 22 '15 at 18:35
  • 1
    @Rob in that case then, they'd need to do `WHERE authorName=:authorName";` – Funk Forty Niner Jul 22 '15 at 18:40
  • 1
    @Fred, correct. I mistakingly figured that would be implied. – Rob Jul 22 '15 at 18:43
  • Best to read up on prepared statements Dave http://php.net/pdo.prepared-statements - you have 2 methods. – Funk Forty Niner Jul 22 '15 at 18:44
  • 1
    are you SURE it's `&` in the database, and not html-encoded as `&`? `A&B != A&B`, after all... – Marc B Jul 22 '15 at 18:45
  • Updated the suggested try if you see an error let me know I"ve never done it that way. – Dave Jul 22 '15 at 18:45
  • 2
    Check the output from `var_dump($authorName)` as copied from the browser page source, not as rendered on the screen. Do you have an errant call to `htmlspecialchars()` somewhere upstream of this which is actually modifying the input? It is likely either your input, or (less likely since phpmyadmin returns results) your stored values were entity encoded as `&amp`. – Michael Berkowski Jul 22 '15 at 18:47
  • band-aid option: use `LIKE`. – Funk Forty Niner Jul 22 '15 at 18:50
  • Tried LIKE, didn't work. The following line used in workbench returns the entry correctly >> select * FROM authors WHERE authorName = 'Berenstain, Stan & Jan' – Dave Jul 22 '15 at 18:56
  • var_dump response: string(26) "Berenstain, Stan & Jan" – Dave Jul 22 '15 at 19:01
  • What's the collation on the db/table/column? – Rob W Jul 22 '15 at 19:06
  • Also, what happens if you `bindValue()` instead? – Rob W Jul 22 '15 at 19:07
  • also try `$sql = "SELECT authorID FROM authors WHERE authorName='Berenstain, Stan & Jan'";` (not in workbench, but the query itself/PHP) and skip the binding stuff. If that works, then you'll know that it's something happening after that. – Funk Forty Niner Jul 22 '15 at 19:10
  • There is nothing to bind value to unless I'm not following. Nothing is returning from the database through this method... Let my try hard coding the author name into the method once and see what happens. – Dave Jul 22 '15 at 19:10
  • Progress... I hardcoded the name into the method. right after the connection in the above code I added $authorName = "Berenstain, Stan & Jan" and we get a find. Is it possible that this is a character type mismatch somehow? – Dave Jul 22 '15 at 19:14
  • Fred, that, or the equivalent of it as I stated above (sorry didn't see your comment before I tried just setting the variable name) worked. I'm currently tracing backwards. Thanks so much guys for your help. I'll post here in a bit if I get stuck, or find a solution. – Dave Jul 22 '15 at 19:21
  • You're welcome Dave. I wish I could have been of more help and would have been nice to find the real issue that is causing this to fail. you can specify charset in the DSN: `$dbConn = new PDO('mysql:charset=utf8mb4');` it could be a charset issue. http://php.net/manual/en/ref.pdo-mysql.connection.php – Funk Forty Niner Jul 22 '15 at 19:32
  • @Fred I think charset is what we're coming too. I let the database use the default when I created it (live and learn) and it turned out to be latin1_sweedish_ci **BOGGLE** so, some questions. View is using utf8, I'm passing in using json, it's decoded, then dumped into a book object. It all works until this lookup. Couple questions. If I change the colation on the column will it update existing data? would forcing it on the connection as suggested above, be a valid work around? Looking for suggestions on how to straighten this mess out. – Dave Jul 22 '15 at 19:44
  • It doesn't seem like a character encoding issue to me. The `&` character is part of ASCII, so unless you're using some other encoding like Big5 or whatever the Chinese encoding is in your PHP it doesn't seem like that would be the issue to me. – Mike Jul 22 '15 at 19:50
  • @Mike - Alright... That came up in another conversation actually too. Here is what I'm starting with. This is in the controller. first exposure of the data to PHP: {"group":"Library Books","bookID":2332,"title":"My Test Book","bookRef":"","location":"ABCs","format":"Book","categories":["ABCs"],"authors":["Berenstain, Stan & Jan"]} – Dave Jul 22 '15 at 19:55
  • TBH Dave, I didn't know this till now, but it seems like it will change your data if you change the collation. See this Q&A http://stackoverflow.com/q/5575491/ - see also http://stackoverflow.com/q/29067703/ – Funk Forty Niner Jul 22 '15 at 19:58
  • @Fred-ii- `latin1_swedish_ci` only uses single byte characters, so converting it to utf-8 should not produce any issues. The question you linked above is using `latin1_bin` – Mike Jul 22 '15 at 20:03
  • @Mike my mistake Mike, thanks for pointing that out. @ Dave: I found those links by doing/Googling "will table change when changing collation mysql". You can further your research from there. I hope this gets resolved, *cheers*. – Funk Forty Niner Jul 22 '15 at 20:06
  • I've converted a few relatively large `latin1_swedish_ci` columns to `utf8_general_ci` without any issues. But to be on the safe side, just do a backup first. – Mike Jul 22 '15 at 20:07
  • I'm almost certain I have the solution. It's so embarresing I don't even want to tell you BUT... In the name of education. I was dumping my results back to the browser and because I was "inspecting elements" I was assuming I was looking at the raw source. Most of you are probably already laughing. Out of frustration I dumped to a log file and guess what I found: {"group":"Library Books","bookID":2332,"title":"My Test Book","bookRef":"","location":"ABCs","format":"Book","categories":["ABCs"],"authors":["Berenstain, Stan & Jan"]} -- I think someone may have even mentioned this. – Dave Jul 22 '15 at 20:12
  • @Fred or Mike, you were both helpful in tracking this down. :) One of you make an answer and I'll accept it. And thanks again for your help, sorry to waste your time. – Dave Jul 22 '15 at 20:13
  • You're welcome Dave. Now, it would only be fair for you to submit an answer, or that we make a community wiki answer, rather than anyone gaining points from this. what do you think @Mike ? – Funk Forty Niner Jul 22 '15 at 20:17
  • @Fred-ii- We could do a community wiki. However I almost think that since that's the solution that it makes the question off topic to be honest. – Mike Jul 22 '15 at 20:23
  • Yeah the solution has nothing to do with the problem I was starting with... Though a new topic with a wiki page discussing the issue would be good somehow. Never done it and don't think I can with my low points. But I'd made an assumptiong I shouldn't have.. Someone else is boudn to do that. – Dave Jul 22 '15 at 20:27
  • @Mike Fair enough. TBH, I wouldn't know where to begin lol too many's been said. Copy/paste the entire comments? haha! – Funk Forty Niner Jul 22 '15 at 20:29
  • 1
    @Fred-ii- Posted. Feel free to edit it as you see fit. – Mike Jul 22 '15 at 20:33

1 Answers1

1

Since your table is latin1_swedish_ci it isn't likely that it is a character encoding issue so much as an html encoding issue. Try doing var_dump($authorName) to look at what you are putting into the query. If you are using your browser to view the output, make sure you look at the page source and not at the generated HTML. Or else issue a header("Content-type: text/plain") before any output is sent to the browser. You are likely putting & in the query instead of &.

Mike
  • 23,542
  • 14
  • 76
  • 87