Escape LIKE metacharacters

parent 63efa539
......@@ -42,6 +42,9 @@ use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\TransactionIsolationLevel;
use Doctrine\DBAL\Types;
use Doctrine\DBAL\Types\Type;
use function sprintf;
use function strlen;
use function strtr;
/**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
......@@ -3578,4 +3581,27 @@ abstract class AbstractPlatform
{
return "'";
}
/**
* Escapes metacharacters in a string intended to be used with a LIKE
* operator.
*
* @param string $inputString a literal, unquoted string
* @param string $escapeChar should be reused by the caller in the LIKE
* expression.
*/
final public function escapeStringForLike(string $inputString, string $escapeChar) : string
{
$replacePairs = [$escapeChar => $escapeChar.$escapeChar];
foreach ($this->getLikeWildcardCharacters() as $wildcardChar) {
$replacePairs[$wildcardChar] = $escapeChar.$wildcardChar;
}
return strtr($inputString, $replacePairs);
}
protected function getLikeWildcardCharacters() : iterable
{
return ['%', '_'];
}
}
<?php
namespace Doctrine\Tests\DBAL\Functional;
use Doctrine\Tests\DbalFunctionalTestCase;
final class LikeWildcardsEscapingTest extends DbalFunctionalTestCase
{
public function testFetchLikeExpressionResult() : void
{
$string = '_25% off_ your next purchase \o/';
$escapeChar = '£';
$stmt = $this->_conn->prepare(sprintf(
"SELECT '%s' LIKE '%s' ESCAPE '%s' as it_matches",
$string,
$this->_conn->getDatabasePlatform()->escapeStringForLike($string, $escapeChar),
$escapeChar
));
$stmt->execute();
$this->assertTrue((bool) $stmt->fetch()['it_matches']);
}
}
......@@ -1468,4 +1468,12 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
array(array('precision' => 8, 'scale' => 2), 'DOUBLE PRECISION'),
);
}
public function testItEscapesStringsForLike() : void
{
self::assertSame(
'\_25\% off\_ your next purchase \\\\o/',
$this->_platform->escapeStringForLike('_25% off_ your next purchase \o/', '\\')
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment