StartMVC开发手册

可以快速上手的开发文档

手册目录

自定义函数

功能概述

自定义函数分两级:全局函数放在 app/function.php,所有请求都能用;模块函数放在 app/{模块}/function.php,只有进入该模块时才会加载。两者都不需要手动引入。

  • 框架只认这两个固定文件,不扫描目录,加载顺序确定。
  • 全局函数在框架引导阶段加载,CLI 与 HTTP 行为一致。

全局函数:app/function.php

文件不存在也不会报错,需要时新建即可。适合放无状态、跨模块通用的小函数。

// app/function.php
if (!function_exists('format_price')) {
 function format_price($cents)
 {
 return '¥' . number_format($cents / 100, 2);
 }
}

框架在注册完自动加载之后才载入这个文件,所以函数体内可以直接使用框架类与助手函数:

if (!function_exists('site_name')) {
 function site_name()
 {
 return config('site.name', 'StartMVC');
 }
}

模块函数:app/{模块}/function.php

只有进入该模块时才加载,适合只在某个模块里用的函数(后台专用、前台专用)。

// app/admin/function.php
if (!function_exists('admin_can')) {
 function admin_can($action)
 {
 return \app\admin\service\Auth::check($action);
 }
}

访问 /admin/... 时该文件被加载,访问 /home/... 时不会加载——既省掉无谓的解析,也避免两个模块的同名函数互相污染。

  • 注意:路由闭包不经过模块解析,闭包里要用模块函数时请自行 require_once。
  • 建议:模块函数统一加模块前缀(admin_、home_)。全局函数没有命名空间,两个模块定义同名函数会直接致命错误。

需要拆分多个文件时

框架不扫描目录,所以拆分的入口仍然是 app/function.php——在里面 require_once 即可,顺序由你控制:

// app/function.php
require_once __DIR__ . '/common/functions/string.php';
require_once __DIR__ . '/common/functions/format.php';

拆分出来的文件建议放在 app/common/functions/,不要新建 app/function/ 目录——function.php 与 function/ 并排会让人分不清哪个是入口。

命名与冲突

全局函数没有命名空间,重复定义是致命错误,无法用 try/catch 捕获。因此约定:

  • 每个函数都用 if (!function_exists('xxx')) 包裹,框架自带的助手函数也是这个写法;
  • 函数名不要与 PHP 内置函数、框架助手函数重名;
  • 一组函数超过 5 个、或者需要共享状态时,说明它应该是一个类——放到 app/common/,按 PSR-4 自动加载,例如 app\common\Str::slug()。

加载顺序

顺序文件加载时机
1startmvc/function.php框架引导,早于 Composer 自动加载
2extend/*/function.php框架引导,扩展自带的函数(按目录名升序)
3app/function.php框架引导,自动加载注册之后
4app/{模块}/function.php进入该模块时(请求分发阶段)

前三步在 CLI 与 HTTP 下都会执行,第四步只在真正分发到某个模块时执行。