I need to eager load relationship within laravel policy The problem is i use the laravel policy inside yajra-datatable which will load it (the policies) line by line
Here’s the code looks like :
public function create(User $user) { $user->load('sections'); $sections = collect($user->sections->toArray())->pluck('name'); return in_array($user->role_id,[3,4]) && in_array('Produksi', $sections->toArray()) && Session::get('productionPlans-branch') !== 'all' && Session::get('productionPlans-period') !== 'all'; }
and i use it in my yajra-datatable like so :
public function table(Request $request) { $query = ProductionPlan::with(['branch','product.category','period'])->orderBy('created_at'); return YajraDataTablesDataTables::of($query) ->addIndexColumn() ->addColumn('action', function($row) { if ($request->user->can('create', $row)) { return '<a href="javascript:void(0)" onclick="show('. $row->id .')">Add</a>'; } }) ->rawColumns(['action']) ->make(true); }
so every line will load the relation again and again
I’m expecting more efficient way to load them just once instead of load the relation line by line How can i achieve this ?
Update :
I tried to use accessor on User model to append the relations with sections table
protected $appends = ['sections']; public function getSectionsAttribute () { return $this->attributes['sections'] = $this->sections()->first(); }
This was success for only the FIRST relation only, i tried to remove the first() method but got the error PDO serialization instead
Serialization of 'PDO' is not allowed
Advertisement
Answer
I think Laravel policies uses the exact object it is called on. So $this->user->can(…) actually is the same object that is being passed as first parameter to the create(User $user) policy method.
In that case, I would try to load it before you call the ->can method inside the closure.
The code could look like this:
public function table(Request $request) { $query = ProductionPlan::with(['branch','product.category','period'])->orderBy('created_at'); $user = $request->user; $user->load('sections'); return YajraDataTablesDataTables::of($query) ->addIndexColumn() ->addColumn('action', function($row) use ($user) { if ($user->can('create', $row)) { return '<a href="javascript:void(0)" onclick="show('. $row->id .')">Add</a>'; } }) ->rawColumns(['action']) ->make(true); }
And then you also have to remember to remove the $user->load('sections');
from inside the create() method in the policy.
This is very important 🙂