Create API Service

15 minutes BEGINNER

Learn how to create the API Service layer - the entry point for all HTTP requests. Master schema validation, authentication, and request handling.

What You'll Learn

Understanding API Service

What is the API layer and its responsibilities

Schema Validation

Validate incoming requests with definePostSchema()

Creating API Service

Create your first API Service class

Video Coming Soon...

What is API Service Layer?

The API Service Layer is the entry point for all HTTP requests in GEMVC. It's the first layer in the 4-layer architecture and handles:

  • URL Endpoints - Maps HTTP requests to methods (e.g., POST /product/createProduct::create())
  • Schema Validation - Validates incoming request data structure and types
  • Authentication - Checks JWT tokens and user roles
  • Delegation - Passes validated requests to Controller layer

Key Principle: The API Service layer never contains business logic. It only validates, authenticates, and delegates to the Controller layer.

1

Understanding the Structure

Basic API Service Structure

Every API Service must extend ApiService. Here's the basic structure:

app/api/Product.php
<?php
namespace App\Api;

use Gemvc\Core\ApiService;
use Gemvc\Http\Request;
use Gemvc\Http\JsonResponse;
use Gemvc\Http\Response;

class Product extends ApiService
{
    public function __construct(Request $request)
    {
        parent::__construct($request);
    }

    public function create(): JsonResponse
    {
    // JSON response and response code 201 (Created)
        return Response::created(null,1,'Product created successfully');
    }
}

Key Points:

  • ✓ Extends ApiService base class
  • ✓ Constructor receives Request object
  • ✓ Methods return JsonResponse
  • ✓ Method names map to URLs (e.g., create()/Product/create)
2

Schema Validation

Validating Request Data

Use definePostSchema() to validate POST requests, or defineGetSchema() for GET requests. The method returns true if validation passes, false otherwise.

app/api/Product.php - Schema Validation Example
<?php
public function create(): JsonResponse
{
    // Validate POST request schema
    if(!$this->request->definePostSchema([
        'name' => 'string',
        'price' => 'float',
        '?description' => 'string'
    ])) {
        // Validation failed - return error response
        return $this->request->returnResponse();
    }
    
    // Validation passed - delegate to Controller
    return (new ProductController($this->request))->create();
}

⚠️ ProductController Not Created Yet

You'll see an error if you try to use ProductController right now because we haven't created it yet. Don't worry! This is expected. We'll learn how to create the ProductController class in the next step: Create Controller.

Supported Schema Types:

  • 'string' - String value
  • 'int' or 'integer' - Integer value
  • 'float' - Float value
  • 'bool' or 'boolean' - Boolean value
  • 'email' - Valid email address
  • 'url' - Valid URL
  • 'array' - Array value

Optional Fields:

Use ? prefix to make fields optional:

Optional Fields Example
<?php
if(!$this->request->definePostSchema([
    'name' => 'string',        // Required
    'price' => 'float',        // Required
    '?description' => 'string' // Optional
])) {
    return $this->request->returnResponse();
}
3

Complete Example

Full CRUD API Service

Here's a complete example of an API Service with all CRUD operations:

app/api/Product.php - Complete Example
<?php
namespace App\Api;

use App\Controller\ProductController;
use Gemvc\Core\ApiService;
use Gemvc\Http\Request;
use Gemvc\Http\JsonResponse;

class Product extends ApiService
{
    public function __construct(Request $request)
    {
        parent::__construct($request);
    }

    // Create - Public endpoint
    public function create(): JsonResponse
    {
        if(!$this->request->definePostSchema([
            'name' => 'string',
            'price' => 'float',
            '?description' => 'string'
        ])) {
            return $this->request->returnResponse();
        }
        
        return (new ProductController($this->request))->create();
    }

    // Read - Requires authentication (see Authentication & Security section)
    public function read(): JsonResponse
    {
        if (!$this->request->auth()) {
            return $this->request->returnResponse();
        }
        
        return (new ProductController($this->request))->read();
    }

    // Update - Requires authentication (see Authentication & Security section)
    public function update(): JsonResponse
    {
        if (!$this->request->auth()) {
            return $this->request->returnResponse();
        }
        
        if(!$this->request->definePostSchema([
            'name' => 'string',
            '?price' => 'float',
            '?description' => 'string'
        ])) {
            return $this->request->returnResponse();
        }
        
        return (new ProductController($this->request))->update();
    }

    // Delete - Requires admin role (see Authentication & Security section)
    public function delete(): JsonResponse
    {
        if (!$this->request->auth(['admin'])) {
            return $this->request->returnResponse();
        }
        
        return (new ProductController($this->request))->delete();
    }
}

⚠️ ProductController Not Created Yet

The use App\Controller\ProductController; import and all ProductController references will cause errors until we create the Controller class. This is normal! We'll create ProductController in the next step: Create Controller.

URL Mapping:

  • POST /Product/createProduct::create()
  • GET /Product/readProduct::read()
  • PUT /Product/updateProduct::update()
  • DELETE /Product/deleteProduct::delete()

Note: URL mapping is automatic - no routes configuration needed! Class name = first URL segment, method name = second URL segment.

Authentication: You can protect endpoints using $this->request->auth() or $this->request->auth(['role']). For detailed authentication and security information, see the Authentication & Security section.

Important Notes

  • No Business Logic: API Service layer should never contain business logic. Always delegate to Controller.
  • Automatic Sanitization: All inputs are automatically sanitized - no manual sanitization needed!
  • Always Return JsonResponse: All methods must return a JsonResponse object.
  • Naming Convention: Use PascalCase for service names (e.g., User.php, Product.php).
4

Create Your API Service

Manual Creation

To create an API Service, simply create a new PHP class file in the app/api/ directory. For example, to create a Product API Service:

File Location:

Create app/api/Product.php

The class name should match the filename (e.g., Product.phpclass Product)

Example: Create a Product API Service

app/api/Product.php
<?php
namespace App\Api;

use App\Controller\ProductController;
use Gemvc\Core\ApiService;
use Gemvc\Http\Request;
use Gemvc\Http\JsonResponse;

class Product extends ApiService
{
    public function __construct(Request $request)
    {
        parent::__construct($request);
    }

    public function create(): JsonResponse
    {
        if(!$this->request->definePostSchema([
            'name' => 'string',
            'price' => 'float',
            'description' => 'string'
        ])) {
            return $this->request->returnResponse();
        }
        
        return (new ProductController($this->request))->create();
    }
}

⚠️ ProductController Not Created Yet

The use App\Controller\ProductController; import will cause an error because the Controller class doesn't exist yet. This is expected! We'll create the ProductController class in the next step: Create Controller.

✨ Automatic Routing - No Configuration Needed!

GEMVC automatically detects and routes your API classes! You don't need to create or configure any routes. The framework automatically maps URLs to your classes and methods.

How URL Mapping Works:

  • Class name = First URL segment
  • Method name = Second URL segment

Example:

Class: Product
Method: create()
URL: http://yourdomain.com/product/create

Alternative: Use CLI Command

You can also use the GEMVC CLI command to generate the API Service file automatically from pre defined templates:

Terminal
gemvc create:service Product

Tip: Use gemvc create:service Product -cmt to create all 4 layers (API, Controller, Model, Table) at once!

🎉 API Service Created!

Great job! You've learned how to create API Service layer. Now let's move to the Controller layer to handle business logic.