
企业应用后端【免费下载链接】dolibarrDolibarr ERP CRM is a modern software package to manage your company or foundations activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). its an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers.项目地址https://gitcode.com/gh_mirrors/do/dolibarr点击查看免费下载本文围绕 Dolibarr 仓库 dev/tools/phan/README.md 展开系统讲解 Dolibarr 如何集成 PHP 静态分析工具 Phan从run-phan.sh的安装与三种运行模式默认检查、full 扩展检查、baseline 基线更新到config.php/config_extended.php两份核心配置的逐项拆解再到 Windows 批处理、Docker、pre-commit 钩子与 GitHub Actions 的多种落地方式。读完本文你将能在本地复现 Dolibarr 官方同款 Phan 检查流程并理解其基线抑制、插件化校验、全局变量类型映射等工程化细节。一、Phan 在 Dolibarr 中的角色Phan 是一款基于 AST抽象语法树的 PHP 静态分析器由 Phan 官方 Wiki 提供安装与入门指引。Dolibarr 将其定位为静态代码检查Static Code Checks工具相关脚本、配置、基线和插件统一收敛在仓库的 dev/tools/phan 目录下与 phpstan见仓库根目录 phpstan.neon.dist形成双引擎静态检查体系。该目录包含以下核心文件文件用途run-phan.shLinux/macOS 主入口脚本自动安装并运行 PhanPHAN.BATWindows 批处理入口支持 extended / fix 模式runPhanDocker.shDocker 容器方式运行 Phanconfig.php默认检查配置与.github/workflows/phan.yml共用config_extended.php扩展检查配置启用更多规则config_fixer.php自动修复automatic-fix专用配置baseline.txt默认检查的基线记录当前已豁免的问题baseline_extended.txt扩展检查的基线目前尚未纳入 gitplugins/自定义插件与自动修复器fixerstubs/为缺失 PHP 扩展提供的类型桩文件allow_phan_in_precommit.shpre-commit 钩子包装脚本二、安装与运行run-phan.sh 全解析官方 README 指出run-phan.sh可以完成 Phan 的安装与运行安装说明与运行说明都内嵌在脚本头部注释中直接运行即可。脚本位于 dev/tools/phan/run-phan.sh其自动安装逻辑如下# 若 Phan 可执行文件不存在则通过 composer 安装 if [ ! -x ${PHAN} ] ; then if [ ! -r ${COMPOSER_CMD} ] ; then echo composer is not available. Provide the path by setting COMPOSER_CMD/path/to/composer exit 1 fi # 首次vendor 目录不存在则 composer install已存在则 update [[ ! -e ${COMPOSER_VENDOR_DIR} ]] ${PHP} ${COMPOSER_CMD} install [[ -e ${COMPOSER_VENDOR_DIR} ]] ${PHP} ${COMPOSER_CMD} update ${PHP} ${COMPOSER_CMD} require --dev phan/phan fi2.1 环境变量脚本头部注释明确了两类可调环境变量COMPOSER_CMDcomposer 可执行路径用于自动安装 Phan。默认值为${MYDIR}/../composer.phar即dev/tools/composer.phar。COMPOSER_VENDOR_DIRcomposer vendor 目录默认指向${MYDIR}/vendorPhan 二进制位于${COMPOSER_VENDOR_DIR}/bin/phan。可在命令行临时注入也可先 export 再运行# 方式一命令行注入 COMPOSER_CMDphp ~/composer.phar COMPOSER_VENDOR_DIR~/vendor ./run-phan.sh # 方式二导出环境变量 export COMPOSER_CMD~/composer.phar export COMPOSER_VENDOR_DIR~/vendor ./run-phan.sh脚本还会额外识别PHAN_CONFIG默认config.php与PHP默认php${MINPHPVERSION}即php7.2一类的版本化命令两个变量并兼容 Cygwin通过cygpath -w转换路径。若vendor/bin/phan不存在但系统 PATH 中已有phan脚本会直接回退使用全局phan。2.2 实际执行命令脚本最终在仓库根目录PROJECT_DIR即dev/tools/phan的上三级执行${PHAN} --analyze-twice --config-file ${PHAN_CONFIG} --memory-limit 4096M ${BASELINE_OPT[]} $即二次分析--analyze-twice、显式指定配置文件、4 GB 内存上限外加基线装载选项见下文。其中--analyze-twice是 Dolibarr 的标准做法——第一遍收集全量类型信息后第二遍再出报告可显著降低跨文件类型推断的误报。三、三种运行模式与实战命令README 明确定义了run-phan.sh的三种参数形态参数行为无参数运行最小检查集默认检查full运行一整套扩展检查集1重新生成基线baseline官方示例README 原文# 默认检查 run-phan.sh # 为默认检查更新基线 run-phan.sh 1 # 扩展检查 run-phan.sh full # 为扩展检查更新基线 run-phan.sh full 1脚本中的解析逻辑与之一一对应run-phan.sh# 参数为 full切换为扩展配置与扩展基线 if [ $1 full ] ; then shift PHAN_CONFIG${MYDIR}/config_extended.php BASELINE${MYDIR}/baseline_extended.txt fi # 参数为 1保存基线否则若基线文件存在则加载基线 if [ $1 1 ] ; then shift BASELINE_OPT(--save-baseline ${BASELINE}) elif [ -r ${BASELINE} ] ; then BASELINE_OPT(--load-baseline ${BASELINE}) fi注意参数顺序可以组合run-phan.sh full 1中full先被消费切换配置随后1触发--save-baseline因此扩展检查的基线写入baseline_extended.txt而纯默认检查的基线保存在 baseline.txt当前约 199 行由 Phan 自动生成文件头部注释记录了PhanUndeclaredProperty : 290等历史问题统计。四、Baseline 基线机制存量问题 vs 新增问题README 专门强调基线文件的设计意图baseline.txt定义的是当前从最终报告中排除的问题集合。原则上是存量容忍、增量零容忍——原则上不应向基线文件追加任何新的豁免项正确做法是修复问题或为代码补充 [Phan annotations]如phan-var-force TYPE $varname、suppress PhanPluginName等注释提供更多类型信息以精确豁免特定场景。从 baseline.txt 的头部可以看出它是 Phan 自动生成的 PHP 数组文件内部按问题类型统计出现次数// # Issue statistics:配合--load-baseline/--save-baseline使用。这一机制让 Dolibarr 这样的大体量历史代码库可以在不解决全部存量告警的前提下通过 CI 持续卡住新增问题实现渐进式质量收敛。五、配置体系config.php 与 config_extended.phpREADME 说明了两份配置的定位config.php 为默认配置config_extended.php 启用更多检查。二者不是并列的独立配置而是继承关系——config_extended.php先include config.php再覆盖plugins与suppress_issue_types两个数组从而在默认基础上加严规则。config.php的注释明确其被.github/workflows/phan.yml使用主要配置项如下。5.1 分析范围target_php_version 8.2, // 分析目标 PHP 版本可选 5.6/7.0/7.1/7.2/7.4/null directory_list [ htdocs, // 主代码目录 scripts, // 命令行脚本 PHAN_DIR . /stubs, // 扩展桩文件目录 ], exclude_analysis_directory_list [ dev/tools/, htdocs/includes/, // 第三方依赖只解析类型、不分析 htdocs/install/doctemplates/, htdocs/core/class/lessc.class.php, // 外部库 htdocs/admin/tools/ui/, PHAN_DIR . /stubs/, ],这里体现的是 Phan 的标准三区模型directory_list中列出的目录会被解析类/方法信息再通过exclude_analysis_directory_list把第三方代码如htdocs/includes/从分析中排除但保留其类型信息——这正是 run-phan.sh 得以在无 vendor 完整源码的情况下仍能跨依赖推断类型的原因。exclude_file_regex则按正则剔除明确不参与分析的文件dev/tools/*、htdocs/custom/*自定义模块、htdocs/.*/canvas/.*/tpl/.*.tpl.php模板文件、htdocs/includes/{nusoap,restler,stripe}/*改为以桩文件分析、htdocs/conf/conf.php等。5.2 全局变量类型映射globals_type_mapDolibarr 大量使用$db、$conf、$user、$langs、$form等全局变量而 Phan 默认无法推断这些运行时注入的全局变量。config.php通过globals_type_map为它们逐一声明类型例如globals_type_map [ db \DoliDB, dbsession \DoliDB, conf \Conf, user \User, langs \Translate, form \Form, formcompany \FormCompany, hookmanager \HookManager, mysoc \Societe, objsoc \Societe, extrafields \ExtraFields, menumanager \MenuManager, // ... website string, // 因 Phan 会自行推断 Website 类型而显式覆盖 ],映射中还包含带形状shape的复杂类型如_Avery_Labels被描述为arraystring,array{name:string,paper-size:string|array{0:float,1:float},...}说明 Dolibarr 对打印机标签这种复合数据结构也做了精确建模。被注释掉的object \CommonObject则提示该键因与代码中大量的$object赋值冲突而放弃启用。5.3 参数正则校验插件ParamMatchRegexPlugin这是 Dolibarr 自研并内置的插件实现见 plugins/ParamMatchRegexPlugin.php用于对函数实参做正则约束校验直接呼应 Dolibarr 的 API 使用规范ParamMatchRegexPlugin [ // GETPOST 的第二参必须是文档化的清洗类型 /^GETPOST$/ [1, $sanitizeRegex, GetPostUnknownSanitizeType], // isModEnabled 的模块名必须在合法模块表内 /^isModEnabled$/ [0, $moduleNameRegex, UnknownModuleName], /^isModEnable[d]$/ [0, $deprecatedModuleNameRegex, DeprecatedModuleName], /^sanitizeVal$/ [1, $sanitizeRegex, UnknownSanitizeType], /^checkVal$/ [1, $sanitizeRegex, UnknownCheckValSanitizeType], // ExtraFields::addExtraField 的字段类型必须合法 /^\\\\ExtraFields::addExtraField$/ [2, $extraFieldTypeRegex, UnknownExtrafieldTypeBack], // 时间函数时区参数约束 /^dol_now$/ [0, {^(?:auto|gmt|tz(?:server|ref|user(?:rel)?))$}, InvalidDolNowArgument], /^dol_mktime$/ [6, {^(?:|0|1|auto|gmt|tz(?:server|ref|user(?:rel)?|,[a-zA-Z-/]))$}, InvalidDolMktimeArgument], /^price2num$/ [1, {^(?:|M[UTS]|C[UTR]|\d)$}, InvalidPrice2NumRounding], ],其依托的三张规则表定义在配置头部$sanitizeRegexGETPOST 清洗类型白名单包括文档化的none/password/array/int/intcomma/alpha/alphawithlgt/alphanohtml/MS/aZ/aZ09/aZ09arobase/aZ09comma/email/san_alpha/restricthtml/nohtml/custom以及未文档化的restricthtmlallowclass/restricthtmlallowunvalid/restricthtmlnolink/restricthtmlallowlinkscript/url$DEPRECATED_MODULE_MAPPING废弃模块名到新模块名的映射如actioncomm→agenda、facture→invoice、propale→propal配合deprecatedModuleNameRegex让调用旧模块名直接报DeprecatedModuleName$VALID_MODULE_MAPPING合法模块名→模块类名映射如order→Commande、product→Product、member→Adherent用于moduleNameRegex校验$EXTRAFIELDS_TYPE2LABELExtraFields 字段类型白名单varchar/text/html/int/double/date/datetime/boolean/price/pricecy/phone/mail/url/ip/icon/password/select/sellist/radio/checkbox/chkbxlst/link/separate。这套插件使 Phan 能从类型是否错误深入到Dolibarr 语义是否违规——例如把GETPOST(x,badtype)、isModEnabled(facture)应为invoice这类历史遗留写法的误用直接拦截在静态检查阶段。5.4 内置插件集与抑制项config.php的plugins数组启用了约 40 个 Phan 内置/捆绑插件config.php按类别可分为代码质量类AlwaysReturnPlugin函数必须无条件返回、UnreachableCodePlugin不可达语句、EmptyStatementListPlugin、DuplicateArrayKeyPlugin、DuplicateExpressionPlugin、LoopVariableReusePlugin类型与 API 类UnknownClassElementAccessPlugin、UnknownElementTypePlugin、SuspiciousParamOrderPlugin、NotFullyQualifiedUsagePlugin、PreferNamespaceUsePlugin、UseReturnValuePlugin字符串/正则/打印类PrintfCheckerPlugin、PregRegexCheckerPlugin、SleepCheckerPlugin语义类InvalidVariableIssetPlugin、RedundantAssignmentPlugin、ConstantVariablePlugin、NumericalComparisonPlugin、SimplifyExpressionPlugin、UnsafeCodePlugin、PHPDocInWrongCommentPlugin、WhitespacePlugin以及自研的NoVarDumpPlugin、SqlInjectionPlugin详见 plugins/ 目录含NoVarDumpPlugin.php、SqlInjectionPlugin.php、ParamMatchRegexPlugin.php三个运行时插件。被注释掉的项如EmptyMethodAndFunctionPlugin、HasPHPDocPlugin、StrictComparisonPlugin保留了取舍痕迹Dolibarr 并未全量开启所有规则而是按误报率可控原则挑选。suppress_issue_types则集中说明了为什么 Dolibarr 放弃某些规则例如PhanPluginWhitespaceTabDolibarr 使用 Tab 缩进、PhanPluginCanUsePHP71Void需保持 PHP 7.0 兼容、PhanPluginShortArrayDolibarr 沿用array()风格、PhanPluginNonBoolBranch31240 处存量、PhanTypeArraySuspiciousNullable约 440 处存量等注释里保留着问题数量统计为后续逐步收紧提供依据。5.5 扩展配置 config_extended.phpconfig_extended.php 通过继承默认配置并做两处收紧在plugins中补启用PHPDocRedundantPlugin、PHPDocInWrongCommentPlugin等默认配置中注释掉的项在此开启如PhanPluginUnknownArrayFunctionReturnTypesuppress_issue_types中移除部分宽松项如保留PhanTypeMismatchArgument的注释说明 Most fixed ~120 occurrences提示扩展模式下该规则已接近可全量开启。由于扩展基线 baseline_extended.txt 当前仅 24 行且未纳入 git因此full模式本质上是对存量问题更透明的试运行。5.6 修复模式 config_fixer.phpconfig_fixer.php 是自动修复专用配置它同样继承config.php但将plugins清空并仅保留DeprecateAliasPlugin通过require_once加载位于 plugins/ 的各个 fixer例如已启用的writeHTMLCellFixer.php以及按需启用的DeprecatedModuleNameFixer、PriceFormFixer、UrlEncodeStringifyFixer、SelectDateFixer、setPageOrientationFixer、textwithpictoFixer、ifsqlFixer、MultiCellFixer、setAutoPageBreakFixer、CellFixer等。配置注释特别提醒当多个 fixer 挂到同一条 Notice 时只有最后一个修复会生效。这些 fixer 多针对 PDF 生成类代码TCPDF 的writeHTMLCell、MultiCell、Cell、setAutoPageBreak等做参数规范化可见 Dolibarr 的历史痛点集中在此类重复性 API 调用上。5.7 扩展桩文件 stubs/config.php通过autoload_internal_extension_signatures为本机未安装的 PHP 扩展提供类型桩stub键名必须与php -m报告的扩展名一致这样当扩展实际可用时 Phan 会跳过桩文件autoload_internal_extension_signatures [ brotli PHAN_DIR . /stubs/brotli.phan_php, curl PHAN_DIR . /stubs/curl.phan_php, gd PHAN_DIR . /stubs/gd.phan_php, imagick PHAN_DIR . /stubs/imagick.phan_php, imap PHAN_DIR . /stubs/imap.phan_php, intl PHAN_DIR . /stubs/intl.phan_php, ldap PHAN_DIR . /stubs/ldap.phan_php, memcached PHAN_DIR . /stubs/memcached.phan_php, mysqli PHAN_DIR . /stubs/mysqli.phan_php, pgsql PHAN_DIR . /stubs/pgsql.phan_php, phpunit PHAN_DIR . /stubs/phpunit.phan_php, session PHAN_DIR . /stubs/session.phan_php, simplexml PHAN_DIR . /stubs/SimpleXML.phan_php, soap PHAN_DIR . /stubs/soap.phan_php, sqlite3 PHAN_DIR . /stubs/sqlite3.phan_php, zip PHAN_DIR . /stubs/zip.phan_php, // ... 共约 20 项 ],对应 stubs/ 目录下 36 个桩文件除扩展桩外还包含第三方库桩nusoap.php、restler.php、stripe.php、GeoIP2.php、swiss-qr-bill.php、ovhsms.php以及模块桩module_numberwords.php、multicompany.php——这些恰好与exclude_file_regex中改以桩文件分析的includes/{nusoap,restler,stripe}对应形成排除原库 装载桩类型的互补策略。六、多平台运行Windows 批处理与 Docker6.1 WindowsPHAN.BATPHAN.BAT 提供 Windows 原生入口须在仓库根目录运行支持三种模式与透传 Phan 参数REM 标准检查 PHAN.BAT REM 扩展检查 PHAN.BAT extended REM 使用修复配置 PHAN.BAT fix REM 标准 phan 参数可附加在命令行后批处理内部会解析参数extended把配置文件切换为dev/tools/phan/config_extended.phpfix则切换为config_fixer.php并追加--automatic-fix、移除--analyze-twice遇到--memory-limit时放弃内置的--memory-limit4G以尊重用户自定义。最终调用../phan/vendor/bin/phan.bat %TWICE% %MEMOPT% %FIX% %CONFIG% %CONFIG_FILE% %USERARGS%其中%MEMOPT%默认--memory-limit4G。6.2 DockerrunPhanDocker.shrunPhanDocker.sh 以phanphp/phan:latest镜像运行同样兼容 Cygwin支持1保存基线与full参数# 检查模式加载基线 docker run -v $MYPATH:/mnt/src phanphp/phan:latest -k /mnt/src/dev/tools/phan/config.php -B /mnt/src/dev/tools/phan/baseline.txt --analyze-twice # 参数为 1保存基线 docker run -v $MYPATH:/mnt/src phanphp/phan:latest -k /mnt/src/dev/tools/phan/config.php --analyze-twice --save-baseline /mnt/src/dev/tools/phan/baseline.txt当参数含full时配置文件切换为config_extended.php。这种方式免去了本机 PHP 与扩展环境的搭建成本。七、接入 pre-commit 与 CI7.1 pre-commit 钩子allow_phan_in_precommit.sh 是 Phan 接入 git pre-commit 的开关式包装默认不启用脚本注释明确This is very slow so not enabled by default只有创建~/.run-phan文件后才执行删除该文件即可关闭同时要求~/vendor/bin/phan存在最终调用~/vendor/bin/phan $并把退出码透传给 git。7.2 GitHub Actionsphan.yml虽然 README 未展开仓库根目录 .github/workflows/phan.yml 正是config.php注释中所指的 CI 使用方可作为最佳实践参考使用shivammathur/setup-php安装 PHP 8.4并启用ast扩展Phan 运行依赖、phan:5.5.2工具通过cs2pr:1.8.6将 Phan 的 checkstyle 输出转换为 GitHub PR 通知--output-modecheckstyle -o _phan.xml采用与脚本一致的参数--quick -k dev/tools/phan/config.php -B dev/tools/phan/baseline.txt --minimum-target-php-version 7.2并附带--analyze-twice之外的--quick优化调度触发时与--minimum-target-php-version最小目标 PHP 版本约束PR 场景下通过 .github/scripts/get_changed_php.sh 拉取变更的 PHP 文件列表仅对变更文件做增量分析phan --file-list且剔除与config.php的exclude_file_regex一致的路径develop 分支与发布分支*.0则执行全量检查检查结果以工件形式保留 2 天。这表明 Dolibarr 的 Phan 检查同时覆盖全量主干质量门禁与PR 增量快速反馈两种形态且本地run-phan.sh的配置与 CI 完全同源。八、小结与自定义扩展建议结合 README 与源码可以看出Dolibarr 的 Phan 集成具备三个工程化特征可直接迁移到其他大型 PHP 项目基线驱动的渐进收紧用baseline.txt托管存量问题--load-baseline用1参数重生成--save-baseline新代码零豁免语义化参数校验通过ParamMatchRegexPlugin把 Dolibarr 特有的模块名、清洗类型、时区参数等约定编译进静态检查实现业务规则即代码检查统一配置、多端复用一份config.php同时服务本地脚本、Windows 批处理、Docker 与 GitHub Actions插件与 fixer 独立成目录plugins/便于按需启用。如需在自有项目中复刻最小步骤是用 composer 安装phan/phan参考 config.php 编写directory_list、exclude_analysis_directory_list、target_php_version与plugins再按 run-phan.sh 的模式封装检查/更新基线双入口脚本即可。Phan 官方 Wiki 的 Getting Started 与 Annotating Your Source Code 两篇文档README 中已给出指引提供了安装细节与phan-*注释语法可作为深入阅读的起点。赞分享企业应用后端【免费下载链接】dolibarrDolibarr ERP CRM is a modern software package to manage your company or foundations activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). its an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers.项目地址https://gitcode.com/gh_mirrors/do/dolibarr点击查看免费下载相关推荐如何永久保存微信聊天记录WeChatMsg免费工具完整实战指南如何永久保存微信聊天记录WeChatMsg免费工具完整实战指南 你是否曾因手机更换、系统升级或意外删除而丢失珍贵的微信对话那些温暖的家人问候、重要的工作沟通终极鸣潮自动化指南从零到高效游戏体验的完整路径终极鸣潮自动化指南从零到高效游戏体验的完整路径 你是否厌倦了在《鸣潮》中重复刷副本、手动管理声骸、盯着技能冷却ok ww这款基于图像识别的鸣潮自动化工具正GUI 自动化计算机视觉RPA人工智能深入理解League OAuth2 Client授权流程从授权码到访问令牌的完整链路深入理解League OAuth2 Client授权流程从授权码到访问令牌的完整链路 OAuth2.0是现代应用开发中实现第三方授权的行业标准协议而Leag上一篇C14 Lambda捕获初始化现代C编程的终极技巧指南下一篇10个Seed-VC高级使用技巧提升语音转换质量创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考