来自url的Laravel自动查询构建器

时间:2014-10-29 14:30:31

标签: php json laravel

我想创建一个自动查询构建器,它从控制器中的url获取params并将其传递给我的存储库。

现在我有一组键/过滤器,查询可以使用它来构建其where子句,它匹配url中的params的键,它可以工作。只要我只用一把钥匙。

如果我...做:

".../api/v1/companies?is_accountant=0"  -->WORKS 
".../api/v1/companies?is_accountant=0&name=test&street=testLane -->FAILS, returns empty

记录存在于我的数据库中,但它返回一个空对象。如果我用1键单独尝试,它会找到记录

有人能发现问题吗?

private $filters = ['id','street','name','is_accountant','nr_ext','postal_code'];

    public function getCompaniesFilterd($params, $limit)
    {
        if (!empty($params)) {
            $query = Company::query();

            foreach($params as $param)
            {
                foreach($this->filters as $filter)
                {
                    if(key($params) == $filter)
                    {
                        $query->where($filter,'=',$param);
                    }
                }
            }
                      $companies = $query->get();
            dd($query);
            return $companies;
        }

        return Company::take(10)->get();
    }

输出

{
"data": []
}

查询转储

object(Illuminate\Database\Eloquent\Builder)[222]
  protected 'query' => 
    object(Illuminate\Database\Query\Builder)[221]
      protected 'connection' => 
        object(Illuminate\Database\MySqlConnection)[212]
          protected 'pdo' => 
            object(PDO)[181]
              ...
          protected 'readPdo' => null
          protected 'reconnector' => 
            object(Closure)[220]
              ...
          protected 'queryGrammar' => 
            object(Illuminate\Database\Query\Grammars\MySqlGrammar)[211]
              ...
          protected 'schemaGrammar' => null
          protected 'postProcessor' => 
            object(Illuminate\Database\Query\Processors\MySqlProcessor)[214]
              ...
          protected 'events' => 
            object(Illuminate\Events\Dispatcher)[14]
              ...
          protected 'paginator' => 
            object(Closure)[219]
              ...
          protected 'cache' => 
            object(Closure)[218]
              ...
          protected 'fetchMode' => int 8
          protected 'transactions' => int 0
          protected 'queryLog' => 
            array (size=1)
              ...
          protected 'loggingQueries' => boolean true
          protected 'pretending' => boolean false
          protected 'database' => string 'homestead' (length=9)
          protected 'tablePrefix' => string '' (length=0)
          protected 'config' => 
            array (size=9)
              ...
      protected 'grammar' => 
        object(Illuminate\Database\Query\Grammars\MySqlGrammar)[211]
          protected 'selectComponents' => 
            array (size=11)
              ...
          protected 'tablePrefix' => string '' (length=0)
      protected 'processor' => 
        object(Illuminate\Database\Query\Processors\MySqlProcessor)[214]
      protected 'bindings' => 
        array (size=5)
          'select' => 
            array (size=0)
              ...
          'join' => 
            array (size=0)
              ...
          'where' => 
            array (size=3)
              ...
          'having' => 
            array (size=0)
              ...
          'order' => 
            array (size=0)
              ...
      public 'aggregate' => null
      public 'columns' => 
        array (size=1)
          0 => string '*' (length=1)
      public 'distinct' => boolean false
      public 'from' => string 'companies' (length=9)
      public 'joins' => null
      public 'wheres' => 
        array (size=3)
          0 => 
            array (size=5)
              ...
          1 => 
            array (size=5)
              ...
          2 => 
            array (size=5)
              ...
      public 'groups' => null
      public 'havings' => null
      public 'orders' => null
      public 'limit' => null
      public 'offset' => null
      public 'unions' => null
      public 'lock' => null
      protected 'backups' => 
        array (size=0)
          empty
      protected 'cacheKey' => null
      protected 'cacheMinutes' => null
      protected 'cacheTags' => null
      protected 'cacheDriver' => null
      protected 'operators' => 
        array (size=19)
          0 => string '=' (length=1)
          1 => string '<' (length=1)
          2 => string '>' (length=1)
          3 => string '<=' (length=2)
          4 => string '>=' (length=2)
          5 => string '<>' (length=2)
          6 => string '!=' (length=2)
          7 => string 'like' (length=4)
          8 => string 'not like' (length=8)
          9 => string 'between' (length=7)
          10 => string 'ilike' (length=5)
          11 => string '&' (length=1)
          12 => string '|' (length=1)
          13 => string '^' (length=1)
          14 => string '<<' (length=2)
          15 => string '>>' (length=2)
          16 => string 'rlike' (length=5)
          17 => string 'regexp' (length=6)
          18 => string 'not regexp' (length=10)
  protected 'model' => 
    object(Winbooks\Core\Models\Company)[213]
      protected 'table' => string 'companies' (length=9)
      protected 'fillable' => 
        array (size=10)
          0 => string 'name' (length=4)
          1 => string 'street' (length=6)
          2 => string 'nr_ext' (length=6)
          3 => string 'postal_code' (length=11)
          4 => string 'city' (length=4)
          5 => string 'phone' (length=5)
          6 => string 'fax' (length=3)
          7 => string 'email' (length=5)
          8 => string 'is_accountant' (length=13)
          9 => string 'country_id' (length=10)
      protected 'connection' => null
      protected 'primaryKey' => string 'id' (length=2)
      protected 'perPage' => int 15
      public 'incrementing' => boolean true
      public 'timestamps' => boolean true
      protected 'attributes' => 
        array (size=0)
          empty
      protected 'original' => 
        array (size=0)
          empty
      protected 'relations' => 
        array (size=0)
          empty
      protected 'hidden' => 
        array (size=0)
          empty
      protected 'visible' => 
        array (size=0)
          empty
      protected 'appends' => 
        array (size=0)
          empty
      protected 'guarded' => 
        array (size=1)
          0 => string '*' (length=1)
      protected 'dates' => 
        array (size=0)
          empty
      protected 'touches' => 
        array (size=0)
          empty
      protected 'observables' => 
        array (size=0)
          empty
      protected 'with' => 
        array (size=0)
          empty
      protected 'morphClass' => null
      public 'exists' => boolean false
  protected 'eagerLoad' => 
    array (size=0)
      empty
  protected 'macros' => 
    array (size=0)
      empty
  protected 'onDelete' => null
  protected 'passthru' => 
    array (size=12)
      0 => string 'toSql' (length=5)
      1 => string 'lists' (length=5)
      2 => string 'insert' (length=6)
      3 => string 'insertGetId' (length=11)
      4 => string 'pluck' (length=5)
      5 => string 'count' (length=5)
      6 => string 'min' (length=3)
      7 => string 'max' (length=3)
      8 => string 'avg' (length=3)
      9 => string 'sum' (length=3)
      10 => string 'exists' (length=6)
      11 => string 'getBindings' (length=11)

