Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 基于json的动态雄辩查询_Php_Laravel - Fatal编程技术网

Php 基于json的动态雄辩查询

Php 基于json的动态雄辩查询,php,laravel,Php,Laravel,我想根据数据库中的payloadjson动态查询 例如: $data = [{"key":"age","relation":">","value":"15"},{"operator":"OR"},{"key":"age","relation":"<=","value":"20"}] 问题是,它可以工作,但我不认为这是最好的方法。我找不到任何使用操作键的解决方案。操作员的用法是更改到何处或在何处 有什么解决方案或技巧可以让它像这样动态调用吗?。我希望我在DB的专栏简洁明了。我只能这样

我想根据数据库中的payloadjson动态查询

例如:

$data = [{"key":"age","relation":">","value":"15"},{"operator":"OR"},{"key":"age","relation":"<=","value":"20"}]
问题是,它可以工作,但我不认为这是最好的方法。我找不到任何使用操作键的解决方案。操作员的用法是更改到何处或在何处

有什么解决方案或技巧可以让它像这样动态调用吗?。我希望我在DB的专栏简洁明了。我只能这样想


谢谢

您可以这样进行原始查询

$data = '[{"key":"age","relation":">","value":"15"},{"operator":"OR"},{"key":"age","relation":"<=","value":"20"}]';

$query = "SELECT * FROM tablename WHERE";

$payload = json_decode($data, true);

foreach ($payload as $value) {
    if (isset($value['operator'])) {
        $query .= " " . $value['operator'];
    } else {
        if ($value['key'] == 'age') {
            $query .= " 'birthday' " . $value['relation'] . " " .  Carbon::now()->subYears($value['value'])->format('Y-m-d');
        }

        if ($value['key'] == 'gender') {
            $query .= " 'gender' " . $value['relation'] . " " . $value['gender'];
        }
    }
}
这将产生如下查询:

SELECT * FROM tablename WHERE 'birthday' > 2001-07-02 OR 'birthday' <= 1996-07-02

当然,您可能会使用printf进行格式化,并以其他方式使其更清晰,但这将使您满怀希望地开始工作。

您可以像这样进行原始查询

$data = '[{"key":"age","relation":">","value":"15"},{"operator":"OR"},{"key":"age","relation":"<=","value":"20"}]';

$query = "SELECT * FROM tablename WHERE";

$payload = json_decode($data, true);

foreach ($payload as $value) {
    if (isset($value['operator'])) {
        $query .= " " . $value['operator'];
    } else {
        if ($value['key'] == 'age') {
            $query .= " 'birthday' " . $value['relation'] . " " .  Carbon::now()->subYears($value['value'])->format('Y-m-d');
        }

        if ($value['key'] == 'gender') {
            $query .= " 'gender' " . $value['relation'] . " " . $value['gender'];
        }
    }
}
这将产生如下查询:

SELECT * FROM tablename WHERE 'birthday' > 2001-07-02 OR 'birthday' <= 1996-07-02
当然,您可以使用printf进行格式化,并以其他方式使其更清晰,但这将使您满怀希望地开始工作。

归根结底,这个想法是它自己的限制,因为存储的查询必须表示数据库的当前状态。这意味着,当数据以不同的方式存储时,这些查询的维护成本将是巨大的——如果将“生日”列更改为“出生日期”,则所有存储的查询都将中断。避免这种情况

相反,通过使用and将查询存储在模型上,可以更好地实现这一目标。如果您仍然需要请求的动态列表,您可以存储与查询相关联的关键字并循环查询。

归根结底,这个想法是它自己的限制,因为存储的查询必须表示数据库的当前状态。这意味着,当数据以不同的方式存储时,这些查询的维护成本将是巨大的——如果将“生日”列更改为“出生日期”,则所有存储的查询都将中断。避免这种情况


相反,通过使用and将查询存储在模型上,可以更好地实现这一目标。如果您仍然需要请求的动态列表,则可以存储与查询关联的关键字并循环查询。

您可以使用变量函数名添加orWhere逻辑:


只要您的json数据与您的数据库不匹配,即json有年龄,但数据库有生日,您将无法避免使用if/else语句。该自定义逻辑必须保留。

您可以使用变量函数名添加orWhere逻辑:


只要您的json数据与您的数据库不匹配,即json有年龄,但数据库有生日,您将无法避免使用if/else语句。这种自定义逻辑将不得不保留。

遇到这个问题,我同意。在这种方法中,您可以创建一个名为scopeJson的模型方法,或者任何您觉得更好的方法来处理其中的所有条件。我试图处理这里的大多数情况,而不仅仅是单一的地点和地点。我假设您的有效负载一次只包含一个生成器

