0

I'm writing a scope for a post resource with a text column to find posts containing a keyword. They keyword should match only if there is a space before and a space or typical punctuation mark afterward (.?!;,-)

Here's my scope method:

public function scopeContainsKeyword($query, $keyword) {
  return $query->where('post', 'LIKE', '% '.$keyword.' %')
               ->orWhere('post', 'LIKE', '% '.$keyword.'.%')
               ->orWhere('post', 'LIKE', '% '.$keyword.'!%')
               ->orWhere('post', 'LIKE', '% '.$keyword.';%')
               ->orWhere('post', 'LIKE', '% '.$keyword.',%')
               ->orWhere('post', 'LIKE', '% '.$keyword.'-%')
               ->orWhere('post', 'LIKE', '% '.$keyword.'?%');
}

This works perfectly if I comment out the orWhere with the question mark. However when that question mark is present, it is getting replaced with the value of the next parameter in the query (date values being checked with another scope), and the final parameter of the query isn't replaced and remains a question mark.

How do I escape this question mark to mark it as a literal question mark instead of a placeholder?

Things I've tried:

->orWhere('post', 'LIKE', DB::raw('\'% '.$keyword.'?%\''))

->orWhere('post', 'LIKE', '% '.$keyword.DB::raw('?').'%')

->orWhere(DB::raw('post LIKE \'% '.$keyword.'?%\'')

->orWhere('post', 'LIKE', '% '.$keyword.'\?%')

Nothing has worked. How do I get this to work?!

jdforsythe
  • 1,057
  • 12
  • 22
  • [Question mark operator in query](http://stackoverflow.com/a/29964037/1235698) – Marcin Orlowski Apr 02 '16 at 17:38
  • It's not really related - I'm not using JSONB and I'm not trying to use the question mark operator. I'm trying to use it inside a string literal as a literal question mark. – jdforsythe Apr 04 '16 at 11:08
  • And I don't get the downvote. I researched quite extensively to see if anyone else has tried this, asked on IRC, asked on Laravel forums, all to no avail. The question is quite clear. – jdforsythe Apr 04 '16 at 11:09

1 Answers1

0

From everything I've tried and a few others have tried helping me with, it seems like the question mark will always get replaced in the LIKE, however it does not get replaced in a REGEXP so this works (and is probably faster than the separate LIKE searches anyway):

public function scopeContainsKeyword($query, $keyword) {
  return $query->where('post', 'REGEXP', ' '.$keyword.'[ ?!,;\-\.\'"]');
}
jdforsythe
  • 1,057
  • 12
  • 22