2 个答案:

答案 0 :(得分:0)

我能够用你的代码重新演绎这种行为,但我不确定是什么导致它。错误似乎是过滤器值不会改变,循环可能有一些奇怪的问题。所以我想把它作为一个重写和改进你的代码的机会,因为我认为Laravel允许一种更优雅的方式来做到这一点。

private $filters = ['id','street','name','is_accountant','nr_ext','postal_code'];

public function getCompaniesFiltered($params, $limit = 10)
{
    $params = array_diff_key($params, $this->filters);

    if(empty($params))
    {
        return Company::take($limit)->get();
    }

    return Company::where($params)->get();
}

使用getCompaniesFiltered(Input::all());调用它对我来说很好。

修改 在仔细观察循环之后,我很确定问题只是一个额外的's':

if(key($params) == $filter)

应该是

if(key($param) == $filter)

if (1 == 'name')(或比较布尔值,字符串和一些整数)可能会导致PHP中出现一种非常奇怪的行为。


编辑2:

注意:请不要在同一主题下提出单独的问题。虽然它们是相关的,但它们仍然是不同的问题,但是你应该给予那些回答它们的人以获得两者的功劳。既然你似乎是StackOverflow的新手,那么现在就让它保持原状,但请记住以后的问题。

asewers:

  

“如果我使用你之前的建议它有效,但我刚注意到,如果你输入一个错误的参数仍然想搜索表格 - &gt;导致表格中找不到错误行。 “

是的,array_diff不是最好的选择,应该是:

$params = array_intersect_key($params, array_flip($this->filters))
  

“我正在尝试像以前一样查询,但现在我也希望能够将params放在我的相关模型上。”

再一次,Laravel使用Eloquent的eager loading concept让这很容易。该课程可能如下所示:

private $mainFilters = ['id', 'name', 'preview','user_id', 'date', 'status'];
private $fileFilters =  ['path', 'uuid'];
private $invoicesFilters = ['due_date', 'payment_status', 'type'];

public function getDocumentsFiltered($params, $limit = 10)
{
    $dependencies = $this->getDependencies($params);
    $documentParams = $this->filterParams($params, $this->mainFilters));

    $documents = Document::with($dependencies);

    if(empty($documentParams))
    {
        return $documents->take($limit)->get();
    }

    return $docuemnts->where($documentParams)->get();
}

protected function getDependencies($params)
{
   $fileParams = $this->filterParams($params, $this->fileFilters));
   $invoiceParams = $this->filterParams($params, $this->invoiceFilters));

   return [
       'file' => function($query) use ($fileParams) {
           $query->where($fileParams);
       },

       'invoice' => function($query) use ($invoiceParams) {
           $query->where($invoiceParams);
       },

       'user',
       'folder',
   ];
}

protected function filterParams($input, $filter)
{
    return array_intersect_key($input, array_flip($filter);
}

代码没有评论,但我认为它几乎解释了自己。

答案 1 :(得分:0)

@Quasdunk你的最后一个答案确实是更好的选择/答案。如果我使用你以前的建议它有效,但我只是注意到,如果你输入一个错误的参数仍然想搜索表 - &gt;导致找不到表中的错误行。

这是我的最终代码

private $filters = ['id', 'name', 'date', 'status'];

public function getDocumentListFilterd($params, $limit = 10)
{

    if (!empty($params)) {
        $query = Document::query();

        foreach($params as $param => $value)
        {

            foreach($this->filters as $filter)
            {

                if($param == $filter)
                {
                    $query->where($filter,'=',$value);
                }
            }
        }
        $documents = $query->get();
        //dd($query);
        return $documents;
    }

    return Company::take(10)->get();

 }