Long controller methods and complicated queries often times go hand in hand. One of the common reasons I see is that developers don't utilize dynamic scopes for their models enough (or at all). As a rule of thumb, whenever I find 'where' query calls that needs a callback, I usually do throw that into a scope. I find this most common when I need to do some sort of constraint on the relationship. Throwing your query calls into a scope abstracts the actual implementation, and you can just re-use the scope whenever you want. ## Example: We are developing a medical service app and we are tasked to get all the doctors having cases assigned to the current authenticated doctor and include a count of cases assigned by each doctor. Our original implementation goes like this.. use App\Models\Doctor; use Illuminate\Support\Facades\Auth; ... public function index() { return Doctor::whereHas('cases', function ($query) { $query->where('assignee_id', Auth::id()); }) ->withCount(['cases' => function ($query) { $query->where('assignee_id', Auth::id()); }]) ->get(); } This implementation isn't bad at all. However, reading this takes a while to process what this code is trying to accomplish. Also, if we are going to use the scope on other places aside from the `index()` method, it makes more sense to just extract it to a scope. Let's see how we can refactor this.. use App\Models\Doctor; use Illuminate\Support\Facades\Auth; ... public function index() { return Doctor::onlyWithCasesAssignedTo(Auth::user()) ->withCountOfCasesAssignedTo(Auth::user()) ->get(); } // Then in our Doctor model, we add couple of query scopes.. use Illuminate\Database\Eloquent\Builder; ... public function scopeOnlyWithCasesAssignedTo(Builder $query, Doctor $doctor) { return $query->whereHas('cases', function ($query) { $query->where('assignee_id', $doctor->id); }); } public function scopeWithCountOfCasesAssignedTo(Builder $query, Doctor $doctor) { return $query->withCount(['cases' => function ($query) { $query->where('assignee_id', Auth::id()); }]); } And there you go! We've successfully extracted the complicated queries from our controller to their dedicated query scope methods. Cheers!
Published Articles
If you need a more robust reporting of your Exceptions, you can just add a report() method to your exception classes. Laravel will auto-detect that (and the render method) and run the logic inside. What's the difference between render and report in Exception classes? In render method you will typically want to return a response of some type (json/view), while report method you will typically want to Log the exception (file/database). And if you are using some 3rd party reporting tool like Sentry or Bugsnag you will want to call that in the report method as well. ``` use Exception; use Illuminate\Support\Facades\Log; class FooException extends Exception { /** * Report the exception. * * @return void */ public function report() { // Using simple Log Log::warning($this->getMessage()); // Using 3rd party integration like Sentry or Bugsnag app('sentry')->captureException($this); } } ```