Chapter 2.4: The PlanetController API Controller
Time to learn: 1 hour
1. The Controller: Mission Control for Celestial Objects
In the MVC architecture, the controller is the intermediary between models and requests:
- 📡 It receives HTTP requests (GET, POST, PUT, DELETE)
- 🔍 It retrieves data from the database via models
- 📦 It formats JSON responses for the API
💡 Space Analogy:
PlanetController
= The mission's MCC (Mission Control Center):
- It receives requests from Earth (
GET /planets
)- It sends commands to the "probes" (models)
- It returns telemetry in JSON format
2. Creating a Resource Controller
A resource controller automatically includes methods for CRUD operations.
Step 1: Generate the controller
What will be created in app/Http/Controllers/PlanetController.php
:
<?php
namespace App\Http\Controllers;
use App\Models\Planet;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule; // Don't forget to add this import
class PlanetController extends Controller
{
// Display a listing of the planets.
public function index(Request $request) {}
// Store a newly created planet in storage.
public function store(Request $request) {}
// Display the specified planet.
public function show(Planet $planet) {}
// Update the specified planet in storage.
public function update(Request $request, Planet $planet) {}
// Remove the specified planet from storage.
public function destroy(Planet $planet) {}
}
3. Implementing the API Methods
A. index()
- Get a list of planets
<?php
public function index(Request $request)
{
// Get planets with pagination, 15 per page
$planets = Planet::paginate($request->get('per_page', 15));
return response()->json($planets); // Automatically 200 OK
}
B. store()
- Create a new planet
<?php
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required|string|max:255|unique:planets',
'description' => 'required|string',
'size_km' => 'required|integer|min:100',
'solar_system' => 'required|string|max:100',
'image_url' => 'nullable|url',
'is_habitable' => 'boolean'
]);
$planet = Planet::create($data);
return response()->json($planet, 201); // 201 Created
}
C. show()
- View a single planet
<?php
public function show(Planet $planet)
{
return response()->json($planet); // Automatic 200 OK
}
D. update()
- Update a planet
<?php
public function update(Request $request, Planet $planet)
{
$data = $request->validate([
'name' => [
'string',
'max:255',
Rule::unique('planets')->ignore($planet->id),
],
'description' => 'sometimes|string', // 'sometimes' - validate only if the field is present
'size_km' => 'sometimes|integer|min:100',
'solar_system' => 'sometimes|string|max:100',
'image_url' => 'sometimes|nullable|url',
'is_habitable' => 'sometimes|boolean'
]);
$planet->update($data);
return response()->json($planet); // 200 OK
}
E. destroy()
- Delete a planet
<?php
public function destroy(Planet $planet)
{
$planet->delete();
return response()->json(null, 204); // 204 No Content
}
4. Route Model Binding
Laravel automatically injects the planet object based on the ID:
- If the planet is not found → automatic 404
- No need for manual
findOrFail()
queries
5. Formatting Responses
Example of an improved response for index()
:
<?php
public function index()
{
return response()->json([
'success' => true,
'data' => Planet::all(),
'message' => 'Planets successfully retrieved'
]);
}
Response for a 404 error (automatic):
{
"message": "No query results for model [App\\Models\\Planet] 123",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException"
}
Review Quiz
🚀 Chapter Summary:
You have created the "control panel" for the planetary system! Your controller can now:
- 🌌 Show a list of planets (
index
) - 🪐 Create new worlds (
store
) - 🔭 Detail a planet's data (
show
) - 🛠️ Update information (
update
) - 💥 Destroy planets (
destroy
)
All that's left is to define the routes! In the next chapter, we will connect the controller to the API routes.
📌 Checkpoint:
Make sure you have
PlanetController.php
inapp/Http/Controllers
with 5 methods.⚠️ If you have errors:
- Check the model name:
use App\Models\Planet;
- Check the imports
- For PostgreSQL: make sure
Planet::all()
returns data- If you have problems with Tinker: run
composer dump-autoload