Time for us to build the first API endpoint. The description from the client looks like this:
A public (no auth) endpoint to get a list of paginated travels. It must return only public travels
So let's transform it into a plan of action for this lesson:
- New API Controller and Route
- Return all Travels with Pagination and API Resource
- Write automated Tests for it with Factories
Controller and Route with Prefix
First, let's generate the Controller:
php artisan make:controller Api/V1/TravelController
As you can see, I immediately add two subfolders:
-
/Api, which means we will store all API controllers in there - maybe in the future, there will be separate/WebControllers -
/V1is an immediate preparation for versioning: it's a personal habit to create API asv1right away, with the idea that there may bev2in the future, which would then land in the/Api/V2subfolder
For now, we need only one method in the Controller, so we have a choice to make it an Invokable, but I have a feeling that there may be more methods like show() in the future, so let's stick to a typical Route::resource() naming and create an index() method:
app/Http/Controllers/Api/V1/TravelController.php:
namespace App\Http\Controllers\Api\V1; use App\Http\Controllers\Controller;use App\Models\Travel; class TravelController extends Controller{ public function index() { return Travel::where('is_public', true)->get(); }}
We also need the Route for that Controller:
routes/api.php:
use App\Http\Controllers\Api\V1\TravelController; // ... Route::get('travels', [TravelController::class, 'index']);
At this point, the endpoint URL would be /api/travels. But I want to use the versioning in the Routes, the same as with namespaces above, to have /api/v1/travels.
We could add this prefix in three different places...
One useful thing I've found is when you use laravel ide-helper to generate docblocks for every model, you can then write a comment in Resources, for example, TravelResource above the returned array specifying
/** @var Travel $this */then it is easier to see the attributes of the model as the IDE can show which are available.Property accessed via magic method, but the added comments would resolve that (note: I haven't used Larastan yet so not sure how different they are in this sense)Thanks for the valuable comment, we'll see what Larastan will say, at the end of this course, and we may make changes accordingly :)