3

I use constraint eager load with an anonymous function:

$users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');
}])->get();

Now I want to replace the anonymous function with a class function. According to PHP: How to use a class function as a callback I found

A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.

Thus I expected that the following will work:

public function start()
{
   $users = App\User::with(['posts' => [$this, 'addRestrain']])->get();
   // ...
}

private function addRestrain($query)
{
  $query->where('title', 'like', '%first%');
}

However, Laravel detects that the passed parameter is not a closure, but an array:

"Type error: Argument 3 passed to Illuminate\Database\Eloquent\Builder::eagerLoadRelation() must be an instance of Closure, array given, called in

Does that mean that it is not possible to use a class function for the eager load constraint?

Adam
  • 25,960
  • 22
  • 158
  • 247

1 Answers1

5

Starting from PHP 7.1.0, you can use Closure::fromCallable (docs):

$users = App\User::with(
  [ 'posts' => \Closure::fromCallable([$this, 'addRestrain']) ]
)->get();

Otherwise, you're limited to using anonymous function wrapping $this->addRestrain call instead.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • Thats awesome, thank you! But `$this->addRestrain` wont work in Laravel I guess, I get then an `Undefined property` error. – Adam May 15 '18 at 15:00
  • Do you do it correctly, like described in [this answer](https://stackoverflow.com/questions/2881311/define-a-closure-as-method-from-class)? And which version of PHP is used? – raina77ow May 15 '18 at 15:01