laravel 方法 Illuminate\Database\Query\Builder::filter 不存在

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49591360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 17:34:56  来源:igfitidea点击:

Method Illuminate\Database\Query\Builder::filter does not exist

phplaravel

提问by dongerpep

I am following a tutorial to write 2 classes for filtering threads in a forum application.I got this error in line
$threads = Thread::latest()->filter($filters); (in threadscontroller)

我正在按照教程编写 2 个用于在论坛应用程序中过滤线程的类。我在
$threads = Thread::latest()->filter($filters);行中遇到此错误。(在线程控制器中)

Method Illuminate\Database\Query\Builder::filter does not exist.

方法 Illuminate\Database\Query\Builder::filter 不存在。

ThreadsController with index method:

带有索引方法的 ThreadsController:

<?php

namespace App\Http\Controllers;

use App\Thread;
use App\Channel;
use App\Filters\ThreadFilters;

use Illuminate\Http\Request;

class ThreadsController extends Controller
{

    public function __construct(){

        $this->middleware('auth')->only('store','create');

    }
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Channel $channel,ThreadFilters $filters)  
    {

$threads = Thread::latest()->filter($filters);  

if($channel->exist){
    $threads->where('channel_id',$channel->id);
}

$threads = $threads->get();

return view('threads.index',compact('threads'));



    }

This is the abstract class Filters:

这是抽象类过滤器:

<?php

namespace App\Filters;
use Illuminate\Http\Request;

abstract class Filters{

protected $request;
protected $builder;

protected $filters = [];

    public function __construct(Request $request){
        $this->request = $request;



    }

    public function apply($builder){
        $this->builder = $builder;

        foreach($this->getFilters() as $filter=>$value){   //filter by,value yunus mesela.
if(method_exist($this,$filter)){    
    $this->$filter($value);  
}

        }

        return $this->builder;

    }


    public function getFilters(){

        return $this->request->intersect($this->filters); 
    } 

}

Here ThreadFilters.php which extends filters class:

这里 ThreadFilters.php 扩展了过滤器类:

<?php

namespace App\Filters;

use App\User;

use Illuminate\Http\Request;


class ThreadFilters extends Filters
{
protected $filters =['by'];        

protected function by($username){
    $user = User::where('name',$username)->firstorFail();

    return $this->builder->where('user_id',$user->id);



}

}

If i change latest to all,i get this error: Type error: Argument 1 passed to Illuminate\Support\Collection::filter() must be callable or null, object given, called in

如果我全部更改为最新,我会收到此错误:类型错误:传递给 Illuminate\Support\Collection::filter() 的参数 1 必须是可调用的或为空,给定的对象,调用

Also can anyone explain me what is $builder doing in those classes ?

也有人能解释一下 $builder 在这些课程中做什么吗?

回答by Aken Roberts

latest()is a modifier shortcut, equivalent to orderBy('created_at', 'desc'). All it does is add the ORDER BYconstraint to the query.

latest()是修饰符快捷方式,相当于orderBy('created_at', 'desc'). 它所做的就是将ORDER BY约束添加到查询中。

filter()is a method on the Collection class. That method does not exist in the query builder, hence the "method not found" error you're receiving.

filter()是 Collection 类上的一个方法。该方法在查询构建器中不存在,因此您会收到“找不到方法”错误。

It does not appear that your filter class should be used with the resulting Collection. Rather, it adds conditionals to your original query. Try implementing it like this:

您的过滤器类似乎不应与生成的集合一起使用。相反,它会向您的原始查询添加条件。尝试像这样实现它:

// Remove the filters() method here.
$threads = Thread::latest();  

if ($channel->exist) {
    $threads->where('channel_id', $channel->id);
}

// Pass your query builder instance to the Filters' apply() method.
$filters->apply($threads);

// Perform the query and fetch results.
$threads = $threads->get();

Also, for future questions, including the tutorial you're attempting/following can provide beneficial context to those helping you. :)

此外,对于未来的问题,包括您正在尝试/遵循的教程,可以为帮助您的人提供有益的背景信息。:)

回答by Markus Schober

If you change latest to all, you're getting a Laravel Collection. So you are calling filter()on a Collection ($threads = Thread::all()->filter($filters);).

如果您更改为全部最新,您将获得一个 Laravel 集合。因此,您正在调用filter()Collection ( $threads = Thread::all()->filter($filters);)。

If you take a look into the code, you'll see, that the where()method of the array class gets called, which calls PHP's array_filtermethod. As you can see, a callablemust be given. But you are passing an Object to the filter method, $filters, which is an ThreadFilters-Object -> method injection here: public function index(Channel $channel,ThreadFilters $filters) ...

如果您查看代码,您会看到where()调用了数组类的方法,该方法调用了 PHP 的array_filter方法。如您所见,必须给出一个可调用对象。但是您将一个对象传递给过滤器方法$filters,这是一个 ThreadFilters-Object -> 方法注入: public function index(Channel $channel,ThreadFilters $filters) ...

Your error message answers your question in a great way: Type error: Argument 1 passed to Illuminate\Support\Collection::filter() must be callable or null, object given, called in

您的错误消息以一种很好的方式回答了您的问题:类型错误:传递给 Illuminate\Support\Collection::filter() must be callable or null, object given, call in