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
Method Illuminate\Database\Query\Builder::filter does not exist
提问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 BY
constraint 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