Introduction
Laravel is one of the most powerful PHP frameworks for modern web development, offering built-in tools for API development. While Laravel provides API Resources for structured responses, it is also possible to build a RESTful API using only routes and controllers. In this tutorial, we will create a RESTful API in Laravel 11 without using API Resources, demonstrating how to handle API requests directly through controllers.
If you’re looking to learn Laravel API development, including CRUD operations, API authentication, and Laravel API best practices, this guide is for you.
What is a RESTful API?
A RESTful API (Representational State Transfer API) allows communication between a client and server using standard HTTP methods such as GET, POST, PUT, and DELETE. Laravel makes it easy to create APIs by leveraging built-in routing and middleware features.

Setting Up a Laravel 11 Project
To begin, install Laravel 11 using Composer:
composer create-project laravel/laravel laravel-api
Navigate to your project directory:
cd laravel-api
Configure your database in the .env
file:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_api
DB_USERNAME=root
DB_PASSWORD=
Run the migration command to create default tables:
php artisan migrate
Creating API Routes Without API Resources
In Laravel 11, API routes are defined in the routes/api.php
file. Instead of using apiResource()
, we will define separate routes for each CRUD operation on a Car
model.
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CarController;
Route::get('/cars', [CarController::class, 'index']); // Get all cars
Route::post('/cars', [CarController::class, 'store']); // Create a new car
Route::get('/cars/{id}', [CarController::class, 'show']); // Get a specific car
Route::put('/cars/{id}', [CarController::class, 'update']); // Update a car
Route::delete('/cars/{id}', [CarController::class, 'destroy']); // Delete a car
API Endpoints Table
HTTP Method | Endpoint | Action | Description |
---|---|---|---|
GET | /api/cars | index | Fetch all cars |
POST | /api/cars | store | Create a new car |
GET | /api/cars/{id} | show | Fetch a single car |
PUT | /api/cars/{id} | update | Update a car |
DELETE | /api/cars/{id} | destroy | Delete a car |
Creating the Car Model and Migration
Generate the Car
model along with its migration:
php artisan make:model Car -m
Modify the migration file xxxx_xx_xx_create_cars_table.php
:
public function up()
{
Schema::create('cars', function (Blueprint $table) {
$table->id();
$table->string('make');
$table->string('model');
$table->integer('year');
$table->decimal('price', 10, 2);
$table->timestamps();
});
}
Run the migration command:
php artisan migrate
Creating the Car Controller
Generate the controller using the following command:
php artisan make:controller CarController
Modify the app/Http/Controllers/CarController.php
file:
namespace App\Http\Controllers;
use App\Models\Car;
use Illuminate\Http\Request;
class CarController extends Controller
{
public function index()
{
return response()->json(Car::all(), 200);
}
public function store(Request $request)
{
$validated = $request->validate([
'make' => 'required|string|max:255',
'model' => 'required|string|max:255',
'year' => 'required|integer',
'price' => 'required|numeric',
]);
$car = Car::create($validated);
return response()->json($car, 201);
}
public function show($id)
{
$car = Car::find($id);
if (!$car) {
return response()->json(['message' => 'Car not found'], 404);
}
return response()->json($car, 200);
}
public function update(Request $request, $id)
{
$car = Car::find($id);
if (!$car) {
return response()->json(['message' => 'Car not found'], 404);
}
$car->update($request->all());
return response()->json($car, 200);
}
public function destroy($id)
{
$car = Car::find($id);
if (!$car) {
return response()->json(['message' => 'Car not found'], 404);
}
$car->delete();
return response()->json(['message' => 'Car deleted successfully'], 200);
}
}
Testing the API
You can test the Laravel API using Postman, cURL, or Laravel’s built-in testing tools. Here’s an example cURL command to fetch all cars:
curl -X GET http://localhost:8000/api/cars
Additional Resources
Conclusion
In this tutorial, we built a RESTful API in Laravel 11 without using API Resources. Instead, we created individual API routes and a controller to handle each HTTP request. We covered how to define routes, create a model and migration, and implement CRUD operations in Laravel.
For production-ready APIs, consider Laravel authentication (Sanctum or Passport) and API documentation for better security and usability.
If you need assistance with Laravel API development or Docker containerization, Techliphant can help! Our team specializes in building scalable, high-performance APIs tailored to your business needs.