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/Web
Controllers -
/V1
is an immediate preparation for versioning: it's a personal habit to create API asv1
right away, with the idea that there may bev2
in the future, which would then land in the/Api/V2
subfolder
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...