Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.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 如何获取大量GET参数并根据它们干净地过滤查询?_Php_Sql_Arrays_Laravel_Lumen - Fatal编程技术网

Php 如何获取大量GET参数并根据它们干净地过滤查询?

Php 如何获取大量GET参数并根据它们干净地过滤查询?,php,sql,arrays,laravel,lumen,Php,Sql,Arrays,Laravel,Lumen,我在Laravel Lumen中为一个RESTful API构建了一个控制器,它接受相对大量的参数并将它们解析到查询的位置,根据是否提供了这些参数来获取数据。比如说, GET /nodes?region=California GET /nodes?ip=127.0.0.1 我目前正在构造函数中使用它们,构建一个参数数组(因为我不知道如何获取Lumen中的原始get数组,这会很不方便,因为我已经有了其他参数),并过滤掉空值(如果它们不在查询中,我将值设置为null) 现在,当涉及到过滤数组中的每

我在Laravel Lumen中为一个RESTful API构建了一个控制器,它接受相对大量的参数并将它们解析到查询的位置,根据是否提供了这些参数来获取数据。比如说,

GET /nodes?region=California
GET /nodes?ip=127.0.0.1
我目前正在构造函数中使用它们,构建一个参数数组(因为我不知道如何获取Lumen中的原始get数组,这会很不方便,因为我已经有了其他参数),并过滤掉空值(如果它们不在查询中,我将值设置为null)

现在,当涉及到过滤数组中的每个值时,我是通过foreach数组来完成的。这是我能想到的最干净的方法,没有太多的代码(我不想让我的控制器太胖)。 有没有其他干净的方法,比如分离函数/类

这是我的构造函数代码:

/**
 * Get some values before using functions.
 * 
 * @param Request $request Instance of request.
 */
public function __construct(Request $request)
{
    $this->offset = (int) $request->input('offset', 0);

    // TODO: I'm not sure how to implement this, code in question
    $this->filters = [
        'region' => $request->input('region', null),
        'name' => $request->input('name', null),
        'ip' => $request->input('ip', null)
    ];

    $this->filters = array_filter($this->filters, function ($v) {
        return !is_null($v);
    });

    // Set a sane SQL limit.
    $this->limit = 5;
    $this->request = $request;
}
以及控制器代码:

/**
 * List all nodes.
 * 
 * @return [string] [JSON containing list of nodes, if sorted.]
 */
public function all()
{
    try {
        // use filters provided
        $data =  Nodes::limit($this->limit)->offset($this->offset);

        foreach ($this->filters as $filter => $value) {
            $data->where($filter, $value);
        }

        $data = $data->get();
        $response = $this->respond($data);
    } catch (\Exception $e) {
        $response = $this->respondServerError('Could not retrieve data from database.');
    }

    return $response;    
}

因此,每当我必须在API中过滤资源列表时,我都会这样做

首先,在开始之前,我要介绍一个关于在控制器方法中获取请求对象的快速技巧:如果您添加
Request$Request
作为
all()
函数的参数,您将可以访问那里的$Request变量,与构造函数相同。因此,完整的签名将是
公共函数all(Request$Request)
。控制器方法具有与其他类构造函数在Laravel/Lumen中获得的相同的魔法依赖注入。或者,在函数中,您可以始终要求
app()
函数为您提供特定类的对象。因为Request对象在容器中仅绑定到'Request',所以您可以请求完整的类名,或者只请求'Request':
$Request=app('Request')

因此,一旦我有了请求对象,在我的控制器方法中,我喜欢将每个过滤器作为一个组或一个接一个地进行检查,这取决于每个过滤器的复杂程度。有时过滤器很复杂,比如需要分解成数组的逗号分隔的ID列表。如果只是简单的字符串过滤器,我倾向于将列表放入一个数组中并运行它

下面是一个示例函数来说明一些想法:

public function getIndex(Request $request)
{
    //Create a User object to append WHERE clauses onto
    $user = app('App\Models\User');

    //Run through our simple text fields
    foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
        if ($request->has($field)) {
            $user->where($field, $request->input($field));
        }
    }

    //This field uses a LIKE match, handle it separately
    if ($request->has('email')) {
        $user->where('email', LIKE, '%' . $request->input('email') . '%');
    }

    //This field is a list of IDs
    if ($request->has('id')) {
        $ids = explode(',', $request->input('id'));
        $user->whereIn('id', $ids);
    }

    //Use pagination
    $users = $user->paginate(25);

    /**
     * Continue with the rest of response formatting below here
     */
}
您会注意到我使用了paginate函数来限制结果。在构建列出资源的API端点时,您需要在标题(我的首选项)或响应正文中输入有关如何获取第一页、上一页、下一页和最后一页结果的信息。Laravel中的分页功能使这变得很容易,因为它可以使用
links()
方法构造大多数链接

不幸的是,您需要告诉它在请求中传递了哪些过滤器参数,这样它才能确保将这些参数添加到它生成的链接中。否则,您将在没有过滤器的情况下返回链接,这对客户端分页没有多大好处

