# z-engine
**Repository Path**: wfdaj/z-engine
## Basic Information
- **Project Name**: z-engine
- **Description**: 仓库路径即仓库访问 URL 地址,更改仓库路径将导致原克隆地址不可用
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-04
- **Last Updated**: 2026-08-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# ZEngine
[](https://github.com/spexdw/z-engine/actions)
[](https://php.net/)
[](LICENSE)
A lightweight PHP framework. No bloat, just the essentials you actually need.
Looking for detailed readme? check ZEngine DeepWiki (Generated by ai expect documentation errors)
## Why?
I got tired of complex frameworks with thousands of files. ZEngine is simple - you can read the entire source code in an afternoon and understand exactly what's happening.
## What's Included
- **Routing** - Map URLs to functions, add parameters, group routes
- **Middleware** - Protect routes, handle auth, whatever you need
- **Database** - Query builder that doesn't get in your way
- **Services** - Session, cookies, cache, validation, logging etc.
- **Dependency Injection** - Automatic, no XML configs
- **Error Pages** - Custom error handling with nice debug screens
## Requirements
- PHP 8.1+
- Composer
- That's it
## Installation
Create a new project:
```bash
composer create-project spexdw/z-engine my-project
cd my-project
```
Or clone it directly:
```bash
git clone https://github.com/spexdw/z-engine.git my-project
cd my-project
composer install
```
## Quick Start
1. Edit `config/env.php` and set your config
2. Edit `app/routes.php` to add your routes
```php
$router->get('/hello/{name}', function ($name) {
return json(['message' => "Hello, $name!"]);
});
```
That's it. No generators, no boilerplate, just write code.
## Routing
```php
// Basic routes
$router->get('/users', function () {
return json(['users' => []]);
});
$router->post('/users', function (Request $request) {
$data = $request->json();
return json(['created' => $data], 201);
});
// Other HTTP methods
$router->put('/users/{id}', function ($id, Request $request) {
return json(['updated' => $id]);
});
$router->patch('/users/{id}', function ($id) {
return json(['patched' => $id]);
});
$router->delete('/users/{id}', function ($id) {
return json(['deleted' => $id]);
});
$router->any('/endpoint', function () {
return json(['method' => 'any']);
});
// URL parameters
$router->get('/users/{id}', function ($id) {
return json(['user_id' => $id]);
});
// Protect routes with middleware
$router->get('/admin', function () {
return json(['secret' => 'data']);
})->middleware(AdminMiddleware::class);
// Group routes
$router->group(['prefix' => '/api'], function ($router) {
$router->get('/users', fn() => json([]));
$router->get('/posts', fn() => json([]));
});
// Controller usage
$router->get('/users', 'UserController@index');
$router->post('/users', [UserController::class, 'store']);
```
## Controllers
Create a controller in `app/Controllers`:
```php
namespace ZEngine\App\Controllers;
use ZEngine\Core\Http\Request;
class UserController
{
public function index()
{
$users = db()->table('users')->get();
return view('users.index', ['users' => $users]);
}
public function store(Request $request)
{
$data = $request->all();
$id = db()->insert('users', $data);
return json(['id' => $id], 201);
}
}
```
## Views
Create views in `app/Views`:
```php
// Return a view
return view('welcome'); // app/Views/welcome.php
return view('users.index', ['users' => $users]); // app/Views/users/index.php
// Using view helper
$router->get('/', function () {
return view('welcome', ['name' => 'John']);
});
```
## Request & Response
```php
// Request helpers
$name = $request->input('name'); // From POST or GET
$email = $request->get('email'); // From query string
$data = $request->post('data'); // From POST
$all = $request->all(); // All input data
$json = $request->json(); // JSON payload
$token = $request->header('Authorization'); // Header
$bearer = $request->bearerToken(); // Bearer token
$file = $request->file('upload'); // Uploaded file
$ip = $request->ip(); // Client IP
// Response helpers
return json(['data' => []], 200); // JSON response
return view('page', ['key' => 'value']); // View response
return redirect('/home'); // Redirect
return Response::make('content', 200); // Plain text
```
## Database
```php
// Query builder
$users = db()->table('users')
->where('status', 'active')
->orderBy('created_at', 'DESC')
->get();
// Get first record
$user = db()->table('users')->where('id', 1)->first();
// Count records
$count = db()->table('users')->where('status', 'active')->count();
// Pagination with limit & offset
$users = db()->table('users')->limit(10)->offset(20)->get();
// Find by ID
$user = db()->find('users', 1);
// Raw queries
$results = db()->query('SELECT * FROM users WHERE id = ?', [1]);
// Insert/Update/Delete
db()->insert('users', ['name' => 'John', 'email' => 'john@example.com']);
db()->update('users', ['status' => 'active'], ['id' => 1]);
db()->delete('users', ['id' => 1]);
// Transactions
db()->beginTransaction();
try {
db()->insert('users', ['name' => 'John']);
db()->commit();
} catch (Exception $e) {
db()->rollback();
}
```
## Services
```php
// Session
session()->set('user_id', 123);
$userId = session()->get('user_id');
$token = session()->token(); // CSRF token
// Cache
cache()->put('key', 'value', 300); // 5m
$value = cache()->get('key');
// Cache with callback (runs only if key doesnt exist)
$users = cache()->remember('users', 3600, function () {
return db()->table('users')->get();
});
// Cookies
cookie()->set('theme', 'dark', time() + 3600);
$theme = cookie()->get('theme');
// Validation
$rules = ['email' => 'required|email', 'age' => 'min:18'];
$isValid = validator()->validate($data, $rules);
// Logging
logger()->error('Something broke', ['context' => 'details']);
logger()->warning('Warning message');
logger()->info('Info message');
logger()->debug('Debug data', ['user_id' => 123]);
// Events
event()->listen('user.registered', function ($userId) {
logger()->info('User registered with ID: ' . $userId);
});
event()->dispatch('user.registered', 123);
// Hash (Password hashing)
$hash = hasher()->make('password123');
$isValid = hasher()->check('password123', $hash);
// Mail
mail()->send('user@example.com', 'Welcome!', 'Hello, welcome to our app!');
// Rate Limiting
$rateLimit = ratelimit()->check('api.endpoint', [
'1minute' => 10,
'1hour' => 100
]); // you can give a identifier if u want
if ($rateLimit) {
return Response::json(['error' => $rateLimit], 429);
}
```
## Middleware
Create a middleware in `app/Middleware`:
```php
class AuthMiddleware
{
public function handle(Request $request, Closure $next)
{
if (!$request->header('Authorization')) {
return Response::json(['error' => 'Unauthorized'], 401);
}
return $next($request);
}
}
```
Use it:
```php
$router->get('/dashboard', function () {
return json(['data' => 'secret']);
})->middleware(AuthMiddleware::class);
```
## Custom Services
Add your service to `core/Providers.php`:
```php
private static function registerMyService(Container $container): void
{
$container->singleton('myservice', function () {
return new MyService();
});
}
```
Then call `self::registerMyService($container);` in the `register()` method.
Use it anywhere:
```php
$result = app('myservice')->doSomething();
```
## Cron-Jobs (Tasks)
Add your cron to `App\Tasks\MyCron` then add your task to `/cron.php`
```php
try {
$doSomething = new DoSomething();
$doSomething->handle();
} catch (\Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
```
Note : cron.php only accessible on cli with CRON_KEY
## Error Handling
Set `APP_DEBUG=true` in `.env` for detailed error pages with code snippets.
Set `APP_DEBUG=false` for production to show clean error pages.
Set `MAINTENANCE_MODE=1` for Maintenance mode (ip whitelist & maintenance msg included)
All errors are logged to `storage/logs/error.log`.
## Contributing
Found a bug? Want a feature? Open an issue or PR. Keep it simple.
## License
MIT. Do whatever you want with it.
## Credits
Built by [spexdw](https://github.com/spexdw) because existing frameworks were too complicated :p