PHP code example of zapj / zap-php-framework

1. Go to this page and download the library: Download zapj/zap-php-framework library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

zapj / zap-php-framework example snippets



error_reporting(E_ALL);
ini_set('display_errors', true);

define('ROOT_PATH', dirname(__DIR__));
define('APP_PATH', ROOT_PATH . DIRECTORY_SEPARATOR . 'app');
define('CONFIG_PATH', ROOT_PATH . DIRECTORY_SEPARATOR . 'config');
define('VAR_PATH', ROOT_PATH . DIRECTORY_SEPARATOR . 'var');
define('VENDOR_PATH', ROOT_PATH . DIRECTORY_SEPARATOR . 'vendor');


use zap\http\Route;

// HTTP 方法快捷注册
Route::get('/user/{id}', function($id) {
    return "User ID: $id";
});
Route::post('/user', 'UserController@save');
Route::put('/user/{id}', 'UserController@update');
Route::patch('/user/{id}', 'UserController@partialUpdate');
Route::delete('/user/{id}', 'UserController@destroy');

// 占位符语法
Route::get('/posts/{id:\d+}', 'PostController@show');     // 正则约束
Route::get('/posts/{slug}', 'PostController@bySlug');      // 任意字符

Route::any('/contact', 'ContactController@index');          // 匹配所有方法
Route::match(['GET', 'POST'], '/form', 'FormController@handle');

// {name:pattern} 格式
Route::get('/user/{id:\d+}', ...);              // 仅数字
Route::get('/user/{name:[a-zA-Z]+}', ...);       // 仅字母
Route::get('/file/{path:.*}', ...);              // 任意路径(包含斜杠)

// 简单占位符 {name} = 匹配除 '/' 外的任意字符
Route::get('/api/{resource}/{id}', ...);

// 注册命名路由
Route::get('/user/profile', 'UserController@profile')->name('profile');
Route::get('/posts/{id:\d+}', 'PostController@show')->name('post.show');

// 生成 URL
$url = Router::url('profile');                          // /user/profile
$url = Router::url('post.show', ['id' => 123]);         // /posts/123

// 前缀分组
Route::group(['prefix' => 'admin'], function() {
    Route::get('/dashboard', 'Admin\DashboardController@index');   // GET /admin/dashboard
    Route::get('/users', 'Admin\UserController@index');            // GET /admin/users
});

// 中间件分组
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function() {
    Route::get('/settings', 'Admin\SettingsController@index');
});

// 嵌套分组
Route::group(['prefix' => 'api'], function() {
    Route::group(['prefix' => 'v1'], function() {
        Route::get('/users', 'Api\V1\UserController@index');       // GET /api/v1/users
    });
});

// 完整 RESTful 路由
Route::resource('posts', 'PostController');
// 自动注册:
//   GET     /posts             → index
//   GET     /posts/create      → create
//   POST    /posts             → save
//   GET     /posts/{id:\d+}    → show
//   GET     /posts/{id:\d+}/edit → edit
//   PUT     /posts/{id:\d+}    → update
//   DELETE  /posts/{id:\d+}    → destroy

// 限定动作
Route::resource('posts', 'PostController', ['only' => ['index', 'show']]);
Route::resource('posts', 'PostController', ['except' => ['destroy']]);

// 路由级中间件
Route::get('/profile', 'UserController@profile')->middleware('auth');

// 组级中间件
Route::group(['middleware' => 'auth'], function() {
    Route::get('/dashboard', 'DashboardController@index');
});

// 注册自定义 404 处理器
Router::setNotFound(function($url) {
    return view('errors.404', ['url' => $url], true);
});

// 或指定控制器方法
Router::setNotFound('ErrorController@notFound');

// config/route.php — 路由文件
use zap\http\Router;

$router = new Router();

// 自动从 config/cache.php 读取驱动并尝试加载缓存
if ($router->loadRoutesFromCache(__FILE__)) {
    return $router;  // ✅ 缓存命中
}

// 注册路由(仅缓存未命中时执行)
Route::get('/users', 'UserController@index');
Route::get('/posts/{id:\d+}', 'PostController@show');
Route::resource('articles', 'ArticleController');
// ...

// 写入缓存(下次请求直接命中)
$router->cacheRoutes(__FILE__);
return $router;

return [
    // 切换缓存驱动只需改这里:'file' | 'redis' | 'memcached' | 'memcache'
    'default' => 'redis',

    'file' => [
        'path' => VAR_PATH . '/cache',
    ],

    'redis' => [
        'params' => ['127.0.0.1', 6379],
    ],

    'memcached' => [
        'driver'  => 'memcached',
        'servers' => [['host' => '127.0.0.1', 'port' => 11211]],
    ],

    'status' => 'enabled',
];

use zap\cache\RedisCache;
use zap\cache\MemcacheCache;

// Redis
Router::setCacheDriver(new RedisCache(['params' => ['10.0.0.5', 6380]]));

// Memcached
Router::setCacheDriver(new MemcacheCache([
    'driver'  => 'memcached',
    'servers' => [['host' => '192.168.1.10', 'port' => 11211]],
]));

// 文件缓存(指定路径)
Router::setCachePath('/data/cache/routes');

// 手动清除缓存(部署脚本中常用)
Router::clearRouteCache();

// 查看缓存状态
$info = Router::getCacheInfo();
// [
//     'driver'       => 'redis',
//     'cache_key'    => 'zap.routes.cache',
//     'cached'       => true,
//     'routes_count' => 42,
// ]

// ❌ 不可缓存
Route::get('/api', function() { return json(['ok' => true]); });

// ✅ 可缓存
Route::get('/api', 'ApiController@status');

namespace App\Controllers;

use zap\http\Controller;

class UserController extends Controller
{
    public function index()
    {
        // 渲染视图
        return view('user.index', ['users' => $users]);
    }

    public function show($id)
    {
        $user = UserModel::findOrFail($id);
        return json($user);
    }
}

use zap\http\RestController;

class PostController extends RestController
{
    public function index()   { /* GET    /posts */ }
    public function create()  { /* GET    /posts/create */ }
    public function save()    { /* POST   /posts */ }
    public function show($id) { /* GET    /posts/{id} */ }
    public function update($id) { /* PUT/PATCH /posts/{id} */ }
    public function destroy($id) { /* DELETE /posts/{id} */ }
}

use zap\http\Request;

