Create API Service
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/create→Product::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.
Understanding the Structure
Basic API Service Structure
Every API Service must extend ApiService. Here's the basic structure:
<?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
ApiServicebase class - ✓ Constructor receives
Requestobject - ✓ Methods return
JsonResponse - ✓ Method names map to URLs (e.g.,
create()→/Product/create)
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.
<?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:
<?php
if(!$this->request->definePostSchema([
'name' => 'string', // Required
'price' => 'float', // Required
'?description' => 'string' // Optional
])) {
return $this->request->returnResponse();
}
Complete Example
Full CRUD API Service
Here's a complete example of an API Service with all CRUD operations:
<?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/create→Product::create()GET /Product/read→Product::read()PUT /Product/update→Product::update()DELETE /Product/delete→Product::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
JsonResponseobject. -
Naming Convention: Use PascalCase for service names (e.g.,
User.php,Product.php).
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.php → class Product)
Example: Create a Product API Service
<?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:
Productcreate()http://yourdomain.com/product/createAlternative: Use CLI Command
You can also use the GEMVC CLI command to generate the API Service file automatically from pre defined templates:
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.