服务器是:
CentOS Linux release 7.4.1708 (Core) , 3.10.0-693.5.2.el7.x86_64
PHP 5.4.16 (cli) (built: Nov 15 2017 16:33:54)
尽管我在 Linux 中针对 PHP cli 的命令行上进行的测试运行良好,但我无法让 PHP SOAP 在网页上正常运行。经过大量搜索,我发现建议将以下内容添加到 /etc/php.ini 文件:
extension=soap.so
这使得执行 SOAP 请求的网页正常工作,但是 PHP CLI 产生了此错误:
PHP Warning: Module 'soap' already loaded in Unknown on line 0
即使在命令行执行“php -v”,我也会收到上述消息。
如果已经加载了 soap 模块,为什么 soap 在 cgi 网页中不起作用?如果已经加载,它在哪里加载的?我该如何纠正这个问题?
# yum list | grep -i soap
php-soap.x86_64 5.4.16-43.el7_4 @updates
CGSI-gSOAP.x86_64 1.3.10-7.el7 epel
CGSI-gSOAP-devel.x86_64 1.3.10-7.el7 epel
SOAPpy.noarch 0.11.6-17.el7 base
fence-agents-vmware-soap.x86_64 4.0.11-66.el7_4.3 updates
glite-lbjp-common-gsoap-plugin.x86_64 3.2.12-7.el7 epel
glite-lbjp-common-gsoap-plugin-devel.x86_64
gsoap.x86_64 2.8.16-9.el7 epel
gsoap-devel.x86_64 2.8.16-9.el7 epel
gsoap-doc.noarch 2.8.16-9.el7 epel
perl-POE-Component-Server-SOAP.noarch 1.14-12.el7 epel
perl-SOAP-Lite.noarch 1.10-1.el7 epel
perl-SOAP-WSDL.noarch 3.003-6.el7 epel
perl-SOAP-WSDL-Apache.noarch 3.003-6.el7 epel
perl-SOAP-WSDL-examples.noarch 3.003-6.el7 epel
php-ZendFramework-Soap.noarch 1.12.20-1.el7 epel
php-ZendFramework2-Soap.noarch 2.4.11-1.el7 epel
php-pear-SOAP.noarch 0.13.0-5.el7 epel
qtsoap.x86_64 2.7-9.el7 epel
qtsoap-devel.x86_64 2.7-9.el7 epel
这是‘yum install php-soap’的一部分:
# cat /etc/php.d/soap.ini
; Enable soap extension module
extension=soap.so
似乎应该不管它。如果我从 /etc/php.ini 中删除 extension=soap.so,命令行上的警告错误消息就会消失,但它会破坏与 php soap 相关的网页。
此外,我不明白为什么不简单地安装和配置用于 php 网页的 SOAP 以及用于 php 和 soap 的其余 yum 安装。
他们的 .ini 或其他配置文件是否需要更改以添加 extension=soap.so?如果需要,这些文件在哪里?
我通过 Web 浏览器和命令行运行了 phpinfo 程序并得到了相同的路径结果:
Server API => Command Line Interface
Virtual Directory Support => disabled
Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini
Scan this dir for additional .ini files => /etc/php.d
例外情况是,从 Web 浏览器的“服务器 API”来看,它是:Apache 2.0 Handler。
当我运行这个时:
php -i | grep -i soap
这是输出:
PHP Warning: Module 'soap' already loaded in Unknown on line 0
/etc/php.d/soap.ini,
PHP Warning: Unknown: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in Unknown on line 0
soap
Soap Client => enabled
Soap Server => enabled
soap.wsdl_cache => 1 => 1
soap.wsdl_cache_dir => /tmp => /tmp
soap.wsdl_cache_enabled => 1 => 1
soap.wsdl_cache_limit => 5 => 5
soap.wsdl_cache_ttl => 86400 => 86400
为了进行比较,我在 virtualBox 中为 CentOS 7 创建了一个实例,并手动安装了 PHP 7,而不是 CentOS 7 附带的 PHP 5。
PHP 7.0.25 (cli) (built: Oct 27 2017 13:55:11) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
它只有一个位于 /etc/php.ini 中的 php.ini 文件,并且添加了 soap.so 后,它在命令行中运行良好且没有错误,并且从服务器运行的 phpinfo() 也表明它正在使用 /etc 中的 php.ini。它还提到它正在使用 /etc/php.d,但 PHP 5 也是如此。但是目录看起来不同,即使它包含相同的 soap.ini 文件的内容,但文件名不同。在 PHP 7 安装中,它们被命名为 20-soap.ini,而在 PHP 5 安装中,它们被命名为 soap.ini。
在 PHP 5 中,如果我将 soap.so 添加到 /etc/php.ini 文件中,CGI 显然正在使用相同的功能,这会使 SOAP 为 CGI 工作,但它会在命令行上生成有关 soap 已加载的错误。
这可能会有所帮助,我已经编辑了 php.ini 以添加 soap.ini,并执行以下操作:
service httpd restart
这会导致 CGI 工作,并且 PHP 命令行不会出现任何错误,也就是说,直到我重新启动服务器,然后返回有关 soap 已加载的 PHP 警告。
PHP cli 在哪里以及如何加载 soap.so,以至于不需要将其添加到 php.ini 文件中?这是否意味着 PHP 是在内置 soap.so 的情况下编译的?
答案1
cli 和 cgi 的 php.ini 路径可以不同。<?php phpinfo(); ?>
使用 cli 和 cgi 进行测试,看看它们使用哪个路径。
第二轮
在我看来,您的 php cli 可执行文件与 soap.so 链接,这就是为什么当您在 php.ini 中指示它再次加载它时它会抱怨的原因。另一方面,您的 Web 服务器可能通过未与 soap.so 链接的共享库使用 php,因此您需要 php.ini 中的“extension=soap.so”行才能通过 dlopen() 加载 soap.so。解决方案可能是对 Web 服务器 php 库和 php cli 可执行文件使用不同的 php.ini,就像在基于 Debian 的发行版中一样。尝试查找您的 Web 服务器如何使用 php 模块。例如,在装有 apache 的 Ubuntu 16.04 上可以找到/usr/lib/apache2/modules/libphp7.0.so
。然后比较链接的库:
ldd $(which php)
ldd /usr/lib/apache2/modules/libphp7.0.so
(将第二行的路径替换为您的 php 模块的路径。)
您可以在 php 命令行使用 -c 开关来指定不同的 ini 文件。
php -c /etc/php.cli.ini myprogram.php
答案2
答案是肯定的。每当我排除 php 故障时,我做的第一件事就是使用 phpinfo() (或 php -i) 来验证它首先使用哪一个。
答案3
是的,这很正常。以 Debian 为例:
root@xxxxx:~# ls /etc/php5/
apache2 cgi cli conf.d fpm mods-available
例如,在本例中,有一个默认的 apache2 php.ini,另一个用于 CGI,另一个用于 FPM,还有一个用于 CLI。如果我进入每个目录,我会找到每个目录的 php.ini。
答案4
PHP 可能以不同的方式读取 SAPI(服务器 API)和 CLI 的配置文件。
如果在您或系统范围的 bash 配置文件中设置了此环境变量,那么 PHP 将扫描目录以查找配置文件。
PHP_INI_SCAN_DIR=:/etc/php.d
这听起来就像你的情况。该环境变量可以为你设置,但不能为 apache 用户设置。
当您运行 CLI 时,它会读取所有 php.ini 配置文件并抛出警告。
看http://php.net/manual/en/configuration.file.php有关如何配置 PHP 的更多信息。