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
- A web server (e.g., Apache, Nginx, or PHP built in web server)
- 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/phpunit
composer dev
The 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.