Skip to content

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

php artisan make:controller PlanetController --api --model=Planet

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:

// In the route: GET /planets/{planet}
// In the method: show(Planet $planet)

  • 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

1. The flag for creating an API controller is:

2. What status should be returned upon successful creation?

3. Route Model Binding allows you to:

4. When deleting a planet, we return:

5. `$request->validate()` is used for:


🚀 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 in app/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