// 获取输入(自动检测 GET → POST → JSON body 优先级)
$name  = Request::input('name');
$all   = Request::all();             // 所有输入(合并 GET+POST+JSON)
$only  = Request::only(['name', 'email']);
$except = Request::except(['_token', 'password']);

// 检测输入是否存在
if (Request::has('id')) { ... }

// 获取特定来源
$page = Request::query('page', 1);   // 仅 GET
$data = Request::post('title');      // 仅 POST

// JSON 请求体(Content-Type: application/json)
$json = Request::json();             // 返回 array|null
$raw  = Request::rawBody();          // 原始请求体字符串

$method   = Request::method();       // GET/POST/PUT/PATCH/DELETE 等
$url      = Request::url();          // http://domain.com/path
$fullUrl  = Request::fullUrl();      // http://domain.com/path?query=string
$uri      = Request::uri();          // /path
$path     = Request::path();         // /path(不含查询字符串)
$scheme   = Request::scheme();       // http / https
$host     = Request::host();         // domain.com
$port     = Request::port();         // 80 / 443

$ip       = Request::ip();           // 客户端 IP(遍历代理头,过滤非法值)
$ua       = Request::userAgent();    // User-Agent
$referer  = Request::referer();      // HTTP_REFERER
$lang     = Request::language();     // 首选语言(如 zh-CN)

// 方法检测
Request::isGet();        Request::isPost();      Request::isPut();
Request::isPatch();      Request::isDelete();    Request::isOptions();
Request::isHead();       Request::isAjax();      Request::isJson();

$file   = Request::file('avatar');               // 获取单个上传文件
if (Request::hasFile('avatar')) { ... }           // 检查是否有上传

$contentType = Request::headers('Content-Type');
$authToken   = Request::headers('Authorization');
$allHeaders  = Request::headers();                // 返回全部请求头

use zap\http\Response;

// JSON 响应(自动设置 Content-Type)
Response::ok(['data' => $result]);
Response::created(['id' => $newId]);

// 错误响应
Response::notFound('资源不存在');
Response::forbidden('无权限');
Response::unauthorized('请先登录');
Response::badRequest('参数错误');
Response::noContent();

// 自定义响应
$res = new Response();
$res->setContent('Hello World')
    ->setStatusCode(200)
    ->html()          // Content-Type: text/html
    ->header('X-Custom', 'value')
    ->send();

// 响应类型快捷
$res->json()          // Content-Type: application/json
    ->html()          // Content-Type: text/html
    ->text();         // Content-Type: text/plain

// 链式构建 + 手动发送
Response::ok($data)->send();  // 显式调用 send() 发 送
Response::notFound()->send();

// 重定向
Response::redirect('/login');
Response::redirect('https://example.com', 301);

// 文件下载
Response::download('/path/to/file.pdf');
Response::download('/path/to/file.pdf', '报告.pdf');

// 设置 Cookie
$res = new Response();
$res->cookie('name', 'value', time() + 3600, '/', '', true, true, 'Lax');

use zap\http\Session;

$session = Session::getInstance();
$session->start();                               // 自动启动(读写时自动调 用)

// 基本操作
$session->set('user', ['id' => 5, 'name' => 'Zap']);
$user = $session->get('user');
$name = $session->get('user.name', 'Guest');    // 点分路径访问嵌套值

// 存在性检查
if ($session->has('user')) { ... }               // 不依赖值真假

// 读取并删除 / 删除
$value = $session->pull('key');                 // 取一次就删
$session->forget('key');
$session->forget(['key1', 'key2']);             // 批量删除

// 数组操作
$session->push('items', 'new item');             // 向数组推入
$session->increment('views');                    // +1
$session->decrement('stock', 2);                 // -2

// 批量操作
$all  = $session->all();                         // 全部数据
$part = $session->only(['user', 'cart']);        // 仅获取指定键

// 安全
$session->regenerate();                          // 防会话固定
$session->regenerate(true);                      // 同时删除旧 session
$session->destroy();                             // 完全销毁

$session = Session::getInstance();

// 写入 Flash
$session->flash('success', '操作成功');
$session->flash('error', '保存失败,请重试');

// 读取并清除
$messages = $session->getFlash();               // 所有类型
$success  = $session->getFlash('success');       // 指定类型
$alerts   = $session->getFlash(['success', 'error']);

// 检查
if ($session->hasFlash()) { ... }

// 清除
$session->clearFlash('success');                 // 清除指定类型
$session->clearFlash();                          // 清除全部

use zap\validator\Validator;

