调试 PhpStorm 中所有内容的指南(IDE、浏览器 [fpm]、cli 和 worker)
在本教程中,我们将设置本地 dockerized PHP 开发环境以供 PhpStorm 和 Xdebug 使用。我们还将确保我们可以从命令行以及从 PhpStorm 运行 PHPUnit 测试。还有一个 Youtube 视频来指导您完成整个过程
https://www.youtube.com/watch?v=bZ1MiynqT98
所有代码示例都在我在 github 上的 Docker PHP 教程存储库中公开可用。您可以在part-4-2-phpstorm-docker-xdebug-3-php-8-1-in-2022找到本教程的分支。本教程之前发表在我的个人博客PhpStorm, Docker and Xdebug 3 on PHP 8.1 in 2022。
介绍
本文是使用 Xdebug 设置 PhpStorm 以在 Docker 上进行本地开发的更新,但还将涵盖调试 php-fpm和php 工作进程的“剩余案例” 。
我们仍将依赖于通过 SSH 配置连接到的始终运行的 docker 设置,而不是使用内置的 docker-compose 功能,因为我觉得它更接近我们在 CI / 生产中所做的。但是,我们将不再使用 SSH 密钥,而是简单地通过密码进行身份验证。
这降低了复杂性并消除了有关“SSH 密钥在存储库中公开”的任何令人讨厌的警告。
安装工具
安装作曲家
通过拉取官方的 composer docker 镜像并简单地将 composer 可执行文件“复制”到基础 php 镜像来安装Composer 。此外,作曲家需要扩展mbstring
和phar
# File: .docker/images/php/base/Dockerfile
ARG ALPINE_VERSION
ARG COMPOSER_VERSION
FROM composer:${COMPOSER_VERSION} as composer
FROM alpine:${ALPINE_VERSION} as base
# ...
RUN apk add --update --no-cache \
php-mbstring~=${TARGET_PHP_VERSION} \
php-phar~=${TARGET_PHP_VERSION} \
# ...
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
因为我们希望我们的构建是确定性的,所以我们通过向文件中添加一个COMPOSER_VERSION
变量来“固定”作曲家版本.docker/.env
COMPOSER_VERSION=2.2.5
并使用它.docker/docker-compose/docker-compose-php-base.yml
:
services:
php-base:
build:
args:
- COMPOSER_VERSION=${COMPOSER_VERSION?}
安装 Xdebug
通过以下方式安装扩展apk
(仅适用于local
目标):
# File: .docker/images/php/base/Dockerfile
FROM base as local
RUN apk add --no-cache --update \
php-xdebug~=${TARGET_PHP_VERSION} \
# ensure that xdebug is not enabled by default
&& rm -f /etc/php8/conf.d/00_xdebug.ini
我们也不想xdebug
立即启用但仅在需要时启用(由于启用扩展时性能下降),因此我们删除默认配置文件并禁用应用程序.ini
文件中的扩展
# File: .docker/images/php/base/conf.d/zz-app-local.ini
; Note:
; Remove the comment ; to enable debugging
;zend_extension=xdebug
xdebug.client_host=host.docker.internal
xdebug.start_with_request=yes
xdebug.mode=debug
有关设置的说明(以前在 xdebug < 3 中调用),请参阅从 Docker 容器运行时在 PhpStorm 上修复 Xdebug 。这仍然适用于 Docker Desktop,但对于 Linux 用户,我们需要将魔术引用添加到所有 PHP 容器(我们不能将其添加到 php 基础映像,因为这是运行时设置):xdebug.client_host=host.docker.internal
xdebug.remote_host
host-gateway
services:
service:
extra_hosts:
- host.docker.internal:host-gateway
最后,我们需要将环境变量添加PHP_IDE_CONFIG
到所有 PHP 容器中。该变量定义为PHP_IDE_CONFIG=serverName=dofroscra
,其中“dofroscra”是我们稍后将配置用于调试的服务器的名称。因为我们在多个地方需要相同的值,所以变量配置在.docker/.env
:
PHP_IDE_CONFIG=serverName=dofroscra
然后加入.docker/docker-compose/docker-compose.local.yml
services:
php-fpm:
environment:
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG?}
php-worker:
environment:
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG?}
application:
environment:
- PHP_IDE_CONFIG=${PHP_IDE_CONFIG?}
安装 PHPUnit
PHPUnit 将通过安装composer
但不会“烘焙到图像中”以进行本地开发。因此,我们必须composer require
在容器中运行。为了使这更方便,在以下位置添加了用于运行任意 Composer 命令的 make 目标.make/01-00-application-setup.mk
:
.PHONY: composer
composer: ## Run composer commands. Specify the command e.g. via ARGS="install"
$(EXECUTE_IN_APPLICATION_CONTAINER) composer $(ARGS);
这允许我make composer ARGS="install"
从主机系统运行以composer install
在容器中执行。因此,composer
将使用application
容器的 PHP 版本和扩展来安装依赖项,但我仍然会在本地看到安装的文件,因为代码库被配置为容器的卷。
在安装 phpunit 之前,我们必须添加所需的扩展dom
和xml
容器
# File: .docker/images/php/base/Dockerfile
# ...
RUN apk add --update --no-cache \
php-dom~=${TARGET_PHP_VERSION} \
php-xml~=${TARGET_PHP_VERSION} \
以及通过重建和重新启动docker设置
make docker-build
make docker-down
make docker-up
现在我们可以通过
make composer ARGS='require "phpunit/phpunit"'
这将创建一个composer.json
文件并设置vendor/
目录:
$ make composer ARGS='require "phpunit/phpunit"'
Using version ^9.5 for phpunit/phpunit
./composer.json has been created
Running composer update phpunit/phpunit
Loading composer repositories with package information
Updating dependencies
...
我还添加了
- 一个最小的
phpunit.xml
配置文件 - 一个测试用例
tests/SomeTest.php
- 以及“与 qa 相关的任何内容”的新 Makefile
.make/01-02-application-qa.mk
:
##@ [Application: QA]
.PHONY: test
test: ## Run the test suite
$(EXECUTE_IN_WORKER_CONTAINER) vendor/bin/phpunit -c phpunit.xml
所以我可以简单地通过make test
$ make test
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose.yml -f ./.docker/docker-compose/docker-compose.local.yml exec -T --user application php-worker vendor/bin/phpunit
PHPUnit 9.5.13 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:00.324, Memory: 4.00 MB
OK (1 test, 1 assertion)
安装 SSH
application
我们将通过容器中的 ssh 从 PhpStorm 执行命令。如前所述,我们不会使用密钥文件进行身份验证,而是简单地使用通过APP_SSH_PASSWORD
变量 in配置.docker/.env
并传递给图像 in的密码.docker/docker-compose/docker-compose.local.yml
。此外,我们2222
将主机系统的端口映射到22
应用程序容器的端口,并确保代码库作为主机和容器之间的卷共享
application:
build:
args:
- APP_SSH_PASSWORD=${APP_SSH_PASSWORD?}
volumes:
- ${APP_CODE_PATH_HOST?}:${APP_CODE_PATH_CONTAINER?}
ports:
- "${APPLICATION_SSH_HOST_PORT:-2222}:22"
容器已包含openssh
并设置密码
ARG BASE_IMAGE
FROM ${BASE_IMAGE} as base
FROM base as local
RUN apk add --no-cache --update \
openssh
ARG APP_SSH_PASSWORD
RUN echo "$APP_USER_NAME:$APP_SSH_PASSWORD" | chpasswd 2>&1
# Required to start sshd, otherwise the container will error out on startup with the message
# "sshd: no hostkeys available -- exiting."
# @see https://stackoverflow.com/a/65348102/413531
RUN ssh-keygen -A
# we use SSH deployment configuration in PhpStorm for local development
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
设置 PhpStorm
我们将配置一个远程 PHP 解释器,它使用 SSH 连接在application
容器中运行命令。之前,我们一直在使用SFTP Deployment configuration
,这有点令人困惑(“SFTP 在这里做什么?”),所以我们将使用SSH 配置来代替,并在Cli 解释器界面中配置路径映射
SSH 配置
在File | Settings | Tools | SSH Configurations
使用以下设置创建一个名为“Docker PHP 教程”的新 SSH 配置
- 主机:127.0.0.1
- 港口:
APPLICATION_SSH_HOST_PORT
见.docker/docker-compose/docker-compose.local.yml
- 用户名:
APP_USER_NAME
见.make/.env
- 认证类型:密码
- 密码:
APP_SSH_PASSWORD
见.docker/.env
PHP 解释器
添加File | Settings | PHP
使用新 SSH 配置的新 PHP CLI 解释器
此外,我们定义了xdebug 扩展的路径,因为默认情况下它是禁用的,但 PhpStorm 可以在需要时自动启用它。application
您可以通过以下方式找到容器中的路径
root:/var/www/app# php -i | grep extension_dir
extension_dir => /usr/lib/php8/modules => /usr/lib/php8/modules
root:/var/www/app# ll /usr/lib/php8/modules | grep xdebug
-rwxr-xr-x 1 root root 303936 Jan 9 00:21 xdebug.so
当从 Docker 容器运行时,我们仍然需要修复 PhpStorm 上的 Xdebug,方法是为xdebug.client_host=host.docker.internal
. 这与我们在 中使用的值相同.docker/images/php/base/conf.d/zz-app-local.ini
。
在解释器概述中,我们现在必须配置路径映射,以便 PhpStorm 知道“哪个本地文件属于哪个远程文件”。远程文件夹在.docker/.env
via中定义
APP_CODE_PATH_CONTAINER=/var/www/app
之后我们可以设置断点,例如 insetup.php
并开始调试:
屏幕截图显示 PhpStorm 添加了我们之前定义的 Xdebug 扩展。
PHPUnit
phpunit
通过配置File | Settings | PHP | Test Frameworks
。首先,我们选择刚刚添加的解释器
然后,我们将路径添加到 composer 自动加载脚本和phpunit.xml
配置文件。
application
PhpStorm 现在将使用容器中的 PHP 解释器执行测试
调试
首先,如果您还没有,请查看官方 xdebug 文档。Derick 在详细解释 xdebug 方面做得很好,包括一些有用的视频,例如Xdebug 3: Xdebug with Docker and PhpStorm in 5 minutes
通过 PhpStorm 执行的调试代码
这应该已经可以开箱即用了。只需设置一个断点,右键单击一个文件并选择“调试’…’”
通过 php-fpm、cli 或从 worker 执行的调试代码
对于没有 PhpStorm 的容器“直接”执行的代码,我们首先需要xdebug
在容器中通过移除;
扩展名前面的/etc/php8/conf.d/zz-app-local.ini
; Note:
; Remove the comment ; to enable debugging
zend_extension=xdebug
为了让这更方便一点,我们使用专门的 make recipe 来处理这些操作.make/01-01-application-commands.mk
.PHONY: execute-in-container
execute-in-container: ## Execute a command in a container. E.g. via "make execute-in-container DOCKER_SERVICE_NAME=php-fpm COMMAND="echo 'hello'"
@$(if $(DOCKER_SERVICE_NAME),,$(error DOCKER_SERVICE_NAME is undefined))
@$(if $(COMMAND),,$(error COMMAND is undefined))
$(EXECUTE_IN_CONTAINER) $(COMMAND);
.PHONY: enable-xdebug
enable-xdebug: ## Enable xdebug in the given container specified by "DOCKER_SERVICE_NAME". E.g. "make enable-xdebug DOCKER_SERVICE_NAME=php-fpm"
"$(MAKE)" execute-in-container APP_USER_NAME="root" DOCKER_SERVICE_NAME=$(DOCKER_SERVICE_NAME) COMMAND="sed -i 's/.*zend_extension=xdebug/zend_extension=xdebug/' '/etc/php8/conf.d/zz-app-local.ini'"
.PHONY: disable-xdebug
disable-xdebug: ## Disable xdebug in the given container specified by "DOCKER_SERVICE_NAME". E.g. "make enable-xdebug DOCKER_SERVICE_NAME=php-fpm"
"$(MAKE)" execute-in-container APP_USER_NAME="root" DOCKER_SERVICE_NAME=$(DOCKER_SERVICE_NAME) COMMAND="sed -i 's/.*zend_extension=xdebug/;zend_extension=xdebug/' '/etc/php8/conf.d/zz-app-local.ini'"
为了捕获传入的请求,我们需要让 PhpStorm 通过Run | Start Listening for PHP Debug Connections
.
对应的端口配置在File | Settings | PHP | Debug
。在 Xdebug < 3 中,默认端口是9000
,而在Xdebug 3 中,默认端口是9003
最后,我们需要通过添加服务器File | Settings | PHP | Servers
服务器的名称必须与我们之前配置为serverName
的环境变量中的键值匹配。PHP_IDE_CONFIG
serverName=dofroscra
php-fpm
因为php-fpm
我们必须在通过以下方式激活后重新启动php-fpm
进程而不重新启动容器xdebug
kill -USR2 1
由于这很难记住,我们在.make/01-01-application-commands.mk
# @see https://stackoverflow.com/a/43076457
.PHONY: restart-php-fpm
restart-php-fpm: ## Restart the php-fpm service
"$(MAKE)" execute-in-container DOCKER_SERVICE_NAME=$(DOCKER_SERVICE_NAME_PHP_FPM) COMMAND="kill -USR2 1"
所以我们现在可以简单地运行
make enable-xdebug DOCKER_SERVICE_NAME=php-fpm
make restart-php-fpm
在浏览器中设置断点public/index.php
并打开http://127.0.0.1/或通过curl http://127.0.0.1/
将按预期停止执行。
cli
除了通过 HTTP 请求触发 PHP 脚本,我们还可以运行 CLI 脚本 –make setup-db
例如考虑目标。要调试此类调用,我们需要遵循与之前相同的步骤:
- 在容器中启用
xdebug
扩展application
- 来自 PhpStorm 的“侦听 PHP 调试连接”
运行以下 make 目标将在 中触发断点setup.php
:
make enable-xdebug DOCKER_SERVICE_NAME=application
make setup-db
php-workers
最后,对于长时间运行的 PHP 进程(又名工作人员)也是如此。和以前一样:
- 在容器中启用
xdebug
扩展php-worker
- 来自 PhpStorm 的“侦听 PHP 调试连接”
- 重新启动 php 工作人员
运行以下 make 目标将在 中触发断点worker.php
:
make enable-xdebug DOCKER_SERVICE_NAME=php-worker
make restart-workers
包起来
恭喜,你成功了!如果现在有些事情还不完全清楚,请不要犹豫发表评论。除此之外,您现在应该拥有一个完全配置的开发设置,可以使用 PhpStorm 作为您的 IDE。
如果您喜欢此类内容,请随意:
- 在推特上关注我
- 看看我的博客
- 一定要看看Github 上 Docker PHP 教程的其余部分
using-phpstorm-docker-and-xdebug-3-on-php-81