public function scopeJson($query, $json)
{
    $wheres = [
        'between' => ['whereBetween', 'not' => 'whereNotBetween'],
        'null'    => ['whereNull', 'not' => 'whereNotNull'],
        'or'      => ['orWhere', 'not' => 'orWhereNot'],
        'in'      => ['whereIn', 'not' => 'whereNotIn'],
        'and'     => ['where', 'not' => 'orWhereNot'],
        'raw'     => 'whereRaw'
    ];

    $builder = json_decode($json);

    if (count($builder) > 0) {
        $query->where(
            $builder[0]->key,
            $builder[0]->relation,
            $builder[0]->value
        );

        // notBetween, notNull, notOr, notIn, notAnd
        if (stripos($builder[1]->operator, 'not') !== false) {
            $whereCondition = $wheres[strtolower(substr($builder[1]->operator, 3))]['not'];
        } else {
            $whereCondition = $wheres[strtolower($builder[1]->operator)];
        }

        if (count($builder[2]) == 3) {
            if ($whereCondition == 'whereRaw') {
                $query->$whereCondition(implode(" ", $builder[2]));
            } else {
                // where, whereNot
                $query->$whereCondition(
                    $builder[2]->key,
                    $builder[2]->relation,
                    $builder[2]->value
                );
            }
        } elseif (count($builder[2]) == 2) {
            // whereBetween, whereNotBetween, where, whereNot
            $query->$whereCondition(
                $builder[2]->key,
                $builder[2]->value
            );
        } elseif (count($builder[2]) == 1) {
            // whereNull, whereNotNull, whereRaw
            $query->$whereCondition(
                $builder[2]->key ?? $builder[2]->value // PHP 7.0 Null Coalescing Operator
            );
        }
    }
    return $query;
}
如果此方法是在用户模型中定义的,则可以通过以下方式使用:

$users = User::json($data)->get();

PS:虽然它应该可以工作,但我没有测试它。

遇到这个问题,我会同意。在这种方法中,您可以创建一个名为scopeJson的模型方法,或者任何您觉得更好的方法来处理其中的所有条件。我试图处理这里的大多数情况,而不仅仅是单一的地点和地点。我假设您的有效负载一次只包含一个生成器

public function scopeJson($query, $json)
{
    $wheres = [
        'between' => ['whereBetween', 'not' => 'whereNotBetween'],
        'null'    => ['whereNull', 'not' => 'whereNotNull'],
        'or'      => ['orWhere', 'not' => 'orWhereNot'],
        'in'      => ['whereIn', 'not' => 'whereNotIn'],
        'and'     => ['where', 'not' => 'orWhereNot'],
        'raw'     => 'whereRaw'
    ];

    $builder = json_decode($json);

    if (count($builder) > 0) {
        $query->where(
            $builder[0]->key,
            $builder[0]->relation,
            $builder[0]->value
        );

        // notBetween, notNull, notOr, notIn, notAnd
        if (stripos($builder[1]->operator, 'not') !== false) {
            $whereCondition = $wheres[strtolower(substr($builder[1]->operator, 3))]['not'];
        } else {
            $whereCondition = $wheres[strtolower($builder[1]->operator)];
        }

        if (count($builder[2]) == 3) {
            if ($whereCondition == 'whereRaw') {
                $query->$whereCondition(implode(" ", $builder[2]));
            } else {
                // where, whereNot
                $query->$whereCondition(
                    $builder[2]->key,
                    $builder[2]->relation,
                    $builder[2]->value
                );
            }
        } elseif (count($builder[2]) == 2) {
            // whereBetween, whereNotBetween, where, whereNot
            $query->$whereCondition(
                $builder[2]->key,
                $builder[2]->value
            );
        } elseif (count($builder[2]) == 1) {
            // whereNull, whereNotNull, whereRaw
            $query->$whereCondition(
                $builder[2]->key ?? $builder[2]->value // PHP 7.0 Null Coalescing Operator
            );
        }
    }
    return $query;
}
如果此方法是在用户模型中定义的,则可以通过以下方式使用:

$users = User::json($data)->get();

PS:虽然它应该可以工作,但我没有测试它。

如果您希望查询是直接的或简单的,那么在这种情况下,您应该更喜欢编写原始查询。那会更干净。@VishalSh谢谢你的建议。在我的例子中有原始查询的例子吗?@s您在有效负载中发送的是什么和运算符?@z3r0ck是的。你说得对。因此,我可以按自己的意愿设置任意多个键。@s您使用的是什么版本的laravel?如果您希望查询是直接的或简单的,那么在这种情况下,您应该更喜欢编写原始查询。那会更干净。@VishalSh谢谢你的建议。在我的例子中有原始查询的例子吗?@s您在有效负载中发送的是什么和运算符?@z3r0ck是的。你说得对。所以我可以放任意数量的钥匙。@s您使用的是什么版本的laravel?嗨。。但是如果json数组是空的呢。这意味着,若并没有给出任何条件,那个么查询将是select*from tablename,其中,这个查询将运行吗?一个简单的if检查可以实现这一点。正如我提到的,这只是一个起点。。但是如果json数组是空的呢。这意味着,若并没有给出任何条件,那个么查询将是select*from tablename,其中,这个查询将运行吗?一个简单的if检查可以实现这一点。正如我提到的,这只是一个起点。