This project is a RESTful API built in native PHP following modern PHP standards (PSR-4 autoloading with PascalCase namespace directories, PSR-12 coding standard, strict types, pure JSON REST conventions, and automated PHPUnit testing). It provides endpoints to manage user data, allowing clients to perform full CRUD (Create, Read, Update, Delete) operations using clean JSON payloads.
- Standard PSR-4 Autoloading: All application source code is consolidated inside
src/under theApp\namespace matching directory casing (App\Config\,App\Controllers\,App\Models\,App\Routes\,App\Utils\). - Reusable Utility Layer (
App\Utils):Response::json(): Standardized HTTP status codes, headers, and JSON encoding.Request::getJson(): Secure JSON request parsing with fallback and mock testing support.Logger::error(): Centralized error logging with absolute project path resolution.
- Pure RESTful Architecture: All requests and responses communicate using standard
application/json. - Type Safety: Enforces
declare(strict_types=1);and scalar typing throughout models and controllers. - Automated Testing: Comprehensive PHPUnit test suite covering utilities, database configuration, and model CRUD operations using in-memory SQLite (
:memory:).
All request and response bodies use JSON (Content-Type: application/json).
- Method:
GET / - Response:
200 OK
{
"status": "success",
"message": "Welcome to Basic PHP RESTful API"
}- Method:
GET /api/users - Response:
200 OK
{
"status": "success",
"message": "Successfully retrieved all users",
"data": [
{
"id": 1,
"name": "John Doe",
"age": 30,
"job": "Software Engineer"
}
]
}- Method:
POST /api/users - Headers:
Content-Type: application/json - Request Body:
{
"name": "Alice Smith",
"age": 28,
"job": "Backend Developer"
}- Response:
201 Created
{
"status": "success",
"message": "Successfully created user",
"data": {
"id": 2,
"name": "Alice Smith",
"age": 28,
"job": "Backend Developer"
}
}- Method:
GET /api/users/:id - Response:
200 OK
{
"status": "success",
"message": "Successfully retrieved user",
"data": {
"id": 1,
"name": "John Doe",
"age": 30,
"job": "Software Engineer"
}
}- Error Response:
404 Not Foundif user does not exist.
- Method:
PATCH /api/users/:id - Headers:
Content-Type: application/json - Request Body (provide any combination of
name,age, orjob):
{
"job": "Lead Architect"
}- Response:
200 OK
{
"status": "success",
"message": "Successfully updated user",
"data": {
"id": 1,
"name": "John Doe",
"age": 30,
"job": "Lead Architect"
}
}- Method:
DELETE /api/users/:id - Response:
200 OK
{
"status": "success",
"message": "Successfully deleted user"
}.
βββ public/
β βββ index.php # Application Entry Point (Bootstrap & Routing)
βββ src/
β βββ Config/
β β βββ Database.php # App\Config\Database - PDO Connection Management
β βββ Controllers/
β β βββ UsersController.php # App\Controllers\UsersController - Request Handling
β βββ Models/
β β βββ User.php # App\Models\User - Database CRUD Operations
β βββ Routes/
β β βββ api.php # Route Matching & HTTP Method Dispatcher
β βββ Utils/
β βββ Logger.php # App\Utils\Logger - Centralized Error Logging
β βββ Request.php # App\Utils\Request - JSON Body Parser
β βββ Response.php # App\Utils\Response - Standardized JSON Emitter
βββ tests/
β βββ Unit/
β βββ DatabaseTest.php # Database configuration unit tests
β βββ RequestTest.php # Request parsing unit tests
β βββ ResponseTest.php # Response emitter unit tests
β βββ UserTest.php # User model in-memory SQLite unit tests
βββ .env.example # Environment variables template
βββ composer.json # PSR-4 Autoload mappings & PHPUnit dependencies
βββ phpunit.xml # PHPUnit test suite configuration
βββ README.md
- PHP 7.4 or higher (PHP 8.x recommended)
- MySQL / MariaDB database
- Composer
- Clone the repository:
git clone https://github.com/FarrelAD/Basic-PHP-RESTful-API.git cd Basic-PHP-RESTful-API - Install dependencies:
composer install
- Copy environment configuration:
Configure your database credentials in
cp .env.example .env
.env.
Execute unit tests using Composer:
composer testOr directly with PHPUnit:
vendor/bin/phpunitcomposer devThe API will be available at http://localhost:8000.
This project ships three code-quality tools as require-dev dependencies, each accessible via a Composer shortcut:
| Tool | Command | Purpose |
|---|---|---|
| PHP_CodeSniffer | composer lint |
Checks code against the PSR-12 standard |
| PHP CS Fixer | composer format |
Verifies formatting without writing (dry-run) |
| PHP CS Fixer | composer format:fix |
Auto-fixes formatting issues in place |
| PHPStan | composer analyse |
Static type analysis at level 6 |
phpcs.xml.distβ PHP_CodeSniffer rules (PSR-12, targetssrc/andpublic/).php-cs-fixer.dist.phpβ PHP CS Fixer rules (PSR-12 + strict types + import ordering)phpstan.neonβ PHPStan settings (level 6, targetssrc/)
This project uses GitHub Actions with two separate, purpose-built workflows.
Triggered automatically on every Pull Request targeting main. All jobs run in parallel on PHP 8.3:
PR β main
βββ syntax-lint php -l on all .php files
βββ lint phpcs (PSR-12)
βββ format php-cs-fixer --dry-run (no write)
βββ analyse phpstan (level 6)
βββ test phpunit
All five checks must pass before a PR is considered safe to merge.
Triggered manually only via the GitHub Actions UI (workflow_dispatch). Inputs:
| Input | Options | Default |
|---|---|---|
environment |
staging / production |
staging |
skip_tests |
true / false |
false |
Jobs run sequentially:
Manual trigger
βββ test Full test suite + syntax check
βββ build composer --no-dev --optimize-autoloader β ZIP artifact
βββ deploy Upload artifact β deploy stub β smoke test stub
To wire up real deployment, edit the deploy step in .github/workflows/deploy.yml and add your secrets (SSH host, key, deploy path, etc.) to the GitHub repository's Settings β Secrets and variables β Actions.
Required GitHub Secrets for Deployment:
SSH_HOST: The IP address or domain of your VPS.SSH_USER: The SSH username (e.g.,ubuntuorroot).SSH_PRIVATE_KEY: Your SSH private key for authentication.DEPLOY_PATH: The absolute path on your server where the app should be deployed (e.g.,/var/www/api).SSH_PORT: (Optional) Custom SSH port, defaults to22.
The deployment uses a zero-downtime symlink approach:
- Releases are stored in
$DEPLOY_PATH/releases/<commit-hash> - A persistent environment file is kept at
$DEPLOY_PATH/shared/.env - The live site points to
$DEPLOY_PATH/current
This project is open-source and available under the MIT License. Feel free to modify and use it as a learning resource.