PHP: setlocale 的值从何而来?

PHP: Where does setlocale's Value Come From?

我注意到 PHP 的 str_word_count is behaving differently on the command line vs. on the web. The behavior seems to due to the default locale value in each environment. If I use setlocale 查看当前语言环境 (echo setlocale(LC_ALL, 0);),在命令行上我得到

C/en_US.UTF-8/C/C/C/C

而在网络上我得到

C

那么各种 PHP SAPI(cli、fpm、mod_php 等)从哪里获得这个默认值?

我的推测是看起来很奇怪的 C/en_US.UTF-8/C/C/C/C 语言环境所有六个语言环境类别都挤在一起,这告诉我 LC_CTYPE=en_US.UTF-8 和其他类别都设置了 C语言环境——所以换一种方式来表达我的问题:为什么我的 php-fpm 服务器将所有语言环境类别默认设置为 C,而我的命令行 PHP 只设置了一个语言环境至 en_US.UTF-8

您可以在 php.ini

中设置 intl.default_locale

似乎 PHP 从 shell 的环境中直接 获取这些值,LC_CTYPE 的值还将检查 LANG 的值

% cat test.php
<?php
echo setlocale(LC_ALL, 0),"\n";

% echo $LANG
en_US.UTF-8

% echo $LC_CTYPE

% php test.php
C/en_US.UTF-8/C/C/C/C

% LC_CTYPE=C php test.php
C

% LANG=C php test.php
C

% LANG=C LC_CTYPE=en_US.UTF-8 php test.php
C/en_US.UTF-8/C/C/C/C

因此,MacOS 似乎将用户个人 shell 的 LANG 设置为 en_US.UTF-8。我的假设是当我通过

启动我的 php-fpm 实例时
brew services start php

那 -- LaunchAgent? -- 正在使用 shell,其中 LANGLC_CTYPE 设置为 C -- 大概是因为只有人类才会对 UTF-8 格式的东西感兴趣。

我假设“在网络上”指的是 Linux 下的 Apache 网络服务器 ...

在这种情况下,setlocale(LC_ALL, 0) 返回 C 的原因如下:

如果您从 Apache 服务器检查 /etc/apache2/envvars,您会发现以下几行:

## The locale used by some modules like mod_dav
export LANG=C
## Uncomment the following line to use the system default locale instead:
#. /etc/default/locale

作为结果 phpinfo() 将产生以下输出:

如果将/etc/apache2/envvars中的行修改如下...

## The locale used by some modules like mod_dav
# export LANG=C
## Uncomment the following line to use the system default locale instead:
. /etc/default/locale

并重新启动 Apache。然后 Apache 将使用您操作系统的区域设置和语言设置(您可以在终端中使用 locale 命令检查它们的 os 设置)。作为上述更改的结果,phpinfo() 将在定义了 de_CH.UTF-8 语言环境的系统上产生例如以下输出:

但您最终可能仍会 setlocale(LC_ALL, 0) 返回 C 或至少某些 LC_ 变量被设置为 C 例如 LC_CTYPE=de_CH.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C"

为了确保 PHP 使用 OS 中的区域设置,您必须调用 setlocale(LC_ALL, "")https://www.php.net/manual/en/function.setlocale.phpsetlocale 的手册说明如下:

// If locales is the empty string "", the locale names will be set from 
// the values of environment variables with the same names as the above
// categories, or from "LANG".

// On Windows, setlocale(LC_ALL, '') sets the locale names from the 
// system's regional/language settings (accessible via Control Panel). 

最后是您的 setlocale(LC_ALL, 0) returns 在您的操作系统上配置的值,例如de_CH.UTF-8:-)