// 方式一:静态工厂(默认从 $_GET/$_POST 读取数据)
$v = Validator::make()
    ->rule(' 'email' => '邮箱', 'age' => '年龄']);

if ($v->validate()) {
    $data = $v->getValidData();  // 验证通过的数据
} else {
    $errors = $v->firstOfAll();  // 每个字段的第一个错误
}

// 方式二:手动传入数据
$v = Validator::make($_POST)->rule('

$v = Validator::make($data)
    // 添加规则:rule(规则名, 字段, [参数])
    ->rule('
    // 自定义错误消息
    ->messages([
        'title.
        'title'   => '标题',
        'content' => '内容',
        'status'  => '状态',
    ])

    // 字段级遇错停检(title 的第一个规则失败后跳过其余 title 规则)
    ->bail('title')

    // 可空字段(值为空时跳过除 

$v = Validator::make($data)->rule('��验证,返回 bool
$v->fails();              // 是否失败
$v->passes();             // 是否通过
$v->getValidData();       // 通过验证的数据数组
$v->get('name');          // 获取单个通过验证的值
$v->errors();             // 所有错误 ['field' => ['rule' => 'message']]
$v->firstOfAll();         // 每字段第一个错误 ['field' => 'message']
$v->error('name');        // 指定字段的第一个错误(字符串)
$v->error('name', true);  // 指定字段的所有错误(数组)
$v->validated();          // 通过返回数据,失败抛出 RuntimeException
$v->reset();              // 重置验证器状态

// 点号分隔嵌套字段
$data = ['user' => ['name' => 'Zap', 'email' => '[email protected]']];
$v = Validator::make($data)
    ->rule('0],
    ['name' => '商品B', 'price' => 200],
]];
$v = Validator::make($data)
    ->rule('

// 闭包方式
$v = Validator::make($data)
    ->rule('callback', 'custom_field', function($name, $value) {
        return $value === 'expected_value';
    });

// 类方式(需实现 check($name, $value) 方法)
$v = Validator::make($data)
    ->rule('callback', 'custom_field', MyValidationRule::class);

// 1. 创建规则类
namespace App\Validators;

use zap\validator\AbstractRule;

class Mobile extends AbstractRule
{
    public function validate($name, $value)
    {
        return preg_match('/^1[3-9]\d{9}$/', $value) === 1;
    }

    public function translateMsgKey()
    {
        return 'rule_mobile';  // 语言文件中的 key
    }
}

// 2. 运行时注册命名空间
$v = Validator::make($data)
    ->addNamespace('App\\Validators')
    ->rule('mobile', 'phone');

use zap\i18n\Language;

// 设置当前语言
Language::locale('zh_CN');

// 获取翻译
echo __('messages.welcome', ['name' => 'Zap']);    // "欢迎 Zap"
echo trans('messages.welcome', ['name' => 'Zap']);  // 同上
echo __('messages.title');                            // 无参数
echo __('messages.greeting', 'Zap');                  // 旧式 {value} 替换

// 复数翻译
echo trans_choice('messages.apples', 1);    // "1 个苹果"
echo trans_choice('messages.apples', 5);    // "5 个苹果"


return [
    'welcome' => '欢迎 {name}',
    'title'   => '我的网站',
    'apples'  => [
        'one'   => '{count} 个苹果',
        'other' => '{count} 个苹果',
    ],
];

use zap\i18n\Language;

// 获取 / 设置当前语言
$locale = Language::locale();           // 'zh_CN'
Language::locale('en');                 // 切换到英文

// 设置回退语言(当前语言找不到翻译时自动尝试)
Language::fallback('en');

// 添加自定义语言文件路径
Language::addPath('/my-app/resources/languages');

// 获取所有可用语言
$locales = Language::availableLocales();  // ['zh_CN', 'en']

// 获取所有搜索路径
$paths = Language::getPaths();

// 数组参数:{key} → value
__('messages.greeting', ['name' => 'Zap', 'role' => '管理员']);
// "你好 Zap,你的角色是 管理员"

// 字符串参数(旧式,仅替换 {value})
__('messages.input', 'hello');
// 消息中 {value} 被替换为 hello

// messages.php
return [
    'comment' => [
        'one'   => '{count} 条评论',
        'other' => '{count} 条评论',
    ],
];

// 使用
echo trans_choice('messages.comment', 1);  // "1 条评论"
echo trans_choice('messages.comment', 8);  // "8 条评论"

// 运行时添加翻译(不依赖文件)
Language::with(['app.name' => '我的应用', 'app.version' => '1.0']);
// 或
Language::set('app.author', 'Zap Team');

// 获取
__('app.name');  // "我的应用"

// 检查是否存在
Language::has('app.name');  // true

use zap\net\Requests;

// GET 请求
$response = Requests::get('https://api.example.com/users', ['page' => 1]);
echo $response->body();       // 响应体
echo $response->status();     // 200

// POST 表单
$response = Requests::post('https://api.example.com/login', [
    'username' => 'admin',
    'password' => 'secret',
]);

// PUT / PATCH / DELETE
$response = Requests::put('https://api.example.com/users/1', ['name' => '新名称']);
$response = Requests::delete('https://api.example.com/users/1');

$r = Requests::get('https://api.example.com/data');

$r->body();              // string — 响应体
(string) $r;             // 同 body(),可当字符串用
$r->json();              // array — JSON 解析
$r->json(false);         // object — JSON 解析为对象
$r->status();            // int — HTTP 状态码 (200, 404, …)
$r->ok();                // bool — 2xx 检查
$r->clientError();       // bool — 4xx 检查
$r->serverError();       // bool — 5xx 检查
$r->contentType();       // string — Content-Type
$r->totalTime();         // float — 请求耗时(秒)
$r->effectiveUrl();      // string — 最终 URL(跟随重定向后)
$r->info();              // array — curl_getinfo 完整信息

// 发送 JSON
$r = Requests::json('POST', 'https://api.example.com/data', [
    'title' => 'Hello',
    'body'  => 'Content',
]);

// 快捷方法
$r = Requests::postJson('https://api.example.com/data', ['key' => 'value']);
$data = Requests::getJson('https://api.example.com/data', ['page' => 1]);

$r = Requests::post('https://api.example.com/data', $data, [
    'Authorization: Bearer token123',
    'X-Custom-Header: value',
    'Accept: application/json',
]);

$r = Requests::post('https://api.example.com/data', $data, $headers, [
    'timeout'          => 30,    // 超时(秒)
    'connect_timeout'  => 5,     // 连接超时(秒)
    'ssl_verify'       => false, // 跳过 SSL 验证(不推荐)
    'follow_redirects' => true,  // 跟随重定向
    'max_redirects'    => 5,     // 最大重定向次数
    'cookie'           => 'key=value',           // Cookie 字符串
    'cookie_file'      => '/tmp/cookies.txt',    // Cookie 文件路径
    'auth'             => ['username', 'pass'],  // HTTP Basic Auth
    'referer'          => 'https://example.com', // Referer
]);

$r = Requests::multipart('https://api.example.com/upload', [
    'title' => '我的图片',         // 普通字段
], [
    'image' => '/path/to/photo.jpg',  // 文件字段
]);

$responses = Requests::multi([
    ['method' => 'GET',  'url' => 'https://api.example.com/users'],
    ['method' => 'GET',  'url' => 'https://api.example.com/posts'],
    ['method' => 'POST', 'url' => 'https://api.example.com/log', 'params' => ['event' => 'visit']],
]);

foreach ($responses as $r) {
    echo $r->status() . ': ' . $r->body();
}

Requests::setUserAgent('MyApp/1.0');
Requests::setDefaultTimeout(60);
Requests::setDefaultConnectTimeout(15);
Requests::setCaCert('/custom/cacert.pem');

use zap\net\Curl;

$html = Curl::get('https://example.com/page', ['id' => 1]);
$result = Curl::post('https://api.example.com/login', ['user' => 'admin', 'pass' => '123']);

use zap\exception\CurlException;

try {
    $r = Requests::get('https://down.example.com/api');
} catch (CurlException $e) {
    echo '错误码: ' . $e->getCode();
    echo '错误信息: ' . $e->getMessage();
}

use zap\helpers\Pagination;

// 创建分页实例(总数,每页条数,当前页)
$p = new Pagination(200, 15, 1);

// 静态工厂
$p = Pagination::make(200, 15, 1);

$p->currentPage();     // 当前页码
$p->perPage();         // 每页条数
$p->total();           // 总记录数
$p->totalPages();      // 总页数
$p->hasPages();        // 是否有多页
$p->hasMorePages();    // 是否还有下一页
$p->isFirstPage();     // 是否第一页
$p->isLastPage();      // 是否最后一页
$p->firstItem();       // 当前页第一条记录序号
$p->lastItem();        // 当前页最后一条记录序号
$p->offset();          // 数据库查询 offset

// 设置基础路径
$p->withPath('/posts');

$p->url(3);              // /posts/3
$p->previousPageUrl();   // /posts/2
$p->nextPageUrl();       // /posts/4
$p->firstPageUrl();      // /posts/1
$p->lastPageUrl();       // /posts/14

// 数组格式(for API response)
$meta = $p->meta();
// [
//     'current_page'   => 1,
//     'per_page'       => 15,
//     'total'          => 200,
//     'total_pages'    => 14,
//     'from'           => 1,
//     'to'             => 15,
//     'has_more'       => true,
//     'next_page_url'  => '/posts/2',
//     'prev_page_url'  => '#',
//     'first_page_url' => '/posts/1',
//     'last_page_url'  => '/posts/14',
// ]

$json = $p->toJson();    // JSON 字符串

// Bootstrap 5 风格(默认)
echo $p->render();

// 自定义前后标签
echo $p->render('上一页', '下一页');

// Bootstrap 4 兼容
echo $p->renderBootstrap4();

// 简易模式(仅上一页/下一页)
echo $p->renderSimple();

// 记录数统计
echo $p->renderCount();  // 共 200 条,每页 15 条,当前第 1 / 14 页

$p = Pagination::make(200)
    ->withPath('/articles')
    ->setPerPage(20)
    ->setCurrentPage(3)
    ->onEachSide(2)              // 当前页左右各显示 2 个页码
    ->setClasses([               // 自定义 CSS 类名
        'nav'      => 'my-pagination',
        'active'   => 'is-active',
        'disabled' => 'is-disabled',
    ]);

echo $p->render();

$p->withRender(function($html, $pagination) {
    return '<div class="custom-pager">' . $html . '</div>';
});

use zap\facades\Url;

// 基础 URL
echo Url::base();        // http://localhost
echo Url::base('https://example.com');  // 设置基础 URL

// 首页
echo Url::home();        // http://localhost

// 完整 URL
echo Url::full();        // http://localhost/users?id=1

// 上一页(Referer)
echo Url::previous();    // 上一页 URL,无 Referer 时回退到首页

// 当前路径
echo Url::current();     // /users

// 定义路由
Route::get('/user/{id}', 'UserController@show')->name('profile');

// 生成 URL
echo Url::route('profile', ['id' => 1]);            // /user/1
echo Url::route('profile', ['id' => 2, 'tab' => 'posts']);  // /user/2?tab=posts

// 绝对 URL
echo Url::route('profile', ['id' => 1], true);      // http://localhost/user/1

echo Url::action('UserController@list');                    // /UserController@list
echo Url::action('UserController@show', [], ['id' => 5]);   // /UserController@show?id=5

// 替换占位符
echo Url::to('/user/{id}/edit', ['id' => 10]);       // /user/10/edit

// 未匹配参数追加为查询串
echo Url::to('/search', ['q' => 'php', 'page' => 2]); // /search?q=php&page=2

// 未匹配参数作为路径段
echo Url::to('/search', ['q' => 'php', 'page' => 2], false); // /search/php/2

Url::controller();      // 当前控制器名
Url::method();          // 当前方法名
Url::getRouteData();    // 完整路由数据数组
Url::getRouteData('profile');  // 指定命名路由的数据

// 布尔检查
if (Url::isActive('/admin*')) { /* 当前在后台 */ }

// 返回 class 名
<a class="<?= Url::isActive('/dashboard', 'nav-active') 

echo Url::secure('/admin/login');    // https://localhost/admin/login

// .env
DB_DRIVER=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=
DB_PREFIX=zap_
DB_CHARSET=utf8mb4

// config/database.php
return [
    'default' => 'mysql',
    'mysql' => [
        'driver'   => env('DB_DRIVER', 'mysql'),
        'host'     => env('DB_HOST', '127.0.0.1'),
        'port'     => env('DB_PORT', '3306'),
        'dbname'   => env('DB_DATABASE', 'test'),
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
        'charset'  => env('DB_CHARSET', 'utf8mb4'),
        'prefix'   => env('DB_PREFIX', 'zap_'),
    ],
    // PostgreSQL 同样支持
];

use zap\DB;

// SELECT
$users = DB::table('users')
    ->select('id', 'name', 'email')
    ->where('status', 1)
    ->orderBy('id', 'desc')
    ->limit(10)
    ->get();

// 单行查询
$user = DB::table('users')->where('id', 1)->first();
$user = DB::table('users')->find(1);
$name = DB::table('users')->where('id', 1)->value('name');  // 单个字段值

// 列提取
$ids = DB::table('users')->pluck('id');                    // [1, 2, 3, ...]
$map = DB::table('users')->pluck('name', 'id');            // [1=>'张三', 2=>'李四']

// INSERT
$id = DB::table('users')->insert(['name' => '张三', 'email' => '[email protected]']);

// INSERT IGNORE
DB::table('users')->insertOrIgnore(['email' => '[email protected]']);

// UPDATE
DB::table('users')->where('id', 1)->update(['name' => '张三(改名)']);

// increment / decrement
DB::table('posts')->where('id', 1)->increment('views');
DB::table('posts')->where('id', 1)->increment('views', 5, ['updated_by' => 1]);
DB::table('stock')->where('id', 1)->decrement('quantity', 1);

// DELETE
DB::table('users')->where('id', 1)->delete();

// INSERT
$id = DB::insert('users', ['name' => '张三', 'email' => '[email protected]']);

// UPDATE
$rows = DB::update('users', ['name' => '张三(改名)'], ['id' => 1]);

// DELETE
$rows = DB::delete('users', ['id' => 1]);
$rows = DB::delete('users', 'status=0 AND created_at<?', ['2023-01-01']);

// 批量插入
DB::batchInsert('users', [
    ['name' => 'A', 'email' => '[email protected]'],
    ['name' => 'B', 'email' => '[email protected]'],
]);

// Upsert / Replace
DB::upsert('users', ['id' => 1, 'name' => '新名字']);
DB::replace('users', ['id' => 1, 'name' => '替换']);

// 计数 & 键值对
$cnt = DB::count('users', 'status=?', [1]);
$map = DB::keyPair('settings', 'key, value');

// 基础条件
->where('status', 'published')              // status = 'published'
->where('age', '>', 18)                     // age > 18
->where('age', '>=', 18)                    // age >= 18
->where('name', 'LIKE', '%张%')              // name LIKE '%张%'

// OR 条件
->where('status', 1)->orWhere('role', 'admin')

// IN / NOT IN
->whereIn('category_id', [1, 2, 3])
->whereNotIn('category_id', [4, 5])

// BETWEEN
->whereBetween('created_at', ['2024-01-01', '2024-12-31'])
->whereNotBetween('price', [100, 500])

// NULL
->whereNull('deleted_at')
->whereNotNull('email_verified_at')
->orWhereNull('parent_id')

// 列与列比较
->whereColumn('updated_at', '>', 'created_at')
->orWhereColumn('a', 'b')

// 子查询 / 嵌套条件
->where(function ($query) {
    $query->where('status', 'active')
          ->orWhere('role', 'admin');
})

// 原始表达式(慎用,避免用户输入)
use zap\db\Expr;
->where('views', '>', new Expr('likes * 2'))

$count  = DB::table('users')->count();
$max    = DB::table('orders')->max('amount');
$min    = DB::table('orders')->min('amount');
$sum    = DB::table('orders')->sum('amount');
$avg    = DB::table('orders')->avg('amount');
$exists = DB::table('users')->where('email', '[email protected]')->exists();

DB::table('posts')
    ->join('users', 'u', 'posts.user_id = u.id')       // INNER JOIN
    ->leftJoin('categories', 'c', 'posts.category_id = c.id')
    ->rightJoin('tags', 't', 'posts.tag_id = t.id')
    ->select('posts.*', 'u.name as author')
    ->get();

DB::table('orders')
    ->select('user_id', DB::raw('SUM(amount) as total'))
    ->groupBy('user_id')
    ->having('total', '>', 100)
    ->get();

DB::table('users')->distinct()->pluck('role');

->orderBy('created_at', 'desc')
->orderBy('id', 'asc')
->orderByDesc('created_at')
->latest('updated_at')
->oldest('id')
->inRandomOrder()            // RAND()
->reorder('priority', 'desc') // 清除已有 ORDER BY 后重排

// 返回 Pagination 实例(含元数据和 HTML 渲染)
$pager = DB::table('posts')->paginate(15);
echo $pager->render();

// 手动 offset / limit
DB::table('posts')->limit(15)->offset(30)->get();

// 分块处理,避免内存溢出
DB::table('logs')->chunk(500, function ($rows, $page) {
    foreach ($rows as $row) {
        // 处理每一行...
    }
});

// 逐行处理
DB::table('users')->each(function ($user, $index) {
    echo $user->name;
});

$first  = DB::table('articles')->where('status', 'published');
$second = DB::table('archives')->where('status', 'published');
$results = $first->union($second)->get();
$results = $first->unionAll($second)->get();

// 查看生成的 SQL(参数已替换,仅供调试)
DB::table('users')->where('id', 1)->toSql();    // SELECT * FROM `zap_users` WHERE `id`=1

// dump 调试
DB::table('users')->where('id', 1)->dump();      // 输出 SQL 并继续
DB::table('users')->where('id', 1)->dd();         // 输出 SQL 并终止

// 获取绑定参数
$bindings = DB::table('users')->where('id', 1)->getBindings();

// SELECT
$users = DB::select('SELECT * FROM users WHERE status=?', [1]);

// 执行 UPDATE / DELETE / DDL,返回受影响行数
DB::exec('UPDATE users SET login_count=login_count+1 WHERE id=?', [1]);
DB::exec('DELETE FROM sessions WHERE expired_at < NOW()');

// 执行 INSERT 并返回新 ID
$id = DB::execInsert('INSERT INTO logs (msg) VALUES (?)', ['start']);

// PDO Statement
$stm = DB::statement('SELECT * FROM users WHERE id=?', [1]);

$db = DB::connection();

// 原始查询
$db->select('SELECT * FROM {users} WHERE status=?', [1]);
$db->get('SELECT * FROM {users} WHERE id=?', [1]);          // 单行
$db->getAll('SELECT * FROM {users}');                       // 全部
$db->value('SELECT name FROM {users} WHERE id=?', [1]);     // 单列值

// CRUD
$id = $db->insert('users', ['name' => '张三', 'email' => '[email protected]']);
$db->update('users', ['status' => 1], 'id=?', [10]);
$db->delete('users', 'status=0 AND created_at < ?', ['2023-01-01']);
$rows = $db->count('users', 'status=?', [1]);

// 批量插入
$db->batchInsert('users', [
    ['name' => 'A', 'email' => '[email protected]'],
    ['name' => 'B', 'email' => '[email protected]'],
]);

// Upsert(MySQL/PGSQL)
$db->upsert('users', ['id' => 1, 'name' => '新名字'], ['name' => '新名字']);

// REPLACE INTO
$db->replace('users', ['id' => 1, 'name' => '替换']);

// Key-value pair
$db->keyPair('settings', 'key, value');

// Schema 操作
$db->getTables();
$db->getTableStructure('users');
$db->getTableColumns('users');
$db->renameTable('old_users', 'new_users');
$db->dropTable('temp');
$db->truncateTable('logs');

namespace App\Models;

use zap\db\Model;

class UserModel extends Model
{
    protected $table = 'users';
    protected $primaryKey = 'id';

    // 自动管理时间戳
    protected $timestamps = true;

    // 批量赋值白名单
    protected $fillable = ['name', 'email', 'status'];

    // 批量赋值黑名单
    // protected $guarded = ['id', 'password'];

    // 类型转换
    protected $casts = [
        'is_active'  => 'boolean',
        'metadata'   => 'json',
        'login_count'=> 'int',
    ];
}

// 按主键查找
$user = UserModel::findById(1);          // 返回 null 或 实例
$user = UserModel::findOrFail(1);        // 未找到抛 RuntimeException
$user = UserModel::findOrNew(1);         // 未找到返回新实例(带 id)

// findBy 动态方法
$user  = UserModel::findByEmail('[email protected]');              // 返回数组
$user  = UserModel::findByIdAndStatus(1, 'active');      // 多条件

// 查询
$users = UserModel::all();               // 全部
$users = UserModel::first();             // 第一条
$count = UserModel::countBy(['status' => 1]);
$exists = UserModel::exists(['email' => '[email protected]']);
UserModel::destroy(5);                   // 按主键删除

$user = new UserModel();
$user->name  = '新用户';
$user->email = '[email protected]';
$user->save();

// 批量赋值(受 fillable/guarded 约束)
$user = new UserModel();
$user->fill(['name' => '张三', 'email' => '[email protected]']);
$user->save();

// 更新
$user = UserModel::findById(1);
$user->name = '改名';
$user->save();

// 删除
$user = UserModel::findById(1);
$user->delete();

// 刷新
$user->refresh();       // 用数据库数据覆盖当前实例
$fresh = $user->fresh(); // 返回新的实例

class PostModel extends Model
{
    protected $timestamps = true;
    // 自动维护 created_at 和 updated_at
    // 列名可通过 const CREATED_AT / UPDATED_AT 自定义
}

$arr  = $user->toArray();      // ['id' => 1, 'name' => '张三', ...]
$json = $user->toJson();       // JSON 字符串(Unicode 不转义)
$json = json_encode($user);    // 同样输出 JSON
echo $user;                    // __toString → toJson()

// 闭包事务(自动提交/回滚)
DB::transaction(function () {
    UserModel::findById(1)->delete();
    LogModel::findById(1)->delete();
});

// 手动事务
DB::beginTransaction();
try {
    UserModel::findById(1)->delete();
    LogModel::findById(1)->delete();
    DB::commit();
} catch (\Throwable $e) {
    DB::rollBack();
    throw $e;
}

DB::enableQueryLog();

DB::table('users')->where('id', 1)->get();
DB::table('posts')->limit(10)->get();

$log = DB::getQueryLog();
// [['sql' => '...', 'params' => [...], 'time' => 1234567890.1234], ...]

DB::flushQueryLog();
DB::disableQueryLog();

DB::connection('mysql')->table('users')->get();
DB::connection('pgsql')->table('logs')->get();

// 连接信息
DB::connectionInfo();  // [driver, server, version, ...]

use zap\view\View;

// 控制器中渲染
return view('users.profile', ['user' => $user]);       // 直接输出
$html = view('emails.welcome', $data, true);            // 返回字符串

// 链式调用
$html = View::make('users.profile')
    ->with('user', $user)
    ->with('role', 'admin')
    ->withLayout('layouts.main')
    ->fetch();

// 直接输出
View::make('home')->with('title', '首页')->show();

// 检查模板是否存在
if (View::exists('admin.dashboard')) { ... }

// 第一个存在的模板(备选逻辑)
$tpl = View::first('custom.home', 'default.home');      // 优先 custom

// app/views/layouts/main.php
<!DOCTYPE html>
<html>
<head>
    <title><?= $this->e($title) 

// 包含子模板(内容自动加入页面)
$this->this->partial('partials.nav', ['active' => 'home']);

// 控制器中独立渲染局部
$sidebar = View::make('partials.sidebar')->fetch();

// HTML 转义(XSS 防护)
<?= $this->e($userInput) 

// 应用启动时注册,所有视图可见
View::share('appName', 'My App');
View::share('currentUser', $user);

// 模板中直接使用
<?= $currentUser['name'] 

// 默认搜索路径:app/views/
// 自动按顺序查找:$path/{name}.php → $path/{name}.html → $path/{name}.twig

// 添加自定义路径
View::addPath('/path/to/extra/views');          // 高优先级(插到头部)
View::addPath('/path/to/vendor/views', true);   // 低优先级(追加末尾)

// 主题支持
// config.php: ['theme' => 'default']
// → 自动追加 themes/default/ 到搜索路径头部

// 注册自定义扩展名
View::registerExtension('phtml');

$html = View::renderString('<h1><?= $title 

// app/views/emails/welcome.twig
<html>
<body>
    <h1>Hello {{ name }}!</h1>
</body>
</html>

// 配置
// config/twig.php
return [
    'template_paths' => [
        'emails' => base_path('app/views/emails'),
    ],
    'options' => [
        'cache' => base_path('storage/cache/twig'),
        'debug' => config('config.debug'),
    ],
    'extensions' => [
        \App\Twig\MyExtension::class,
    ],
];

// 读取配置(支持点号分隔)
$debug = config('config.debug', false);
$host  = config('database.mysql.host', '127.0.0.1');

// 动态设置
config(['app.name' => 'Zap App']);

// 清除配置缓存
\zap\Config::clearCache();

use zap\Log;

// 级别:DEBUG / INFO / NOTICE / WARNING / ERROR / CRITICAL / ALERT / EMERGENCY
Log::info('用户登录', ['user_id' => 123]);
Log::warning('磁盘空间不足');
Log::error('支付失败', ['order_id' => 456]);
Log::debug('SQL执行时间', ['sql' => $sql, 'time' => 0.05]);

// 配置(config/log.php)
return [
    'default' => 'app',
    'level'   => 200,   // INFO 级别
    'path'    => VAR_PATH . '/logs/app.log',
    'app' => [
        'handler' => \Monolog\Handler\StreamHandler::class,
        'params'  => [VAR_PATH . '/logs/app.log', 200],
    ],
];

use zap\facades\Cache;

// PSR-16 风格接口
Cache::set('key', 'value', 3600);     // 设置,TTL 3600 秒
$value = Cache::get('key', '默认值');  // 获取
Cache::has('key');                     // 是否存在
Cache::delete('key');                  // 删除
Cache::clear();                        // 清空

// 批量操作
Cache::setMultiple(['a' => 1, 'b' => 2], 3600);
$items = Cache::getMultiple(['a', 'b']);

// 配置(config/cache.php)
return [
    'default' => 'file',          // file | redis
    'stores' => [
        'file' => [
            'path' => VAR_PATH . '/cache',
        ],
        'redis' => [
            'host'     => '127.0.0.1',
            'port'     => 6379,
            'password' => null,
            'database' => 0,
            'prefix'   => 'zap:',
        ],
    ],
];

use zap\http\Session;

// 读取
Session::get('user_id');
Session::all();

// 写入
Session::set('user_id', 123);

// 删除
Session::delete('user_id');
Session::destroy();

// Flash 消息(一次性)
session()->setFlash('操作成功', 'success');    // 设置
session()->getFlash('message');                // 读取

use zap\component\Hooks;

// 添加过滤器
Hooks::add_filter('content_format', function($content) {
    return nl2br($content);
});

// 添加动作
Hooks::add_action('user_registered', function($user) {
    Log::info('新用户注册', ['user' => $user]);
});

// 应用过滤器
$content = Hooks::apply_filters('content_format', $rawContent);

// 触发动作
Hooks::do_action('user_registered', $user);

namespace App\Middlewares;

use zap\http\Middleware;

class AuthMiddleware implements Middleware
{
    public function handle($request, \Closure $next)
    {
        if (!isset($_SESSION['user'])) {
            return redirect('/login');
        }
        return $next($request);
    }
}

// 注册(config/route.php 或启动时)
Route::middleware('auth', AuthMiddleware::class);

// 使用
Route::group('/admin', function() {
    // ...
})->middleware('auth');

// 或给单条路由
Route::get('/dashboard', 'DashboardController@index')->middleware('auth');

#!/usr/bin/env php


define('ROOT_PATH', dirname(__DIR__));
define('APP_PATH', ROOT_PATH . '/app');
define('CONFIG_PATH', ROOT_PATH . '/config');
define('VAR_PATH', ROOT_PATH . '/var');
define('VENDOR_PATH', ROOT_PATH . '/vendor');


namespace App\Commands;

use zap\console\Command;
use zap\console\Input;
use zap\console\Output;

class HelloCommand extends Command
{
    public function configure(): void
    {
        $this->setName('hello')
             ->setDescription('输出欢迎信息')
             ->addArgument('name', '名称', true)
             ->addArgument('greeting', '问候语', false, 'Hello')
             ->addOption('uppercase', 'u', '转为大写输出');
    }

    public function execute(Input $input, Output $output): int
    {
        $name = $input->getArgument(0);
        $greeting = $input->getArgument(1) ?? 'Hello';

        $message = "{$greeting}, {$name}!";

        if ($input->getOption('uppercase')) {
            $message = strtoupper($message);
        }

        $output->success($message);
        return self::SUCCESS;
    }
}

public function configure(): void
{
    $this
        // 命令名
        ->setName('hello')
        // 描述(在列表命令中显示)
        ->setDescription('输出欢迎信息')
        // 位置参数:名称、描述、是否必填、默认值
        ->addArgument('name', '名称', true)
        ->addArgument('title', '标题', false, 'Mr.')
        // 命名选项:名称、短选项、描述、默认值
        ->addOption('uppercase', 'u', '转为大写')
        ->addOption('times', 't', '重复次数', 1);
}

class MyCommand extends Command
{
    public function execute(Input $input, Output $output): int
    {
        // 位置参数(0-based 索引)
        $firstName = $input->getArgument(0);
        $secondArg = $input->getArgument(1, '默认值');
        $allArgs   = $input->getArguments();  // 所有位置参数数组

        // 命名选项
        $uppercase = $input->getOption('uppercase');
        $times     = $input->getOption('times', 1);
        $allOpts   = $input->getOptions();

        // 检查是否存在
        $input->hasOption('verbose');
        $input->hasParam('v');

        // 兼容旧接口(1-based)
        $first = $input->getParam(1);

        return self::SUCCESS;
    }
}
bash
composer 

project/
├── app/
│   ├── controllers/       # 控制器
│   ├── models/            # 模型
│   ├── middlewares/       # 中间件
│   └── views/             # 视图模板
├── config/                # 配置文件
│   ├── config.php         # 应用配置
│   ├── database.php       # 数据库配置
│   ├── log.php            # 日志配置
│   ├── cache.php          # 缓存配置
│   └── route.php          # 路由配置
├── public/                # 入口目录
│   └── index.php          # 入口文件
├── var/
│   └── cache/             # 缓存文件
├── vendor/
└── composer.json
php
public function execute(Input $input, Output $output): int
{
    // 基本输出
    $output->writeln('普通文本');
    $output->write('不换行...');

    // 带颜色标签的输出
    $output->writeln('<info>信息</info>');
    $output->writeln('<error>错误</error>');
    $output->writeln('<warning>警告</warning>');
    $output->writeln('<success>成功</success>');
    $output->writeln('<debug>调试信息</debug>');

    // 快捷彩色方法
    $output->info('信息消息');
    $output->error('错误消息');     // 输出到 stderr
    $output->warning('警告消息');
    $output->success('成功消息');
    $output->debug('调试消息');

    // 格式化输出
    $output->printf('共处理 %d 条记录', $count);

    // 按详细级别输出
    $output->writelnV('详细信息(-v)');    // 需 -v
    $output->writelnVV('更详细(-vv)');      // 需 -vv
    $output->writelnVVV('调试详情(-vvv)');  // 需 -vvv

    // 检测颜色支持
    if ($output->hasColorSupport()) {
        $output->writeln('<red>红色文字</red>');
    }

    return self::SUCCESS;
}
php
$console->setDefaultCommand(MyDefaultCommand::class);
php
// 路径
base_path('app/views');        // 项目根路径
config_path('database.php');   // 配置路径
app_path('models/User.php');   // 应用路径
storage_path('logs/app.log');  // 存储路径

// 应用 & 依赖
app();                          // 获取 App 实例
app('router');                  // 获取容器中的服务

// 配置
config('database.default');
config(['app.debug' => true]);

// 路由
route('profile');               // 命名路由 URL
url('/users');                  // 完整 URL

// 响应
redirect('/login');             // 重定向
view('home', ['name' => 'Zap']);// 视图
json(['code' => 0]);            // JSON 响应

// 其他
dd($data);                      // dump & die
env('APP_ENV', 'production');   // 环境变量
value(function() { ... });      // 执行回调

// 国际化(需先加载语言文件)
__('welcome');                                 // 简单翻译
__('user.greeting', ['name' => 'Zap']);        // 带参数翻译
trans_choice('apples', 5);                     // 复数翻译

// 字符串
snake_case('HelloWorld');       // hello_world
camel_case('hello_world');      // helloWorld
studly_case('hello_world');     // HelloWorld
str_contains('hello world', 'world');  // true
str_starts_with('hello', 'he');        // true
str_ends_with('hello', 'lo');          // true
str_limit('very long text', 10);       // very lon...
php
// 缩放:传入宽或高之一即可等比缩放
$img->resize(800);               // 固定宽度,高度等比
$img->resize(null, 600);         // 固定高度,宽度等比
$img->resize(800, 600);          // 同时指定宽高

// 等比缩放(不留白)
$img->fit(400, 300);             // 按短边适配,决不超出目标范围
$img->fit(400, 300, true);       // 第三个参数 true 允许放大

// 居中裁剪(fill/cover)
$img->fill(400, 300);            // 缩放后居中裁剪
$img->thumb(400, 300, 'top');    // 锚点裁剪:center/top/bottom/left/right/top-left 等

// 正方形裁剪
$img->square(300);               // 按短边出 300x300
$img->square(300, 'top-left');   // 指定锚点

// 矩形裁剪
$img->crop(100, 100, 300, 300);

// 画布扩展
$img->resizeCanvas(800, 600, 'center', 'FFFFFF');
php
$img->rotate(90);                // 顺时针旋转 90°
$img->rotate(45, 'FF0000');      // 旋转并指定背景色

$img->flip();                    // 水平翻转
$img->flop();                    // 垂直翻转
$img->flipBoth();                // 180° 翻转

// 根据 EXIF Orientation 自动修正(手机竖拍纠正)
$img->orient();
php
// 设置输出格式(自动转换)
$img->setOutputFormat('webp');     // 转 WebP
$img->setOutputFormat('jpeg');     // 转 JPEG
$img->setOutputFormat('png');      // 转 PNG
$img->setOutputFormat('gif');      // 转 GIF

// 控制质量
$img->setQuality(85);              // 0-100(默认 90)
php
// 保存到文件
$img->save('/output/result.jpg');
$img->save('/output/result.jpg', 95);      // 指定质量

// 保存到目录(使用原始文件名)
$img->savePath('/output/');

// 保存到路径(自动创建目录)
$img->saveFile('/output/images/avatar.png');

// 获取二进制数据
$data  = $img->getImageData();              // 原格式
$data  = $img->getImageData('webp', 80);    // 指定格式+质量

// Base64 Data URI
$uri   = $img->toBase64();
$uri   = $img->toBase64('png');

// 浏览器输出
$img->toBrowser();                           // 直接输出
$img->download('photo.jpg');                 // 强制下载
$img->download('photo.jpg', null, 90);       // 指定质量
php
// 复制(独立的 GD 资源,互不影响)
$copy = $img->copy();
$copy->resize(200)->save('/output/thumb.jpg');

// 显式销毁(释放内存)
$img->destroy();

// 析构时自动释放,无需手动调用
php
// 图片信息
$info = $img->info();      // [file, dirname, basename, mime, width, height, bits, ...]
$info = $img->toArray();   // 同 info()

// EXIF(仅 JPEG)
$exif = $img->getExif();

// 分辨率(DPI)
$res = $img->getResolution();

// Getter 方法
$img->getWidth();
$img->getHeight();
$img->getMimeType();
$img->getExtName();
$img->getFile();
$img->getImage();          // GD 资源
$img->getBits();
php
use zap\image\Image;

$avatar = new Image('/tmp/upload.jpg');

$avatar
    ->orient()                                   // 修正 EXIF 方向
    ->square(400, 'center')                      // 裁剪为正方形
    ->resize(200, 200)                           // 缩放到目标尺寸
    ->sharpen()                                  // 轻微锐化
    ->setOutputFormat('webp')                    // 转为 WebP
    ->setQuality(85)
    ->saveFile('/public/avatars/user_123.webp');

// 同时生成缩略图
$avatar->copy()
    ->resize(64, 64)
    ->saveFile('/public/avatars/user_123_thumb.webp');
php
use zap\fileupload\FileUpload;

$uploader = new FileUpload();

// 设置限制
$uploader->setAllowedTypes(['jpg', 'png', 'gif', 'pdf']);
$uploader->setMaxSize(5 * 1024 * 1024); // 5MB

try {
    // 单文件上传
    $file = $uploader->upload('avatar', '/path/to/uploads');
    echo $file->getSavedPath();              // 最终保存路径
    echo $file->getClientOriginalName();     // 原始文件名
    echo $file->getSize();                   // 文件大小(字节)
    echo $file->getClientExtension();        // jpg
} catch (\zap\fileupload\FileUploadException $e) {
    echo '上传失败: ' . $e->getMessage();
    echo '字段名: ' . $e->getField();
}
php
// 前端 input: <input type="file" name="photos[]" multiple>

$uploader = new FileUpload();
$uploader->setAllowedTypes(['jpg', 'png']);
$uploader->setMaxSize(10 * 1024 * 1024); // 10MB

$files = $uploader->uploadMultiple('photos', '/path/to/uploads');

foreach ($files as $file) {
    echo $file->getSavedPath() . "\n";
}

// 获取所有保存的文件
$allFiles = $uploader->getFiles();
php
// 方式一:指定基础文件名
$file = $uploader->upload('avatar', '/uploads', 'user_avatar');

// 方式二:禁用自动重命名(使用原始文件名)
$uploader->setAutoRename(false);
$file = $uploader->upload('avatar', '/uploads');

// 方式三:自定义命名回调
$uploader->setNameCallback(function ($file, $suggestedName) {
    return 'prefix_' . date('Ymd') . '_' . uniqid();
});
$file = $uploader->upload('avatar', '/uploads');
php
// 通过 MIME 类型限制(更精确)
$uploader->setAllowedMimes([
    'image/jpeg',
    'image/png',
    'image/gif',
    'application/pdf',
]);

// 可与扩展名限制同时使用
$uploader->setAllowedTypes(['jpg', 'png', 'gif', 'pdf']);
$uploader->setAllowedMimes(['image/jpeg', 'image/png', 'image/gif', 'application/pdf']);
php
$file = $uploader->upload('file', '/uploads');

$file->getClientOriginalName();  // string  原始文件名
$file->getClientExtension();     // string  扩展名(小写,不含点)
$file->getSize();                 // int     文件大小(字节)
$file->getClientMimeType();      // string  浏览器提供的 MIME 类型
$file->getMimeType();            // string  服务器检测的真实 MIME 类型
$file->getTmpName();             // string  临时文件路径
$file->getError();               // int     上传错误码
$file->isValid();                // bool    上传是否成功
$file->getErrorMessage();        // string  可读的错误消息
$file->getSavedPath();           // ?string 移动后的保存路径
php
$uploader = new FileUpload();

$uploader
    ->setAllowedTypes(['jpg', 'png', 'gif'])
    ->setMaxSize(5 * 1024 * 1024)
    ->setAutoRename(true);

$file = $uploader->upload('image', '/uploads');
php
use zap\crypto\OpenSSL;

$encrypted = OpenSSL::encrypt('敏感数据', 'your-secret-key');
$decrypted = OpenSSL::decrypt($encrypted, 'your-secret-key');
php
// config/config.php
return [
    'debug' => true,   // 开发环境:显示详细错误
    // 'debug' => false, // 生产环境:不显示敏感信息
];
nginx
location / {
    try_files $uri $uri/ /index.php?$query_string;
}