Published Articles

Enter a search term to find articles.
2020-07-03

I personally think that one of the most underrated feature of Laravel is Form Request. Form Requests allows you to perform more complex authorizations and validations and can drastically clean up your controllers if you know how to use it.  Here are 3 things you probably did not know you can do with Form Requests. # 1. Removing the authorize method will make the authorization check pass. When generating Form Requests using `php artisan make:request FooRequest` command , the authorize method by default will return false. However, instead of returning true in this method, you can just delete it entirely - which achieves the same result and a much cleaner approach. # 2. Add a persist method in Form Request class to handle storing and updating of your models. Basically, we will let our form persist itself. Lets take a look at this simple blog post example: // In our PostRequest class we can have the following methods. class PostRequest { public function rules() { return [ 'title' => 'required|max:255', 'body' => 'required', ]; } public function persist(Post $post = null) // We type-hint our Post model here. { $post = $post ?? new Post; $post->title = $this->title; $post->body = $this->body; $post->save(); return $post->fresh(); } } // In our PostController we can have the store and update methods like so. class PostController extends Controller { public function store(PostRequest $request) { // You can definitely return view or redirect here, whichever you prefer. // Let's assume this is a json endpoint so we just return PostResource. return PostResource($request->persist()); } public function update(PostRequest $request, Post $post) // Route-model binding. { // We pass the post model so it will be updated in persist method. return PostResource($request->persist($post)); } } Now this cleans up the controller into single-line and we have our validation and persistence layers both within the Form Request class. # 3. Before-and-after-validation hooks you can tap into in Form Request class. If you need to do some logic before the validation runs, such as sanitizing data from the request, you can use the `prepareForValidation()` method. protected function prepareForValidation() { $this->merge([ 'slug' => Str::slug($this->slug), ]); } If you need to do some logic after the validation runs, such as performing further validations, you can use the `withValidator(...)` method. public function withValidator($validator) { $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); } **Bonus:** Form Request is just an instance of `Illuminate\Http\Request`. Which means whatever properties or methods you have access to using the `request()` helper, you can also access it in the Form Request class. For further information about Form Requests, visit the official Laravel documentation here: [https://laravel.com/docs/7.x/validation#form-request-validation](https://laravel.com/docs/7.x/validation#form-request-validation) Cheers!

2019-01-06

`Illuminate\Support\Manager::class` is an abstract class that you can inherit from to assist you in constructing your own manager implementation for your drivers. This class only requires you to implement `getDefaultDriver()` method in your own class. Creating drivers can either be by using closure, or declaring a `create{DriverName}Driver` in your manager implementation. One good example of concrete implementation is Laravel's `Illuminate\Hashing\HashManager::class`, which inherits from `Manager::class` and shows you how to manage your drivers. **P.S:** I know, I know! Code to interface not inheritance. First, you can still code to interface while inheriting from this class. Also, this is just an optional approach for creating manager classes, so it's still up to you as a developer.

2018-10-10

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!

2018-09-19

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); } } ```

Marvin Quezon · Copyright © 2024 · Privacy · Sitemap