0

I have this relationship in my Model:

public function modulesData($module) {
    return $this->belongsToMany($module)
        ->withTimestamps();
}

What I want is to eagerload a dynamic relation of my model. But how can I do this? I use this code to eagerload my relation, but how can I add the parameter $module?

$model->with(['modulesData'])->get();

Thanks for reply.

goldlife
  • 1,949
  • 3
  • 29
  • 48

2 Answers2

2

Consider the following:

Define the fallback function to your Model:

public function __call($name, $arguments)
{
    if (strpos($name, 'modulesData') !== false) {
        $nameArray = explode(' ', $name);
        $moduleName = ucfirst($nameArray[1]);
        $moduleClass = 'App\Modules\\' . $moduleName . '\\' . $moduleName;
        return $this->modulesData($moduleClass);
    } else {
        return parent::__call($name, $arguments);
    }
}

Use the with function with this way:

$tal = \App\Model::with('modulesData ModuleName')->get();

(being 'ModuleName' the name of the module you want to use as parameter for the relationship).

This way you can eagerload with the string "modulesData_moduleName". When with is invoked it won't find that function and will fallback to __call, which will extract the "moduleName" and call the relationship "modulesData" with it as parameter.

Amarnasan
  • 14,939
  • 5
  • 33
  • 37
  • this is an interesting approach .. but this will not work, because there is already a __call function in the laravel model class. (vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php) ... I got the error "Call to a member function orderBy() on null" – goldlife Dec 16 '15 at 11:59
  • @goldlife No problem: Updated with call to parent::_call in case it doesn't match what we are looking for – Amarnasan Dec 16 '15 at 12:05
  • hm also error: "Call to a member function orderBy() on boolean" .. instead of "Call to a member function orderBy() on null" – goldlife Dec 16 '15 at 12:18
  • Your code provides the approach for the solution. It works now with this code: public function __call($name, $arguments) { if (strpos($name,'modulesData') !== false) { $nameArray = explode('_', $name); $moduleName = ucfirst($nameArray[1]); $moduleClass = 'App\Modules\\'.$moduleName.'\\'.$moduleName; return $this->modulesData($moduleClass); } else { return parent::__call($name, $arguments); } } the return false is wrong in your code. It has to be return parent::_call. please change it, I will accept it. – goldlife Dec 16 '15 at 12:37
  • @goldlife You got it. – Amarnasan Dec 16 '15 at 12:44
  • 1
    @goldlife Oh, minor change in the code of your comment: the delimiter in the comment was empty, replaced in the code of the answer with an espace. And also replaced the underscore in the `with` call with another espace. Team work! – Amarnasan Dec 16 '15 at 13:05
-1

I dont know how to pass parameters but you could do something like:

$model->with(['modulesData' => function($q) {
    $q->withTimestamps();
}])->get();
Amir Bar
  • 3,007
  • 2
  • 29
  • 47