PHP 使用 SQLite 测试 JSON Contains

Shi*_*hiv 2 php mysql sqlite json laravel

我的 Web 应用程序使用 Laravel 和 MySQL,但对于我的测试,我在内存中使用 SQLite。

这是我在控制器中使用的代码:

$opportunities = DB::table('opportunities')
        ->whereRaw('JSON_CONTAINS(businesses, \'"' . $business . '"\')')
        ->get();
Run Code Online (Sandbox Code Playgroud)

测试时会抛出异常,因为 SQLite 没有 JSON_CONTAINS 函数。我怎样才能解决这个问题,以便我的测试通过并且不必对结构进行任何大规模更改?SQLite 是否有这样的功能或类似的功能?

谢谢

小智 9

对已接受答案的更多解释:

/**
 * Call this method in your test. 
 * @PHP 7.4+
 */
private function setupSqlite(): void
{
    DB::connection()->getPdo()->sqliteCreateFunction('JSON_CONTAINS', function ($json, $val, $path = null) {
        $array = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
        // trim double quotes from around the value to match MySQL behaviour
        $val = trim($val, '"');
        // this will work for a single dimension JSON value, if more dimensions
        // something more sophisticated will be required
        // that is left as an exercise for the reader
        if ($path) {
            return $array[$path] == $val;
        }

        return in_array($val, $array, true);
    });
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这个查询,它适用于 mysql/mariadb 和 sqlite:

$result = Product::whereRaw('JSON_CONTAINS(tags, \'"' . $tag . '"\')')->get();
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,我使用简单数组搜索 json 列:

$column = ["example", "test", "simple"];
Run Code Online (Sandbox Code Playgroud)


Nic*_*ick 6

您可以JSON_CONTAINS在测试期间使用sqlite_create_function例如进行模拟

function json_contains($json, $val) {
  $array = json_decode($json, true);
  // trim double quotes from around the value to match MySQL behaviour
  $val = trim($val, '"');
  // this will work for a single dimension JSON value, if more dimensions
  // something more sophisticated will be required
  // that is left as an exercise for the reader
  return in_array($val, $array);
}

sqlite_create_function(<your db handle>, 'JSON_CONTAINS', 'json_contains');
Run Code Online (Sandbox Code Playgroud)

您可能还想模拟可选的第三个参数,JSON_CONTAINS例如

function json_contains($json, $val, $path = null) {
  $array = json_decode($json, true);
  // trim double quotes from around the value to match MySQL behaviour
  $val = trim($val, '"');
  // this will work for a single dimension JSON value, if more dimensions
  // something more sophisticated will be required
  // that is left as an exercise for the reader
  if ($path)
    return $array[$path] == $val;
  else
    return in_array($val, $array);
}
Run Code Online (Sandbox Code Playgroud)