下面是一个更完整的示例,用于记录过滤器参数,以便将其附加到分页链接上:

public function getIndex(Request $request)
{
    //Create a User object to append WHERE clauses onto
    $user = app('App\Models\User');

    //List of filters we found to append to links later
    $appends = [];

    //Run through our simple text fields
    foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
        if ($request->has($field)) {
            $appends[$field] = $request->input($field);
            $user->where($field, $request->input($field));
        }
    }

    //This field uses a LIKE match, handle it separately
    if ($request->has('email')) {
        $appends['email'] = $request->input('email');
        $user->where('email', LIKE, '%' . $request->input('email') . '%');
    }

    //This field is a list of IDs
    if ($request->has('id')) {
        $appends['id'] = $request->input('id');
        $ids = explode(',', $request->input('id'));
        $user->whereIn('id', $ids);
    }

    //Use pagination
    $users = $user->paginate(25);

    //Make sure we append our filter parameters onto the pagination object
    $users->appends($appends);

    //Now calling $users->links() will return the correct links with the right filter info

    /**
     * Continue with the rest of response formatting below here
     */
}
分页文档可在此处找到:

有关分页链接如何出色完成的示例,请查看Github的API文档:


最后,从概念上讲,它与你所做的并不太遥远。这里的优点是,您可以将代码移动到需要它的方法中,而不是每次初始化控制器时都让它在构造函数中运行,即使会调用不同的方法


希望有帮助

因此,每当我必须在API中过滤资源列表时,我都会这样做

首先,在开始之前,我要介绍一个关于在控制器方法中获取请求对象的快速技巧:如果您添加
Request$Request
作为
all()
函数的参数,您将可以访问那里的$Request变量,与构造函数相同。因此,完整的签名将是
公共函数all(Request$Request)
。控制器方法具有与其他类构造函数在Laravel/Lumen中获得的相同的魔法依赖注入。或者,在函数中,您可以始终要求
app()
函数为您提供特定类的对象。因为Request对象在容器中仅绑定到'Request',所以您可以请求完整的类名,或者只请求'Request':
$Request=app('Request')

因此,一旦我有了请求对象,在我的控制器方法中,我喜欢将每个过滤器作为一个组或一个接一个地进行检查,这取决于每个过滤器的复杂程度。有时过滤器很复杂,比如需要分解成数组的逗号分隔的ID列表。如果只是简单的字符串过滤器,我倾向于将列表放入一个数组中并运行它

下面是一个示例函数来说明一些想法:

public function getIndex(Request $request)
{
    //Create a User object to append WHERE clauses onto
    $user = app('App\Models\User');

    //Run through our simple text fields
    foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
        if ($request->has($field)) {
            $user->where($field, $request->input($field));
        }
    }

    //This field uses a LIKE match, handle it separately
    if ($request->has('email')) {
        $user->where('email', LIKE, '%' . $request->input('email') . '%');
    }

    //This field is a list of IDs
    if ($request->has('id')) {
        $ids = explode(',', $request->input('id'));
        $user->whereIn('id', $ids);
    }

    //Use pagination
    $users = $user->paginate(25);

    /**
     * Continue with the rest of response formatting below here
     */
}
您会注意到我使用了paginate函数来限制结果。在构建列出资源的API端点时,您需要在标题(我的首选项)或响应正文中输入有关如何获取第一页、上一页、下一页和最后一页结果的信息。Laravel中的分页功能使这变得很容易,因为它可以使用
links()
方法构造大多数链接

不幸的是,您需要告诉它在请求中传递了哪些过滤器参数,这样它才能确保将这些参数添加到它生成的链接中。否则,您将在没有过滤器的情况下返回链接,这对客户端分页没有多大好处

下面是一个更完整的示例,用于记录过滤器参数,以便将其附加到分页链接上:

public function getIndex(Request $request)
{
    //Create a User object to append WHERE clauses onto
    $user = app('App\Models\User');

    //List of filters we found to append to links later
    $appends = [];

    //Run through our simple text fields
    foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
        if ($request->has($field)) {
            $appends[$field] = $request->input($field);
            $user->where($field, $request->input($field));
        }
    }

    //This field uses a LIKE match, handle it separately
    if ($request->has('email')) {
        $appends['email'] = $request->input('email');
        $user->where('email', LIKE, '%' . $request->input('email') . '%');
    }

    //This field is a list of IDs
    if ($request->has('id')) {
        $appends['id'] = $request->input('id');
        $ids = explode(',', $request->input('id'));
        $user->whereIn('id', $ids);
    }

    //Use pagination
    $users = $user->paginate(25);

    //Make sure we append our filter parameters onto the pagination object
    $users->appends($appends);

    //Now calling $users->links() will return the correct links with the right filter info

    /**
     * Continue with the rest of response formatting below here
     */
}
分页文档可在此处找到:

有关分页链接如何出色完成的示例,请查看Github的API文档:


最后它离你做的事情不远了,