-
Notifications
You must be signed in to change notification settings - Fork 17
Home
GEMVC - The PHP Multi-Platform Microservices REST API Framework
GEMVC is a multi-platform PHP framework to create REST API that works on:
- ✅ OpenSwoole (async, WebSocket, hot reload)
- ✅ Apache (traditional PHP-FPM)
- ✅ Nginx (high performance, reverse proxy)
Key Features:
- 🔒 90% Security Automatic - Input sanitization, SQL injection prevention, path protection
- 🌐 Webserver-Agnostic - Same code works on all platforms
- 🛠️ CLI Code Generation - Generate Services, Controllers, Models, Tables
- 📝 Simple API - Clean, straightforward code structure
- ⚡ High Performance - Connection pooling, async capabilities
- ✅ PHPStan Level 9 - Write type-safe, bug-free code with the highest static analysis level
GEMVC uses a 4-layer architecture pattern but as recommendation , it never force you :
API Layer (app/api/) → URL endpoints, schema validation
↓
Controller Layer (app/controller/) → Business logic orchestration
↓
Model Layer (app/model/) → Data logic, validations
↓
Table Layer (app/table/) → Database access, queries
Purpose: URL endpoints, request validation, authentication
Naming: PascalCase (e.g., User.php, Product.php)
Responsibilities:
- Handel Authentication and Sanitization for incoming request
- Request schemas what input accepted by this endpoint (
definePostSchema(),defineGetSchema()) - Handle authentication (
$request->auth()) - Delegate to Controller layer
Example openSwoole (app/api/User.php) is endpoint domain.com/user/:
Example apache/nginx (app/api/User.php) is endpoint domain.com/api/user/:
Example openSwoole (app/api/User.php method create()) is endpoint domain.com/user/create:
Example apache/nginx (app/api/User.php method create()) is endpoint domain.com/api/user/create:
Note in .env file you can by setting SERVICE_IN_URL_SECTION=0 and METHOD_IN_URL_SECTION=1 have same result as openSwoole:
Why? because of support traditional shared cpanel hosting based on NginX and Apache:
Key Points:
- ✅ Extends
ApiService(orSwooleApiServicefor OpenSwoole) - ✅ Uses
definePostSchema()for validation - ✅ Uses
?prefix for optional fields:'?name' => 'string' - ✅ Delegates to Controller, doesn't handle business logic
Purpose: Business logic orchestration
Naming: PascalCase + "Controller" suffix (e.g., UserController.php)
Responsibilities:
- Orchestrate business logic
- Map request data to models
- Handle request/response flow
Example (app/controller/UserController.php):
Key Points:
- ✅ Extends
Controller - ✅ Uses
mapPostToObject()to convert request to model - ✅ Can specify method calls:
'password' => 'setPassword()' - ✅ Delegates to Model layer
Purpose: Data logic, validations, transformations
Naming: PascalCase + "Model" suffix (e.g., UserModel.php)
Responsibilities:
- Business validations (e.g., duplicate email check)
- Data transformations (e.g., password hashing)
- Error handling
Example (app/model/UserModel.php):
Key Points:
- ✅ Extends corresponding
Tableclass (e.g.,UserModel extends UserTable) - ✅ Contains business logic and validations
- ✅ Uses
insertSingleQuery(),updateSingleQuery(),deleteByIdQuery() - ✅ Returns
JsonResponseobjects
Purpose: Database access, queries, schema definition
Naming: PascalCase + "Table" suffix (e.g., UserTable.php)
Responsibilities:
- Define database table structure
- Define properties matching database columns
- Provide query methods
Example (app/table/UserTable.php):
Key Points:
- ✅ Extends
Tableclass - ✅ Properties match database columns (with types)
- ✅
protectedproperties are not exposed in SELECT queries - ✅ Properties starting with
_are ignored in CRUD operations (see below) - ✅ Uses fluent query builder:
$this->select()->where()->limit()->run() - ✅ Returns
null|staticornull|static[]for query methods
GEMVC maps URLs to code automatically:
URL: /api/User/create
↓
Extracts: Service = "User", Method = "create"
↓
Loads: app/api/User.php
↓
Calls: User::create()
URL Structure:
/api/{ServiceName}/{MethodName}
Examples:
-
POST /api/User/create→User::create() -
GET /api/User/read/?id=1→User::read() -
POST /api/User/update→User::update() -
POST /api/User/delete→User::delete() -
GET /api/User/list→User::list()
Configuration (.env):
SERVICE_IN_URL_SECTION=1 # Service name position in URL
METHOD_IN_URL_SECTION=2 # Method name position in URLLaravel/Symfony: MVC (Model-View-Controller)
GEMVC: 4-Layer (API → Controller → Model → Table)
Laravel: Routes defined in routes/web.php or routes/api.php
GEMVC: Automatic URL-to-class mapping (/api/User/create → User::create())
Laravel: Form Requests, Validation Rules
GEMVC: definePostSchema() method with inline validation
Laravel: Eloquent ORM (User::create(), User::find())
GEMVC: Fluent Query Builder ($this->select()->where()->run())
Laravel: Singular models (User), plural tables (users)
GEMVC: Consistent naming (User API, UserController, UserModel, UserTable)
Laravel: Various response types
GEMVC: Consistent JsonResponse with Response::success(), Response::created(), etc.
Laravel: Manual middleware, CSRF tokens
GEMVC: 90% automatic - Input sanitization, SQL injection prevention built-in
- GEMVC is NOT Laravel - Don't expect Laravel conventions
- GEMVC is NOT Symfony - Different architecture and patterns
- Follow GEMVC patterns - Use the User example as a reference
- 4-Layer Architecture - API → Controller → Model → Table
- Automatic Security - Input sanitization, SQL injection prevention built-in
- ✅ Extend
ApiServicefor API classes - ✅ Extend
Controllerfor controllers - ✅ Extend
Tablefor models and tables - ✅ Use
definePostSchema()for validation - ✅ Use fluent query builder for database operations
- ✅ Return
JsonResponseobjects - ✅ Use PHPStan Level 9 - Write type-safe code!
- ✅ Add type hints to all methods and properties
- ✅ Use strict types:
declare(strict_types=1); - ✅ Use
_prefix for aggregation - Properties starting with_are ignored in CRUD operations
- ❌ Don't use Laravel conventions
- ❌ Don't create routes files
- ❌ Don't use Eloquent-style syntax
- ❌ Don't skip the 4-layer architecture
- ❌ Don't manually sanitize inputs (it's automatic!)
- ❌ Don't skip PHPStan - Run it regularly!
- ❌ Don't ignore type errors - Fix them!
- ❌ Don't use
mixedtypes without reason
GEMVC is built with PHPStan Level 9 (the highest level!) and you should use it too!
PHPStan Level 9 catches:
- ✅ Type errors before runtime
- ✅ Null pointer exceptions
- ✅ Undefined method calls
- ✅ Incorrect array access
- ✅ Type mismatches
- ✅ Missing return types
- ✅ And much more!
During gemvc init, you'll be asked if you want to install PHPStan. Say YES!
Or install manually:
composer require --dev phpstan/phpstan# Run analysis
vendor/bin/phpstan analyse
# Or use composer script
composer phpstanWithout PHPStan (bugs in production):
public function getUser($id)
{
return $this->selectById($id)->name; // ❌ Might be null!
}With PHPStan Level 9 (caught at development):
public function getUser(int $id): ?UserModel
{
$user = $this->selectById($id);
if (!$user) {
return null;
}
return $user; // ✅ Type-safe!
}- Type Safety: Catch errors before they happen
- Better IDE Support: Auto-completion, refactoring
- Cleaner Code: Forces you to write explicit types
- Fewer Bugs: Static analysis catches issues early
- Team Consistency: Everyone writes code the same way
GEMVC includes:
- ✅ Level 9 configuration (highest level)
- ✅ OpenSwoole stubs for proper type checking
- ✅ Redis stubs for connection type safety
- ✅ Pre-configured
phpstan.neonfile
Use PHPStan Level 9 - Write clean, type-safe, bug-free code! 🎯
MIT License bei Ali Khorsandfard gemvc.de(https://www.gemvc.de)
Built with ❤️ for developers who want simplicity, security, and performance.