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;
}