diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..c5861b2
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,49 @@
+name: Build and Deploy MkDocs
+
+on:
+ push:
+ branches:
+ - $default-branch
+
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup Pages
+ id: pages
+ uses: actions/configure-pages@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Install Dependencies
+ run: pip install -r requirements.txt
+ - name: Build
+ run: mkdocs build --strict
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: './build'
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..417d0fb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+build/
+venv/
diff --git a/README.md b/README.md
index 048ce3c..5a61b85 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,9 @@
# Why cannot you set up Xdebug?
-> ℹ️ Use issues tab to suggest changes
-
-Most users experience difficulties with setting up [Xdebug](https://xdebug.org/) in their development environments. The problem has deteriorated due to several reasons:
-
-- Insufficient understanding of Xdebug work
-- An overload of ambiguous and inaccurate google-answers
-- No out-of-the-box solution to run "in one click"
-
-As long as the last two reasons are hard to affect, the focus of the article is decreasing impact of the first reason. So the goal is to explain how Xdebug does work under the hood, how IDE does work with Xdebug, and how the browser side has to work. The narrative format will help you systematize knowledge in an orderly manner. As a result, the acquired knowledge will reduce efforts on setting Xdebug up in an unfamiliar environment.
-
-In addition, you will gain insights into the following related questions: what is DBGp Proxy, why you should not use Xdebug Cloud and how to set up Xdebug in nonstandard environments (like SPA application). You won't gain information about instructions for installing Xdebug extension, instructions for using the debugger.
-
-The document is presented in two languages:
-
-- [English](./xdebug_en.md)
-- ~~[Русский](./xdebug_ru.md)~~ deprecated
+The article is [here](https://paulradley.github.com/why-cannot-you-set-up-xdebug)
### TODO List
-- WSL2 environment
\ No newline at end of file
+- WSL2 environment
+- SEO TAGS
+- Google Analytics
\ No newline at end of file
diff --git a/docs/assets/extra.css b/docs/assets/extra.css
new file mode 100644
index 0000000..fa16c16
--- /dev/null
+++ b/docs/assets/extra.css
@@ -0,0 +1,14 @@
+.md-typeset .admonition,
+.md-typeset details {
+ border-width: 0;
+ border-left-width: 4px;
+ font-size: .75rem;
+}
+
+.md-typeset table:not([class]) {
+ border-top: 0
+}
+
+.md-typeset th {
+ display: none;
+}
diff --git a/docs/assets/favicon.svg b/docs/assets/favicon.svg
new file mode 100644
index 0000000..99f4139
--- /dev/null
+++ b/docs/assets/favicon.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/docs/img/cli_mode_xdebug.webp b/docs/img/cli_mode_xdebug.webp
new file mode 100644
index 0000000..be2d2d1
Binary files /dev/null and b/docs/img/cli_mode_xdebug.webp differ
diff --git a/docs/img/dbgp_ide_key.webp b/docs/img/dbgp_ide_key.webp
new file mode 100644
index 0000000..d289d8f
Binary files /dev/null and b/docs/img/dbgp_ide_key.webp differ
diff --git a/docs/img/dbgp_proxy_tool.webp b/docs/img/dbgp_proxy_tool.webp
new file mode 100644
index 0000000..9916684
Binary files /dev/null and b/docs/img/dbgp_proxy_tool.webp differ
diff --git a/docs/img/multiple_projects.webp b/docs/img/multiple_projects.webp
new file mode 100644
index 0000000..f65964f
Binary files /dev/null and b/docs/img/multiple_projects.webp differ
diff --git a/docs/img/web_browser_ide_key.webp b/docs/img/web_browser_ide_key.webp
new file mode 100644
index 0000000..c980c38
Binary files /dev/null and b/docs/img/web_browser_ide_key.webp differ
diff --git a/docs/img/web_mode_schema.webp b/docs/img/web_mode_schema.webp
new file mode 100644
index 0000000..2a096fd
Binary files /dev/null and b/docs/img/web_mode_schema.webp differ
diff --git a/docs/img/web_mode_simple.webp b/docs/img/web_mode_simple.webp
new file mode 100644
index 0000000..ca3dc41
Binary files /dev/null and b/docs/img/web_mode_simple.webp differ
diff --git a/docs/img/web_mode_xdebug.webp b/docs/img/web_mode_xdebug.webp
new file mode 100644
index 0000000..c8d43d2
Binary files /dev/null and b/docs/img/web_mode_xdebug.webp differ
diff --git a/docs/img/xdebug_cloud.webp b/docs/img/xdebug_cloud.webp
new file mode 100644
index 0000000..b248965
Binary files /dev/null and b/docs/img/xdebug_cloud.webp differ
diff --git a/docs/img/xdebug_cloud_id.webp b/docs/img/xdebug_cloud_id.webp
new file mode 100644
index 0000000..b84ac9d
Binary files /dev/null and b/docs/img/xdebug_cloud_id.webp differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..be2aeb5
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,412 @@
+---
+hide:
+ - navigation
+---
+
+# Why cannot you set up Xdebug?
+
+## Abstract
+
+Most users experience hardships with setting up [Xdebug](https://xdebug.org/) in their development environments. This problem has deteriorated for two reasons:
+
+- Insufficient understanding of Xdebug work
+- An overload of ambiguous and inaccurate google-answers
+
+As long as the second reason is hard to affect, this article focuses on reducing the impact of the first reason. So the goal is to explain how Xdebug works under the hood, how an IDE interacts with Xdebug, and how a web browser side has to function. The narrative format of the article will help systematize your knowledge in an orderly manner. As a result, the acquired knowledge will lead to reduction of efforts on setting Xdebug up in an unfamiliar environment.
+
+In addition, you will gain insights into the following related questions: What is DBGp Proxy Tool, and why you should not use Xdebug Cloud. You won't gain any information about installing the Xdebug extension or using the debugger.
+
+## Problem area
+
+Setting up Xdebug requires an interaction with several components in the development environment — a client, a server, an IDE. The number of components and their potential working environment lead to complications in a configuration process. Understanding how Xdebug works will reduce efforts on setting up Xdebug in any development environment.
+
+!!! note ""
+
+ Configuration examples are presented only for Xdebug version 3.
+
+## Operational principle
+
+Let's start with PHP. In some perspective PHP applications could work in two modes:
+
+- The Web mode — handling incoming HTTP requests from a browser
+
+ Examples of stacks working with the mode: php cgi, nginx+fpm, nginx unit
+
+- The CLI mode — direct execution from a terminal
+
+ Examples of stacks working with the mode: roadrunner, phpunit, horizon
+
+Xdebug works the same in these two modes. But we are going to examine them separately for clarification.
+
+### The Web mode
+
+It is assumed that a web server has already started and ready to handle HTTP requests. An illustration of HTTP request path from a client to PHP looks like the one below:
+
+
+
+!!! note ""
+
+ `...` — means the presence of intermediate nodes that take place in the Internet. They may not exist in a local development.
+
+Xdebug injects to that flow (note that the extension tries to connect back to the client):
+
+
+
+Let's examine this process step-by-step in more detail:
+
+
+
+!!! note ""
+
+ In that context, the client is a local host. It has a running browser that sends an HTTP request and an IDE that listens to incoming connections from Xdebug.
+
+1. The client sends the HTTP request with a trigger which means that this request must be debugged.
+2. The PHP script is started, then it receives and handles the request.
+3. The PHP engine during startup hooks runs the Xdebug extension.
+4. Checking the presence of the trigger is in progress.
+5. A client's address is being searched.
+6. Attempts are being made to establish a connection with the client.
+7. Debugging launch: transfering control to the client, communication, waiting commands from the client.
+8. The end of debugging due to a stop command from the client or a finish of script execution.
+
+#### The trigger
+
+The HTTP request must contain a special trigger to initialize the Xdebug session on the server side. The trigger is a simple key+value pair: `XDEBUG_TRIGGER=` (the legacy version is still working `XDEBUG_SESSION=`). This trigger must be a part of the HTTP request from one of the possible options:
+
+- Cookie
+- Query param
+- Post payload
+
+A popular browser extension [Xdebug Helper](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc?hl=en) uses the Cookie approach to transfer that trigger.
+
+!!! note ""
+
+ The `xdebug.trigger_value` setting allows to configure the exact value for activation the debugging process. By default, Xdebug accepts any non-empty value.
+
+#### The Xdebug hook and the trigger checking
+
+The Xdebug extension integrates with the PHP lifecycle. So when the PHP engine starts, the Xdebug startup hook checks the presence of the trigger. If there is no trigger, the Xdebug extension doesn't attempt establishing a connection and PHP continues to work as usual.
+
+#### The search for a client's address and establishing a connection
+
+If there was a positive check, the Xdebug extension starts to search for the client's address and establish a connection with it. The success of this step is the established connection with a client's IDE.
+
+The search logic is simple. Just iterate (by trying to connect) all potential clients' addresses until the first succeed connection has been found. Here is an example of the workflow:
+
+1. Xdebug tries to connect to the address from the environment variable `HTTP_X_FORWARDED_FOR`
+2. Xdebug tries to connect to the address from the environment variable `REMOTE_ADDR`
+3. _(fallback)_ Xdebug tries to connect to the address from the Xdebug configuration (by default, it is `localhost`)
+
+If all attempts have failed, PHP would go on as usual (without debugging).
+
+!!! warning ""
+
+ By default, checking addresses from environment variables is disabled, and Xdebug only looks at the fallback address. Enabling this option frees you of hard coding the client's address.
+
+The described workflow uses this configuration:
+
+```ini
+; This is overridden behavior. By default, it is disabled
+xdebug.discover_client_host = true
+
+; This is used as the fallback address
+xdebug.client_host = localhost
+; Xdebug always connects to an IDE on this port
+xdebug.client_port = 9003
+```
+
+#### The communication with the client
+
+[DBGp](https://xdebug.org/docs/dbgp) protocol aims to form communication between the Xdebug extension and the IDE. As a result, the familiar features like breakpoints, stacktrace, variable inspection are worked in the IDE.
+
+At that step, the interactive debugging process has started for the client.
+
+### CLI mode
+
+CLI applications are run from a console. An illustration of injecting Xdebug in the CLI mode looks like the one below:
+
+
+
+The communication is similar to the [Web mode](#web-mode) but with a few distinctions:
+
+1. The trigger `XDEBUG_TRIGGER` must be passed as an environment variable to initialize the Xdebug session.
+
+2. Checking addresses from environment variables feature (from the [Searching client's address](#searching-clients-address-and-establishing-a-connection) section) won't work in that mode. The `xdebug.client_host` setting has to be overridden with the client's address.
+
+```ini
+xdebug.client_host =
+xdebug.client_port = 9003
+```
+
+Here is an example of starting PHP in the CLI mode with the enabled Xdebug extension:
+
+```shell
+XDEBUG_TRIGGER=1 php script.php
+```
+
+### IDE
+
+The main task of the IDE is to accept the Xdebug connection and provide an interactive debug process for users. But also the IDE has to deal with two nontrivial issues — a file mapping and working with multiple projects.
+
+#### File mapping
+
+What is a file mapping issue? The absolute path to the file containing code is used in actions such as the 'Step over' command or when a user sets breakpoints. These paths will differ between the IDE and the Xdebug extension if the code is being executed in an isolated environment, like a virtual machine, a container or a remote server.
+
+The Xdebug extension can only work with its paths and cannot control the file mapping itself. Instead, the IDE performs the correct file mapping between the local and remote paths.
+
+Here's an example of how the IDE substitutes these paths to maintain proper communication with the Xdebug extension (based on user settings):
+
+[//]: # (TODO: maybe be more specific?)
+
+| | |
+|------------------|--------------------------------------|
+| Local host path | `/Users/macos/my-project/index.php` |
+| Remote host path | `/home/vagrant/my-project/index.php` |
+
+#### Multiple projects
+
+
+
+Nowadays, developers often work on multiple projects at the same time. How to achieve automatic routing of incoming Xdebug requests to the right project?
+
+This problem is fully solved in PhpStorm and partially in Visual Studio Code. In the next section, the description will be provided.
+
+#### PhpStorm integration
+
+PhpStorm's logic uses fuzzy criteria to determine the correct routing. In general, it consists of two steps:
+
+1. Getting values from environment variables that has been set at start of the PHP script. PhpStorm iterates through them until the first non-empty has found:
+
+ - `PHP_IDE_CONFIG`
+ - `SERVER_NAME` and `SERVER_PORT`
+ - `SSH_CONNECTION`
+
+ The found value is used as an identifier of the project.
+
+ !!! warning ""
+
+ If all environment variables have empty values, an interactive debug process in not possible.
+
+2. Searching for the right project from in the project settings `Settings` / `PHP` / `Servers`. If there is no match, PhpStorm adds a new `Server` based on the calculated identifier.
+
+As a result, created `Server` will be used for automatic routing and correct file mapping.
+
+#### Visual Studio Code integration
+
+The popular [PHP Debug Adapter](https://github.com/xdebug/vscode-php-debug) for Visual Studio Code brings all usual debugging processes and file mapping via `pathMappings` setting in the configuration`launch.json`, except for working with multiple projects.
+
+The current solution assumes that only one project at a time can listen to Xdebug connections. For that reason, a user has to manually change a project that will be debugged.
+
+## Proxy
+
+!!! note ""
+
+ This section is dedicated to the solutions (that collaborate with Xdebug) that can enhance a development environment. The content will be accompanied by examples of usage the solutions with PhpStorm.
+
+The proxy allows the establishment of the connection from the debugger to the IDE through an intermediate node. That approach makes it possible to:
+
+- Easily configure the Xdebug extension
+- Bypass network restrictions
+- Debug an application by multiple users
+
+### DBGp Proxy Tool
+
+[DBGp Proxy Tool](https://xdebug.org/docs/dbgpProxy) is a utility that runs on a node. It provides two features: partially coping with [NAT](https://en.wikipedia.org/wiki/Network_address_translation) and allowing multiple users to debug an application simultaneously (on a shared stage, for example).
+
+
+
+
+Setting up is divided into two parts: configuration on the server side and configuration on the client side. Here is the server side configuration:
+
+1. Xdebug establishes a connection with DBGp Proxy Tool. So the Xdebug configuration must have the explicit address of DBGp Proxy Tool specified in the `xdebug.client_host` setting.
+
+ ```ini
+ ; Disable auto discover from environment variables
+ xdebug.discover_client_host = false
+ xdebug.client_host =
+ xdebug.client_port = 9003
+ ```
+
+2. DBGp Proxy Tool starts on the node and listens to new connections from the Xdebug extension and the IDE.
+
+ ```shell
+ ./dbgpProxy --server 0.0.0.0:9003 --client 0.0.0.0:9001
+ ```
+
+Here is the client side configuration:
+
+1. The client's IDE sends a request to DBGp Proxy Tool. This request contains an IDE key — a unique identifier for DBGp Proxy Tool that used for routing the Xdebug session to the right client.
+
+
+
+2. A user prepares the IDE key on the browser side and initiates debugging of an HTTP request. The trigger with the specific value must be set — `XDEBUG_TRIGGER=Bob`.
+
+
+
+ Under the hood `XDEBUG_TRIGGER=Bob` will be sent as Cookie.
+
+When the setup is completed, DBGp Proxy Tool will route the Xdebug session to the client's IDE using the specified IDE key from the client's HTTP request.
+
+!!! warning ""
+
+ DBGp Proxy Tool establishes new connections to the IDE for each new incoming Xdebug request. This implies that the connection from DBGp Proxy Tool to the client must not be affected by network restrictions.
+
+### Xdebug Cloud
+
+[Xdebug Cloud](https://xdebug.cloud/) is a commercial product. It simplifies significantly the installing process. Moreover, it affords to establish the Xdebug session between nodes behind NAT and firewalls. Multi-user usage is also supported.
+
+
+
+The setting up workflow is small:
+
+1. Get the Cloud ID (register + pay)
+
+2. Put the Cloud ID into the Xdebug configuration:
+
+ ```ini
+ xdebug.cloud_id = f0ec9529-184b-471c-bd20-c12b1bfa9258
+ ; The timeout should be higher for the reliable connection
+ xdebug.connect_timeout_ms = 1000
+ ```
+
+3. Put the Cloud ID into the configuration of PhpStorm.
+
+
+
+That's it. This is the easiest way to set up Xdebug in any environment! But...
+
+!!! danger "Be aware!"
+
+ The connection between the PHP engine and Xdebug Cloud is not secured. The DBGp protocol allows to execute any PHP code. So, in case of [man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack), an attacker can gain a full access to your system ([issue link](https://github.com/xdebug/xdebug/pull/646)).
+
+ For that reason use Xdebug Cloud at your own risk!
+
+## Troubleshooting
+
+This troubleshooting is focused on covering basic steps that can help in most cases. Comprehending the information posted above is highly necessary for following the troubleshooting.
+
+### How to diagnose a problem?
+
+If Xdebug does not connect to an IDE, follow this checklist to diagnose a problem:
+
+1. Check that the Xdebug extension is installed for both CLI and Web modes:
+
+ ```shell
+ php -v
+ -> with Xdebug v3.3.1, Copyright (c) 2002-2023, by Derick Rethans
+
+ php-fpm -v
+ -> with Xdebug v3.3.1, Copyright (c) 2002-2023, by Derick Rethans
+ ```
+
+2. Check the actual configuration of Xdebug. The CLI and Web modes use their own configurations. This means that changes must be made twice, once for the CLI mode and once for the Web mode:
+
+ ```shell
+ php -i | grep xdebug
+
+ php-fpm -i | grep xdebug
+ ```
+
+ 1. Pay attention on these options:
+
+ ```ini
+ xdebug.mode = debug ; For Step Debugging mode, always use 'debug'
+ xdebug.start_with_request = default ; For Step Debugging mode, always use 'default'
+ xdebug.client_port = 9003 ; Use this port as the default
+ xdebug.discover_client_host = ; Depending on your environment, it could be 'true' or 'false'
+ xdebug.client_host = ; If the previous setting is 'false', then type the client's address here
+ xdebug.idekey = ; Leave the empty value if you don't use DBGp Proxy Tool
+ ```
+
+ 2. The changes must be made in `.ini` files. Use these commands to detect their locations:
+
+ ```shell
+ php --ini
+
+ php-fpm -i # Check the beginning of the output
+ ```
+
+ !!! note ""
+
+ Keep in mind to restart PHP-FPM after the changes have been made.
+
+3. Check if the client's address is correct:
+
+ 1. In a Docker environment on Mac or Windows, the only solution is:
+
+ ```ini
+ xdebug.discover_client_host = false
+ xdebug.client_host = host.docker.internal
+ ```
+
+ 2. In a Docker environment on Linux or a virtual machine in any operational system (with host only network), the auto discover feature works fine:
+
+ ```ini
+ xdebug.discover_client_host = true
+ xdebug.client_host = localhost
+ ```
+
+ 3. On localhost or on a remote server with an open SSH connection to it:
+
+ ```ini
+ xdebug.discover_client_host = false
+ xdebug.client_host = localhost
+ ```
+
+4. Inspect a log file of the Xdebug extension:
+
+ ```ini
+ xdebug.log = /tmp/xdebug.log
+ xdebug.log_level = 7
+ ```
+
+5. Inspect a log file of PhpStorm:
+
+ - Open: **Help** / **Diagnostic Tools** / **Debug Log Settings**
+ - Add line and save: `#com.jetbrains.php`
+ - Checkout the log file: **Help** / **Show Log in Finder/Explorer/Navigator**
+
+### How to set up PhpStorm?
+
+PhpStorm offers a variety of features for working with PHP, including debugging. However, there is a set of settings that have to be configured to achieve the full experience.
+
+1. Ensure that one of the environment variables (from the [PhpStorm integration](#phpstorm-integration) section) is set on the server side.
+ 1. If `SERVER_NAME` or `SSH_CONNECTION` are not set (as is often the case in a Docker environment), using `PHP_IDE_CONFIG` becomes the only appropriate solution.
+ 2. The `PHP_IDE_CONFIG` variable must adhere to the following pattern: `serverName=`.
+
+2. Add your PHP interpreter in following section: `Settings` / `PHP` / `CLI interpreter`.
+3. Additionally, add file mapping in the same section.
+4. The `Server` record must be provided in the `Settings` / `PHP` / `Server` section. PhpStorm creates it for you after the first attempt of the Xdebug session.
+5. Additionally, add file mapping for the created `Server`.
+
+As a result, you can run CLI scripts with debugging, execute tests with execute, always listen for PHP Debug connections and expect debugging in the correct project.
+
+### Debugging an SPA-application
+
+Mostly, backend and frontend applications are located at different addresses. In that case, the browser extension [Xdebug Helper](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc) doesn't send the debugging trigger to the backend. The main solution is to use the same domain for both applications.
+
+1. Edit the configuration file of the frontend application's web-server. If [webpack](https://webpack.js.org/) is used, then modify `webpack.config.js`:
+
+ ```javascript
+ module.exports = {
+ devServer: {
+ // Use the same configuration block for `vite.config.js`
+ proxy: {
+ '/api': {
+ target: `${process.env.BACKEND_URL}`,
+ changeOrigin: true,
+ xfwd: false,
+ },
+ },
+ ...
+ ```
+
+2. Update the backend address to match the frontend application address on the client (typically by modifying the `BACKEND_URL` variable in the `.env.local`)
+
+Now, all request with the `/api` prefix will be proxied to the backend. the `XDEBUG_TRIGGER` trigger will be sent as a Cookie.
+
+### Debugging in other environments
+
+Check out [Ultimate Guide](https://www.jetbrains.com/help/phpstorm/debugging-with-phpstorm-ultimate-guide.html) from JetBrains. There are a few cases of debugging in nonstandard environments (like via SSH tunnel). Also, you can find more solutions to real problems there.
+
+Check out [Step Debugging](https://xdebug.org/docs/step_debug) on the official Xdebug website.
diff --git a/img/cli_xdebug.png b/img/cli_xdebug.png
deleted file mode 100644
index a9d8d51..0000000
Binary files a/img/cli_xdebug.png and /dev/null differ
diff --git a/img/cloud_id.png b/img/cloud_id.png
deleted file mode 100644
index 295bb2a..0000000
Binary files a/img/cloud_id.png and /dev/null differ
diff --git a/img/cloud_schema.png b/img/cloud_schema.png
deleted file mode 100644
index ac60d8f..0000000
Binary files a/img/cloud_schema.png and /dev/null differ
diff --git a/img/dbgp.png b/img/dbgp.png
deleted file mode 100644
index be2d2cb..0000000
Binary files a/img/dbgp.png and /dev/null differ
diff --git a/img/dbgp_register.png b/img/dbgp_register.png
deleted file mode 100644
index 730a6f4..0000000
Binary files a/img/dbgp_register.png and /dev/null differ
diff --git a/img/helper_idekey.png b/img/helper_idekey.png
deleted file mode 100644
index d7bb101..0000000
Binary files a/img/helper_idekey.png and /dev/null differ
diff --git a/img/ide_cli_run.png b/img/ide_cli_run.png
deleted file mode 100644
index 23f31c7..0000000
Binary files a/img/ide_cli_run.png and /dev/null differ
diff --git a/img/ide_file_mapping.png b/img/ide_file_mapping.png
deleted file mode 100644
index db76c55..0000000
Binary files a/img/ide_file_mapping.png and /dev/null differ
diff --git a/img/ide_filename.png b/img/ide_filename.png
deleted file mode 100644
index 3daac69..0000000
Binary files a/img/ide_filename.png and /dev/null differ
diff --git a/img/ide_find_server.png b/img/ide_find_server.png
deleted file mode 100644
index 1408d8b..0000000
Binary files a/img/ide_find_server.png and /dev/null differ
diff --git a/img/ide_host_port.png b/img/ide_host_port.png
deleted file mode 100644
index 665c251..0000000
Binary files a/img/ide_host_port.png and /dev/null differ
diff --git a/img/ide_name.png b/img/ide_name.png
deleted file mode 100644
index f705b2f..0000000
Binary files a/img/ide_name.png and /dev/null differ
diff --git a/img/ide_none.png b/img/ide_none.png
deleted file mode 100644
index 0260c94..0000000
Binary files a/img/ide_none.png and /dev/null differ
diff --git a/img/ide_select_project.png b/img/ide_select_project.png
deleted file mode 100644
index 77fc64e..0000000
Binary files a/img/ide_select_project.png and /dev/null differ
diff --git a/img/ide_servers.png b/img/ide_servers.png
deleted file mode 100644
index d64a240..0000000
Binary files a/img/ide_servers.png and /dev/null differ
diff --git a/img/project_search.png b/img/project_search.png
deleted file mode 100644
index cfb7cac..0000000
Binary files a/img/project_search.png and /dev/null differ
diff --git a/img/session.png b/img/session.png
deleted file mode 100644
index 96d89f8..0000000
Binary files a/img/session.png and /dev/null differ
diff --git a/img/web_request.png b/img/web_request.png
deleted file mode 100644
index 1b7c03a..0000000
Binary files a/img/web_request.png and /dev/null differ
diff --git a/img/web_xdebug.png b/img/web_xdebug.png
deleted file mode 100644
index a520462..0000000
Binary files a/img/web_xdebug.png and /dev/null differ
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..edc1fbd
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,34 @@
+site_name: Why cannot you set up Xdebug?
+site_author: Paul Radley
+site_description: Personal Blog
+site_dir: build
+site_url: https://paulradley.github.com/why-cannot-you-set-up-xdebug
+repo_url: https://github.com/paulradley/why-cannot-you-set-up-xdebug
+
+theme:
+ name: material
+ favicon: assets/favicon.svg
+ icon:
+ repo: fontawesome/brands/github
+ features:
+ - toc.follow
+
+plugins:
+ - git-revision-date-localized
+
+markdown_extensions:
+ - pymdownx.highlight:
+ anchor_linenums: true
+ line_spans: __span
+ pygments_lang_class: true
+ - pymdownx.inlinehilite
+ - pymdownx.snippets
+ - pymdownx.superfences
+ - admonition
+ - pymdownx.details
+
+extra_css:
+ - assets/extra.css
+
+nav:
+ - Why cannot you set up Xdebug?: index.md
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..fd6368d
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,33 @@
+Babel==2.14.0
+certifi==2023.11.17
+charset-normalizer==3.3.2
+click==8.1.7
+colorama==0.4.6
+ghp-import==2.1.0
+gitdb==4.0.11
+GitPython==3.1.41
+idna==3.6
+Jinja2==3.1.3
+Markdown==3.5.2
+MarkupSafe==2.1.3
+mergedeep==1.3.4
+mkdocs==1.5.3
+mkdocs-git-revision-date-localized-plugin==1.2.2
+mkdocs-material==9.5.4
+mkdocs-material-extensions==1.3.1
+packaging==23.2
+paginate==0.5.6
+pathspec==0.12.1
+platformdirs==4.1.0
+Pygments==2.17.2
+pymdown-extensions==10.7
+python-dateutil==2.8.2
+pytz==2023.3.post1
+PyYAML==6.0.1
+pyyaml_env_tag==0.1
+regex==2023.12.25
+requests==2.31.0
+six==1.16.0
+smmap==5.0.1
+urllib3==2.1.0
+watchdog==3.0.0
diff --git a/xdebug_en.md b/xdebug_en.md
deleted file mode 100644
index e7b9613..0000000
--- a/xdebug_en.md
+++ /dev/null
@@ -1,416 +0,0 @@
-# How does Xdebug work?
-
-
-
-- [Problem area](#problem-area)
-- [Operational principle](#operational-principle)
- * [Web mode](#web-mode)
- + [Trigger](#trigger)
- + [Xdebug hook and Trigger check](#xdebug-hook-and-trigger-check)
- + [Searching client's address and establishing a connection](#searching-clients-address-and-establishing-a-connection)
- + [Communication with the client](#communication-with-the-client)
- + [End of debugging](#end-of-debugging)
- * [CLI mode](#cli-mode)
- * [IDE](#ide)
- + [File mapping](#file-mapping)
- + [Project search](#project-search)
- + [PhpStorm integration](#phpstorm-integration)
- + [Visual Studio Code integration](#visual-studio-code-integration)
-- [Proxy](#proxy)
- * [DBGp Proxy](#dbgp-proxy)
- * [Xdebug Cloud](#xdebug-cloud)
-- [Troubleshooting](#troubleshooting)
- * [How to inspect a problem?](#how-to-inspect-a-problem)
- * [Debugging a CLI-application](#debugging-a-cli-application)
- * [Debugging an SPA-application](#debugging-an-spa-application)
- * [Debugging in other environments](#debugging-in-other-environments)
-
-
-
-## Problem area
-
-Setting up Xdebug requires interaction with several components in the development environment — client, server, IDE. The number of components and their potential working environment lead to complications in configuration process. Understanding how Xdebug works will reduce efforts on setting Xdebug up in any development environment.
-
-## Operational principle
-
-To begin with, let's start with PHP. In some perspective PHP applications could work in two modes:
-
-- Web mode — handling incoming HTTP requests from the browser
-
- Examples of stacks working with: nginx+fpm, nginx unit
-
-- CLI mode — direct execution from the terminal
-
- Examples of stacks working with: roadrunner, phpunit, horizon
-
-Xdebug works the same in these two modes. But for easy understanding we are going to examine them separately.
-
-### Web mode
-
-It is assumed that web server has already started and ready to handle HTTP requests. The illustration of HTTP request path from a client to PHP looks like the one below:
-
-
-
-> ℹ️ `...` — means the presence number of intermediate nodes that take place in the public network. They may not exist in the local development.
-
-Xdebug injects to that flow (note that the extension tries to connect back to the client):
-
-
-
-Let's examine this process step-by-step in more detail:
-
-
-
-> ℹ️ In that context, the client is local host. It has a running browser that sends HTTP request and the IDE that listens for incoming connections from Xdebug.
-
-1. The client sends an HTTP request with a trigger which means that this request must be debugged.
-2. Starting PHP script that receives and handles the request.
-3. The PHP engine in startup hooks runs Xdebug extension.
-4. Checking the presence of the trigger.
-5. Searching client's address.
-6. Attempts to establish connection with the client.
-7. Start of debugging: control transfer to the client, communication, waiting commands from the client.
-8. End of debugging due to stop command from the client or ending of script execution.
-
-#### Trigger
-
-The HTTP request must contain special trigger to initialize Xdebug session on the server side. The trigger is simple key+value pair: `XDEBUG_TRIGGER=` (legacy version is still working `XDEBUG_SESSION=`). This trigger must be part of the HTTP request from one of the possible options:
-
-- Cookie
-- Query param
-- Post payload
-
-The popular browser extension [Xdebug Helper](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc?hl=en) uses the Cookie approach to transfer the trigger.
-
-> ℹ️ `xdebug.trigger_value` setting allows for configuration a value that serves as the exact trigger for Xdebug extension. By default, trigger value could be anything.
-
-#### Xdebug hook and Trigger check
-
-The Xdebug extension integrates with the PHP lifecycle. So when PHP engine starts, startup hook of Xdebug checks the presence of the trigger. If there is no trigger, Xdebug extension doesn't attempt establishing a connection and PHP continues to work as usual.
-
-#### Searching client's address and establishing a connection
-
-If there was a positive check, Xdebug extension starts searching the client's address and establishes a connection with it.
-
-> ℹ️ In that context, the client is still the one who sent HTTP request
-
-The established connection with the client is a condition for the success of this step.
-
-The algorithm is based on checking potential clients' addresses until all are checked. Check consists of getting address from runtime-variable and bounding connection with it. In case of success, established connection is used. In case of failure, proceed to the next address. In case of consideration of all possible addresses, the last attempt with the reserved (from configuration) address performs.
-
-Here is an example of how Xdebug extension works with the applied configuration below:
-
-1. Establish a connection to the address from HTTP header `X-FORWARDED-FOR`
-2. Establish a connection to the address from environment `REMOTE_ADDR` (mostly used)
-3. _(reserved)_ Establish a connection to the address from Xdebug configuration (by default, it is `localhost`)
-
-If all attempts have failed, then PHP will continue to work as usual.
-
-> ⚠️ By default, checking addresses from runtime-variables is disabled, and Xdebug only looks at reserved address. The enabled setting could be used instead of hardcoding the client's address or in an environment with multiple developers.
-
-The using configuration:
-
-```ini
-; This is overridden behavior. By default, it is disabled
-xdebug.discover_client_host = true
-
-; This is used as reserved address
-xdebug.client_host = localhost
-; Xdebug always connects to the IDE on this port
-xdebug.client_port = 9003
-```
-
-> ℹ️ `xdebug.client_discovery_header` setting allows override of runtime-variables which will be checked as potential clients' addresses.
-
-#### Communication with the client
-
-The communication between Xdebug extension and an IDE occurs utilizing [DBGp](https://xdebug.org/docs/dbgp) protocol. This protocol aims to form communication between these units. As a result, the IDE is provided with familiar features like breakpoints, stacktrace, viewing variables in the debugging process.
-
-#### End of debugging
-
-The connection between the IDE with Xdebug extension breaks. PHP script completes the work.
-
-The next HTTP request that has to be debugged will go through this whole cycle.
-
-### CLI mode
-
-CLI application is run by the user. The illustration of injecting Xdebug to CLI call looks like one below:
-
-
-
-The communication is similar to the [Web mode](#web-mode) but with a few distinctions:
-
-1. Special trigger `XDEBUG_TRIGGER` must be passed as environment variable to initialize Xdebug session.
-
-2. Checking addresses from runtime-variables feature from [Searching client's address](#searching-clients-address-and-establishing-a-connection) section won't work in that mode. The easiest way to solve this problem is by using a reserved address from `xdebug.client_host` setting. The setting could be overridden at PHP startup time.
-
-Here is an example of running PHP in CLI with enabled Xdebug extension:
-
-```shell
-XDEBUG_TRIGGER=1 php -d xdebug.client_host= script.php
-```
-
-### IDE
-
-Apart from performing the main role of accepting connection from Xdebug and providing interactive debugging process, IDE also has to deal with two nontrivial issues — file mapping and searching the right project.
-
-#### File mapping
-
-As was mentioned before, Xdebug uses DBGp protocol that works in command-response manner — an IDE sends command (such as 'Step over') through that protocol and receives response with a new debugging state.
-
-Let's take it closer to the response of the 'Step over' command that steps to the next line of code. Pointer moves to line 42 in an IDE:
-
-
-
-Under the hood an IDE receives raw response from Xdebug:
-
-```xml
-
-
-
-
-```
-
-Look at the filenames. These filename paths are different from each other. The reason is that code runs in an isolated environment such as virtual machine or container. At the same time, an IDE controls code on the host side. So one of the IDE goals is to provide mapping between the local host path and the remote host path of the project for the proper functioning with Xdebug extension. For the above example, IDE must have configured mapping something like this:
-
-| | |
-|------------------|----------------------------|
-| Local host path | `/Users/macos/ez-project` |
-| Remote host path | `/home/vagrant/ez-project` |
-
-#### Project search
-
-
-
-Nowadays, a developer could work on multiple projects at the same time. As a consequence, several projects are open on the local machine. All of these opened projects wait for the connection from Xdebug. So the responsibility of an IDE is to correspond incoming Xdebug request with the right project.
-
-This problem is fully solved in PhpStorm and partially in Visual Studio Code. In the next section, the description will be provided.
-
-#### PhpStorm integration
-
-The integrated debugger of PhpStorm provides all default features. Phpstorm also solves the noticed issues above but in a slightly special way. Let's dive deeper.
-
-PhpStorm listens incoming connections from various remote servers. And when the IDE accepts a new connection, it has to route this connection to the right PhpStorm's project. Routing depends on the declared servers in all projects' settings:
-
-
-
-So PhpStorm uses the next algorithm to find the right project:
-
-
-
-1. Accepting a new connection.
-2. Calculating the identifier of the server (just a simple request to execute PHP code via DBGp Protocol). PhpStorm asks to execute expressions one by one until it gets the first non-empty result:
-
- - Executing `$_SERVER['PHP_IDE_CONFIG']`
-
- The result could be: `serverName=laradock`
-
- - Executing `$_SERVER['SERVER_NAME']` and `$_SERVER['SERVER_PORT']`
-
- The result could be: `ez-project.test` and `443`
-
- - Executing `$_SERVER['SSH_CONNECTION']`
-
- The result could be: `10.0.2.2 53500 10.0.2.15 22` (the last IP address and port number are used)
-
- 2.1. If all execution results have returned empty values, then the IDE can't identify the connection and asks the user to use `PHP_IDE_CONFIG` environment.
-
-
-
-3. Searching the project's Server that is capable to handle the incoming connection. The search depends on how the identifier has been found:
-
- - If `$_SERVER['PHP_IDE_CONFIG']` result has been set, then IDE performs a search for Server by its `Name`:
-
-
-
- - If `$_SERVER['SERVER_NAME']`/`$_SERVER['SERVER_PORT']` result or `$_SERVER['SSH_CONNECTION']` result have been set, then performs search for Server by its `Host` and `Port`
-
-
-
- 3.1. If 0 or more than 1 project have been found, then PhpStorm will offer to manually choose the right project.
-
-
-
- 3.2. PhpStorm will create Server if identifier has been found using other than `PHP_IDE_CONFIG` variable.
-
-4. The found (or selected) project is used for interactive debugging.
-
-The last step is to configure file mapping. As the Server has been created, there is a place where path mapping has to be specified:
-
-
-
-It also should set CLI interpreter up in PhpStorm and the same mapping to run and debug CLI scripts (like PHPUnit tests) from the IDE.
-
-> ℹ️ There are minor edge cases that are not described. But the information I've given is enough to understand the basics. Use it when setting up for an unfamiliar environment.
-
-#### Visual Studio Code integration
-
-The popular [PHP Debug Adapter](https://github.com/xdebug/vscode-php-debug) for Visual Studio Code brings all usual debugging process and file mapping via `pathMappings` setting in `launch.json`, except of working with multiple projects.
-
-The current solution assumes that only one project can listen for PHP Debug connections. For that reason, user has to manually change project that will be debugged.
-
-## Proxy
-
-> ℹ️ This section is dedicated to the related solutions that work in cooperation with Xdebug and could be profitable in a development environment. The content will be accompanied by examples of using with PhpStorm.
-
-Proxy allows to establish connection from debugger to IDE through intermediate node. That approach makes it available to:
-
-- Configure Xdebug easily
-- Debug an application with multiple users
-- Bypass network restrictions
-
-### DBGp Proxy
-
-[DBGp Proxy](https://xdebug.org/docs/dbgpProxy) is utility that runs on a node. It provides two features: partially cope with NAT and allow multiple users to debug an application simultaneously (on shared stage, for example).
-
-
-
-Setting up is split to 2 parts: configuration on server's side and configuration on client's side. Here is server's side configuration:
-
-1. Xdebug establishes a connection with DBGp Proxy. So PHP configuration must have the explicit address of DBGp Proxy tool in `xdebug.client_host` option.
-
- ```ini
- ; Disable auto discover
- xdebug.discover_client_host = false
- xdebug.client_host =
- xdebug.client_port = 9003
- ```
-
-2. DBGp Proxy tool starts on the node and listens new connections from Xdebug and IDE.
-
- ```shell
- ./dbgpProxy --server 0.0.0.0:9003 --client 0.0.0.0:9001
- ```
-
-For the client's side:
-
-1. Client's IDE sends request to DBGp Proxy tool. This request contains IDE key — unique identifier for DBGp Proxy tool that uses for routing Xdebug session to the right client.
-
-
-
-2. User prepares IDE key on the browser side and initiates debugging HTTP request. Trigger with the specific value must be set — `XDEBUG_TRIGGER=CLIENT_2`.
-
-
-
- Under the hood `XDEBUG_TRIGGER=CLIENT_2` will be sent as Cookie.
-
-When setup is complete DBGp Proxy will route debug session to the client's IDE by specified IDE key from client's HTTP request.
-
-> ⚠️ DBGp Proxy tool establishes new connections to IDE for incoming Xdebug requests. It means that the connection between DBGp Proxy and clients must not be affected by network restrictions.
-
-### Xdebug Cloud
-
-[Xdebug Cloud](https://xdebug.cloud/) is commercial product. It significantly simplifies installing process. Moreover, it affords to establish Xdebug session between nodes behind NAT and firewalls. Multi-user usage is also supported.
-
-
-
-Setting up workflow is small:
-
-1. Get the Cloud ID (register + pay)
-
-2. Put Cloud ID in configuration of PHP:
-
- ```ini
- xdebug.cloud_id = f0ec9529-184b-471c-bd20-c12b1bfa9258
- ; Timeout should be higher for the reliable connection
- xdebug.connect_timeout_ms = 1000
- ```
-
-3. Put Cloud ID in configuration of PhpStorm.
-
-
-
-That's all. It is the easiest way to set up Xdebug in any environment.
-
-> ⚠️ Be aware! Connection between PHP engine and Xdebug Cloud is not secured. DBGp protocol allows to execute any PHP code. So, in man-in-the-middle attack, attacker could gain full access to your system ([issue link](https://github.com/xdebug/xdebug/pull/646)).
->
-> For that reason use Xdebug Cloud at your own risk!
-
-## Troubleshooting
-
-There are a lot of guides about setting Xdebug up in the Internet. This section is purposed for setting in a nonstandard environments.
-
-### How to inspect a problem?
-
-If Xdebug does not connect to an IDE, follow this checklist to inspect a problem.
-
-1. Check that Xdebug extension is installed for FPM and CLI modes:
-
- ```shell
- php -v
- -> with Xdebug v3.2.1, Copyright (c) 2002-2023, by Derick Rethans
-
- php-fpm -v
- -> with Xdebug v3.2.1, Copyright (c) 2002-2023, by Derick Rethans
- ```
-
-2. Check the actual configuration of Xdebug:
-
- ```shell
- php -i | grep xdebug
-
- php-fpm -i | grep xdebug
- ```
-
-3. Inspect log file of Xdebug extension:
-
- - Enable logging in `xdebug.ini`:
-
- ```ini
- xdebug.log = /tmp/xdebug.log
- ```
-
-4. Inspect log file of PhpStorm:
-
- - Open: **Help** / **Diagnostic Tools** / **Debug Log Settings**
- - Add line and save: `#com.jetbrains.php`
- - Checkout the log file: **Help** / **Show Log in Finder/Explorer/Navigator**
-
-### Debugging a CLI-application
-
-That approach even works with an application that could produce workers that need to be debugged. Just add the trigger mark and don't forget to set the right client's address in the config:
-
-```shell
-XDEBUG_TRIGGER=1 php artisan horizon
-```
-
-There is an easier way to do it. PhpStorm solves that problem, so all you need is to add PHP script in the `Run` / `Edit configurations` and start debugging:
-
-
-
-### Debugging an SPA-application
-
-Mostly backend and frontend applications are located at different addresses. In that case, browser extension [Xdebug Helper](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc) doesn't send the debugging trigger to the backend. The main solution is to use the same domain for both applications.
-
-1. Edit configuration file of frontend application web-server. If [webpack](https://webpack.js.org/) is used, then edit `webpack.config.js`:
-
- ```javascript
- module.exports = {
- devServer: {
- // Use the same configuration block for the `vite.config.js`
- proxy: {
- '/api': {
- target: `${process.env.BACKEND_URL}`,
- changeOrigin: true,
- xfwd: false,
- },
- },
- ...
- ```
-
-2. Change backend address to the frontend application address in the client (usually, it is something like changing `BACKEND_URL` variable in `.env.local`)
-
-Now all request with `/api` prefix will be proxied to the backend. `XDEBUG_TRIGGER` trigger will be sent as Cookie.
-
-**Alternative solution:**
-
-1. Find the request for the debugging in the DevTool Network tab.
-2. Copy like `copy as cURL`.
-3. Paste it in the terminal and add to the end `-H 'Cookie: XDEBUG_TRIGGER=1`.
-4. Send the request.
-
-### Debugging in other environments
-
-Check out [Ultimate Guide](https://www.jetbrains.com/help/phpstorm/debugging-with-phpstorm-ultimate-guide.html) from JetBrains. There are a few cases of debugging in nonstandard environments (like via SSH tunnel).
-
-Also, more solutions to the real problems can be found there.
diff --git a/xdebug_ru.md b/xdebug_ru.md
deleted file mode 100644
index a5c9ae6..0000000
--- a/xdebug_ru.md
+++ /dev/null
@@ -1,520 +0,0 @@
-# Конфигурация Xdebug
-
-
-
-- [Проблематика](#%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)
-- [Принцип работы](#%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B)
- * [Web-приложение](#web-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5)
- + [Триггер](#%D1%82%D1%80%D0%B8%D0%B3%D0%B3%D0%B5%D1%80)
- + [Проверка триггера](#%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D1%82%D1%80%D0%B8%D0%B3%D0%B3%D0%B5%D1%80%D0%B0)
- + [Поиск адреса клиента и соединение](#%D0%BF%D0%BE%D0%B8%D1%81%D0%BA-%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%B0-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D0%B0-%D0%B8-%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5)
- + [Общение с клиентом](#%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%BC)
- + [Завершение сессии](#%D0%B7%D0%B0%D0%B2%D0%B5%D1%80%D1%88%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%B5%D1%81%D1%81%D0%B8%D0%B8)
- * [CLI-приложение](#cli-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5)
- * [Проксирование](#%D0%BF%D1%80%D0%BE%D0%BA%D1%81%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
- + [DBGp Proxy](#dbgp-proxy)
- + [Xdebug Cloud](#xdebug-cloud)
-- [Конфигурация](#%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F)
- * [Универсальная конфигурация Xdebug](#%D1%83%D0%BD%D0%B8%D0%B2%D0%B5%D1%80%D1%81%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F-xdebug)
- + [Local](#local)
- + [Vagrant](#vagrant)
- + [Docker](#docker)
- * [Особенности настройки в PhpStorm](#%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8-%D0%B2-PhpStorm)
- + [Запуск скриптов из IDE](#%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA-%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2-%D0%B8%D0%B7-ide)
- + [Обработка запросов пришедших в IDE](#%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0-%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2-%D0%BF%D1%80%D0%B8%D1%88%D0%B5%D0%B4%D1%88%D0%B8%D1%85-%D0%B2-ide)
-- [Частые проблемы](#%D1%87%D0%B0%D1%81%D1%82%D1%8B%D0%B5-%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D1%8B)
- * [Как инспектировать?](#%D0%BA%D0%B0%D0%BA-%D0%B8%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C)
- * [Cannot find file '/var/www/ez-project/index.php' locally](#cannot-find-file-varwwwez-projectindexphp-locally)
- * [Как запустить из CLI?](#%D0%BA%D0%B0%D0%BA-%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D1%82%D0%B8%D1%82%D1%8C-%D0%B8%D0%B7-cli)
- * [Отладка долгоиграющего приложения](#%D0%BE%D1%82%D0%BB%D0%B0%D0%B4%D0%BA%D0%B0-%D0%B4%D0%BE%D0%BB%D0%B3%D0%BE%D0%B8%D0%B3%D1%80%D0%B0%D1%8E%D1%89%D0%B5%D0%B3%D0%BE-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F)
- * [Отладка SPA приложения](#%D0%BE%D1%82%D0%BB%D0%B0%D0%B4%D0%BA%D0%B0-spa-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F)
-
-
-
-## Проблематика
-
-> Как снизить время разработчика на установку Xdebug?
-
-Конфигурация Xdebug требует вмешательства в работу нескольких компонентов рабочего окружения — клиент, сервер, IDE. Разнообразие этих компонентов и их возможных сред запуска усложняет процесс конфигурации. Понимание работы Xdebug позволит снизить временные затраты на его конфигурацию для любой среды.
-
-Данная статья содержит разделы, призванные решить обозначенную проблему. В ней содержится:
-
-- Принцип работы Xdebug
-- Универсальная конфигурация
-- Интеграция с PhpStorm
-- Частые проблемы
-
-## Принцип работы
-
-PHP приложения могут работать в двух режимах:
-
-- web режим — обработка входящих HTTP запросов из браузера.
-
- Примеры работы в связке с: nginx+fpm, nginx unit
-
-- cli режим — когда из терминала выполняется запуск.
-
- Примеры работы в связке с: roadrunner, phpunit, horizon
-
-Работа Xdebug для обоих режимов имеет общий алгоритм. Но для простоты понимания будем рассматривать их отдельно.
-
-### Web приложение
-
-Путь HTTP запроса проходит следующим образом:
-
-![request](./img/request.png)
-
-> `...` означают наличие промежуточных узлов, проходящих через публичную сеть. В локальной разработке обычно отсутствуют.
-
-В этот процесс внедряется отладка:
-
-![request_xdebug](./img/web_xdebug.png)
-
-Рассмотрим этот процесс подробнее:
-
-> Клиент в контексте статьи — это хост, на котором расположен браузер, отправляющий запрос и IDE, слушающее входящие соединения от Xdebug.
-
-1. Клиент отправляет запрос с меткой триггера, что этот запрос нужно отладить.
-2. Стартует PHP скрипт, который начинает обрабатывать HTTP запрос.
-3. PHP engine в стартовых хуках запускает Xdebug расширение
-4. Выполняется проверка наличия триггера.
-5. Происходит поиск адреса клиента.
-6. Попытка установки соединения с клиентом.
-7. Начало отладки: передача управления клиенту, общение и ожидания команд от клиента.
-8. Окончание отладки из-за команды остановки от клиента или при завершении работы скрипта.
-
-![session](./img/session.png)
-
-#### Триггер
-
-Для того чтобы инициировать Xdebug сессию, в HTTP запросе необходимо передать специальный триггер (метка). Эта метка состоит из пары ключ+значение: `XDEBUG_TRIGGER=<любое значение>` (легаси версия продолжает поддерживаться `XDEBUG_SESSION=<любое значение>`). Триггер необходимо передать одним из трех способов:
-
-- Cookie
-- Query-параметр
-- Post-нагрузка
-
-Популярное браузерное расширение [Xdebug hepler](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc?hl=en) передает триггер через Cookie.
-
-> С помощью опции `xdebug.trigger_value` можно конфигурировать значение, при котором будет срабатывать триггер. По умолчанию срабатывает на любое значение.
-
-#### Xdebug хук и Проверка триггера
-
-Расширение Xdebug встраивается в жизненный цикл PHP. Поэтому после старта PHP engine в стартап хуке Xdebug выполняется проверка наличия триггера. В случае его отсутствия Xdebug расширение не предпринимает попыток создания сессии и PHP продолжает работать в штатном режиме.
-
-#### Поиск адреса клиента и соединение
-
-После положительной проверки триггера выполняется поиск адреса клиента, с котором будет установленно соединение.
-
-> Клиентом в нашем контексте имеется ввиду, тот, кто изначально отправил HTTP запрос.
-
-Критерием успешности выполнения этого шага является успешная установка соединения с клиентом.
-
-Алгоритм основан на проверке всех потенциальных клиентских адресов. Сама проверка состоит из получения адреса из runtime-переменной и установки соединения с этим адресом. При успешной попытки используется это установленное соединение. При неудачной попытке происходит переход к следующему потенциальному адресу. В случае перебора всех возможных адресов происходит последняя попытка соединения с резервным адресом, указанным в конфигурации Xdebug.
-
-Пример работы Xdebug с примененной ниже конфигурацией:
-
-1. Соединение с адресом из HTTP заголовка `X-FORWARDED-FOR` (если используется load balancer)
-2. Соединение с адресом из переменной `REMOTE_ADDR` (используется в основном)
-3. (резервный) Соединение с адресом из конфигурации Xdebug (по-умолчанию `localhost`)
-
-Если все же не удалось установить соединение ни с каким адресом, то PHP продолжает работать как обычно.
-
-Конфигурация:
-
-```ini
-xdebug.client_discovery_header = "HTTP_X_FORWARDED_FOR,REMOTE_ADDR"
-; Это переопределенное поведение. По умолчанию, оно отключено
-xdebug.discover_client_host = true
-
-; Это резервное соединение
-xdebug.client_host = localhost
-xdebug.client_port = 9003
-```
-
-Обратите внимание, что расширение Xdebug подключается к IDE через порт 9003.
-
-#### Общение с клиентом
-
-Общение между Xdebug (отладчиком) и IDE (клиентом) выполняется по протоколу [DBGp](https://xdebug.org/docs/dbgp). Задача протокола согласовать общение между отладчиком и клиентом.
-
-Помимо обмена техническими параметрами, необходимые для установки соединения, в процессе общения Xdebug присылает информацию, сообщающую данные о текущей остановке скрипта. Рассмотрим подробнее:
-
-```xml
-
-
-
-
-```
-
-Остановка скрипта при отладке описывается двумя значениями: название файла и номер строки. В IDE это выглядит следующим образом:
-
-![Image](./img/xsession.png)
-
-Эти пути отличаются друг от друга. Причина в том, что код работает в другой среде, такой как виртуальная машина или контейнер. В то же время, для IDE файлы с кодом расположены на текущем хоста. Так что одна из задач IDE — обеспечить маппинг этих путей для корректной работы с Xdebug.
-
-#### Окончание отладки
-
-Соединение IDE с Xdebug расширением обрывается. PHP скрипт завершает работу.
-
-### CLI-приложение
-
-// TODO: картинка в режиме CLI
-
-Схема общения в отличие от web приложения практически идентична, но с небольшими отличиями:
-
-1. Вместо передачи `XDEBUG_TRIGGER` в HTTP запросе, эта переменная должны быть передана в качестве переменной окружения.
-2. Автоматический поиск адреса клиента с помощью переменных `HTTP_X_FORWARDED_FOR` и `REMOTE_ADDR` недоступен в этом режиме. Используйте `xdebug.client_host` с указанным адресом хоста
-
-Пример запуска PHP в CLI с включенным Xdebug расширением:
-
-```shell
-XDEBUG_TRIGGER=1 php -d xdebug.client_host= script.php
-```
-
-### Проксирование
-
-Проксирование позволяет подключение отладчика к IDE через промежуточный узел.
-
-#### DBGp Proxy
-
-[DBGp Proxy](https://xdebug.org/docs/dbgpProxy) — утилита, запускаемая на узле. Она позволяет частично преодолеть NAT, а также настроить отладку приложения между несколькими пользователями одновременно.
-
-![dbgp](./img/dbgp.png)
-
-Схема работы следующая:
-
-1. Запускается `DBGp Proxy` утилита, который слушает 2 сокета:
-
- - _(server)_ Соединения от PHP engine
- - _(client)_ Соединения от IDE
-
- ```shell
- ./dbgpProxy --server 0.0.0.0:9003 --client 0.0.0.0:9001
- ```
-
-2. В конфигурации PHP явно указывается адрес `DBGp Proxy` утилиты
-
- ```ini
- ; Отключение автообнаружения
- xdebug.discover_client_host = false
- xdebug.client_host = <адрес DBGp Proxy>
- xdebug.client_port = 9003
- ```
-
-3. IDE отправляет запрос в `DBGp Proxy`. Этот запрос содержит ключ IDE — уникальный идентификатор для DBGp Proxy утилиты, который используется для маршрутизации Xdebug сессии нужному клиенту.
-
- ![dbgp_register](./img/dbgp_register.png)
-
-4. DBGp Proxy утилита принимает запрос и регистрирует IDE (3 последних строчки):
-
- ```text
- ➜ ./dbgpProxy --client 0.0.0.0:9001 --server 0.0.0.0:9003
- 10:00:00 [dbgpProxy] Proxy started
- 10:00:00 [server] Started server server on 0.0.0.0:9003
- 10:00:00 [server] Started client server on 0.0.0.0:9001
- 10:00:12 [server] Start new client connection from 192.168.56.1:55708
- 10:00:12 [proxyinit] [CLIENT_2] Added connection for IDE Key 'CLIENT_2': 192.168.56.1:9003
- 10:00:12 [server] Closing client connection from 192.168.56.1:55708
- ```
-
-5. Пользователь подготавливает ключ IDE на клиентской стороне и инициирует отладку HTTP запроса. К примеру, установка IDE ключа в браузерном расширении Xdebug Helper:
-
- ![xdebug_helper_idekey](./img/xdebug_helper_idekey.png)
-
- Под капотом будет отправлена куки `XDEBUG_TRIGGER=CLIENT_2`
-
-Теперь `DBGp Proxy` будет маршрутизировать пришедшие сессии отладки в клиентские IDE по указанному ключу из HTTP запроса.
-
-> ⚠️ DBGp Proxy утилита устанавливает новые соединения с IDE на каждый запрос от Xdebug расширения. Это означает, ограничения сети не должны влиять на соединение между DBGp Proxy и клиентом.
-
-#### Xdebug Cloud
-
-[Xdebug Cloud](https://xdebug.cloud/) — коммерческий продукт. Его использование значительно упрощает процесс установки Xdebug. Более того, он позволяет устанавливать Xdebug сессии между узлами в обход NAT и фаерволов.
-
-![xcloud](./img/xcloud.png)
-
-Процесс установки простой:
-
-1. Получить Cloud ID
-
-2. Указать его в конфигурацию PHP
-
- ```ini
- xdebug.cloud_id = f0ec9529-184b-471c-bd20-c12b1bfa9258
- ; Следует повысить таймаут для надежного соединения
- xdebug.connect_timeout_ms = 1000
- ```
-
-3. Указать Cloud ID в конфигурации PhpStorm
-
- ![xdebug_cloud](./img/xdebug_cloud.png)
-
-Настройка завершена.
-
-> ⚠️ Имейте ввиду! Соединение между PHP engine и Xdebug Cloud не защищено. DBGp протокол позволяет выполнение любого PHP кода. Так, что в случае man-in-the-middle атаки, злоумышленник может получить полный доступ к вашей системе ([issue link](https://github.com/xdebug/xdebug/pull/646)).
-
-## Конфигурация
-
-### Универсальная конфигурация Xdebug
-
-В Интернете есть множество ответов с различным видением процесса отладки. С моей точки зрения (отладка в IDE только, когда браузерное расширение включено) только эти опции должны быть изменены, остальные должны быть нетронуты.
-
-> Настоятельно рекомендую использовать 9003 порт. Этот порт более уникален, в отличии старого 9000 порта, который может быть занят другими процессами.
-
-#### Local
-
-```ini
-xdebug.mode = debug
-
-xdebug.discover_client_host = false
-xdebug.client_host = localhost
-xdebug.client_port = 9003
-```
-
-#### Vagrant
-
-```ini
-xdebug.mode = debug
-
-xdebug.discover_client_host = true
-xdebug.client_port = 9003
-```
-
-#### Docker
-
-```ini
-xdebug.mode = debug
-
-xdebug.discover_client_host = false
-xdebug.client_host = host.docker.internal
-xdebug.client_port = 9003
-```
-
-### Особенности настройки в PhpStorm
-
-![phpstorm_xdebug](./img/phpstorm_xdebug.png)
-
-// TODO: нормальное объяснение — что-то вроде общей шины и работы над несколькими проектами.
-
-Помимо выполнения основной функции управления отладкой PhpStorm решает еще две нетривиальные проблемы — поиск проекта и маппинг файлов. Сложность со стороны IDE заключается в том, что у пользователя открыто множество проектов, настроено несколько окружений (локальное, vagrant, docker, ssh). Задача IDE является соотнести пришедший на отладку запрос с запущенным проектом и выполнить маппинг локальных файлов с файлами, находящимися на удаленной машине.
-
-Для комфортной работы разработчику необходимо выполнить обе настройки, о которых говорится далее.
-
-#### Запуск скриптов из IDE
-
-// TODO: картинка в запуском тестов
-
-В этом режиме PhpStorm'у уже известен проект и его поиск не требуется. При запуске отладки необходимо указать (удаленный) интерпретатор и установить корректный маппинг:
-
-- `Settings` — `PHP` — `CLI Interpeter` — выбрать хост с удаленной машиной ([Check Xdebug installation](https://www.jetbrains.com/help/PhpStorm/configuring-xdebug.html#integrationWithProduct))
-- `Settings` — `PHP` — `Path mappings` — настроить (убедиться в наличии) соответствия путей на локальной машине и удаленной. Пример в таблице ниже
-
-| | |
-|-----------------------------|----------------------------|
-| Путь на хосте | `/Users/macos/ez-project` |
-| Путь в виртуалке/контейнере | `/home/vagrant/ez-project` |
-
-Теперь вы сможете запускать PHP скрипты из IDE, например запуск PHPUnit тестов:
-
-// TODO: картинка
-
-#### Обработка запросов пришедших в IDE
-
-В этом режиме PhpStorm'у неизвестен ни проект, ни маппинг. IDE в этом случае сначала выполняет поиск проекта по следующему алгоритму:
-
-1. IDE принимает соединение
-2. IDE вычисляет идентификатор соединения. По DBGp протоколу PhpStorm вычисляет значения:
-
- - `$_SERVER['PHP_IDE_CONFIG']`
-
- Пример: `serverName=laradock`
-
- - `$_SERVER['SERVER_NAME']`
-
- Пример: `ez-project.test`
-
- - `$_SERVER['SSH_CONNECTION']`
-
- Пример: `10.0.2.2 53511 10.0.2.15 22`
-
-3. IDE ищет проект, в который необходимо маршрутизировать соединение
-
- - Если `$_SERVER['PHP_IDE_CONFIG']` установлен, то выполняется поиск `Server` по его `Name`
-
- ![laradock](./img/laradock.png)
-
- - Если `$_SERVER['SERVER_NAME']` или `$_SERVER['SSH_CONNECTION']` установлены, то выполняется поиск `Server` по его `Host` и `Port`
-
- ![host_port](./img/host_port.png)
-
- - Если ни одна из переменных не установлена, то IDE не сможет идентифицировать соединение
-
- ![none](./img/none.png)
-
-4. Если проект не найден, то IDE предложит вручную выполнить маршрутизацию в проект
-
-// TODO: картинка ручного выбора проекта
-
-// TODO: примечание, что для Docker'а обычно используется — PHP_IDE_CONFIG, а для vagrant — SSH_CONNECTION
-
-**Для того чтобы настроить конфигурацию, необходимо:**
-
-1. Выполнить первый HTTP запрос с включенным дебагом
-2. Выбрать предложенный IDE проект и файл
-3. Зайти в `Settings` — `Servers` — Выбрать созданный `Server`
-4. Выбрать `Use path mappings`
-5. Напротив пути к локальному пути прописать путь к проекту в виртуалке/контейнере
-
-| | |
-|-----------------------------|-------------------------------------|
-| Путь на хосте | `/Users/macos/projects/ez-project` |
-| Путь в виртуалке/контейнере | `/home/vagrant/projects/ez-project` |
-
-## Частые проблемы
-
-### Как инспектировать?
-
-1. Проверить, что для CLI и FPM режимов Xdebug подключен
-
- ```shell
- php -v
- -> with Xdebug v3.2.1, Copyright (c) 2002-2023, by Derick Rethans
-
- php-fpm8.2 -v
- -> with Xdebug v3.2.1, Copyright (c) 2002-2023, by Derick Rethans
- ```
-
-2. Если расширение отсутствует, то попробовать установить через:
-
- ```shell
- # Включение
- phpenmod xdebug
- # Обязательна перезагрузка fpm после включения
- sudo systemctl restart php-fpm
- # Возможна вариация
- sudo systemctl restart php8.2-fpm
- ```
-
- Либо `pecl`, либо любые другие способы из Интернета
-
-3. Проверить конфигурацию для CLI и FPM режимов, что она совпадает с [Универсальная конфигурация Xdebug](#Универсальная конфигурация Xdebug)
-
- ```shell
- php -i | grep xdebug
-
- php-fpm -i | grep xdebug
- ```
-
-// TODO: поиск файла с конфой
-4. Если заявленная конфигурация отличается от фактической, возможно в папке `conf.d` могут содержаться несколько конфигураций Xdebug. Приоритет конфигураций над последним загруженным.
-
- Также имена конфигурационных файлов могут содержать числа-префиксы, необходимые для указания порядка загрузки (сравнение строк по символам ASCII). Приоритет для двух файлов `20-xdebug.ini` и `xdebug.ini` будет:
-
- - `20-xdebug.ini`
- - `xdebug.ini` — директивы из ранее загруженных файлов будут переопределены
-
-5. Если Xdebug не соединяется с IDE, то проинспектировать логи:
-
- - Включить логи, добавив в `xdebug.ini`:
-
- ```ini
- xdebug.log = /var/log/xdebug.log
- ```
-
- - Добавить файл с логом и правами
-
- ```shell
- sudo touch /var/log/xdebug.log
- sudo chmod 666 /var/log/xdebug.log
- ```
-
-// TODO: inspect xdebug in IDE
-
-6. Остальные проблемы см. официальной документации [Troubleshooting common PHP debugging issues](https://www.jetbrains.com/help/PhpStorm/troubleshooting-php-debugging.html) либо гугл.
-
-### Cannot find file '/var/www/ez-project/index.php' locally
-
-> Cannot find file '/var/www/ez-project/index.php' locally.
-> To fix it set server name by environment variable PHP_IDE_CONFIG and restart debug session.
-
-Убедиться в наличии одной из переменных из раздела [Обработка запросов пришедших в IDE](./Обработка запросов пришедших в IDE)
-
-### Как запустить из CLI?
-
-Для запуска из CLI необходимо убедиться, что адрес IDE будет определен верно. В случае с универсальной конфигурацией для локальной машины и docker-окружения необходимо запустить:
-
-```shell
-XDEBUG_TRIGGER=1 php artisan tests
-
-# При необходимости передать конфиг, по которому будет идентифицирован сервер
-PHP_IDE_CONFIG='serverName=SomeName' XDEBUG_TRIGGER=1 php artisan tests
-```
-
-Для Vagrant используйте:
-
-```shell
-XDEBUG_TRIGGER=1 php -d xdebug.client_host=10.0.2.2 artisan tests
-```
-
-### Отладка долгоиграющего приложения
-
-Отладка долгоиграющего приложения усложняется, если оно порождает воркеров. Для отладки кода, исполняемого воркером, используйте:
-
-1. В начале кода, который необходимо отладить, вызовите функцию:
-
- ```php
- xdebug_connect_to_client();
- ```
-
-2. Запустите долгоиграющее приложение со специальным флагом:
-
- ```shell
- php -d xdebug.start_with_request=no artisan horizon
- ```
-
-### Отладка SPA приложения
-
-Работа с SPA приложением подразумевает расположение фронтенд и бэкенд приложений на разных адресах. В этом случае при работе клиентского приложения, браузерное расширение [Xdebug Helper](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc) не будет отправлять триггер отладки при отправке запроса на бэкенд. Решение заключается в расположении фронтенд и бэкенд приложений на одном адресе:
-
-1. Необходимо в конфигурации веб-сервера, который отдает фронтенд, внести правки:
-
- В случае, если используется webpack, то в `webpack.config.js`:
-
- ```javascript
- module.exports = {
- devServer: {
- proxy: {
- '/api': {
- target: `${process.env.BACKEND_URL}`,
- changeOrigin: true,
- xfwd: false,
- },
- },
- ...
- ```
-
- В случае, если используется vite, то в `vite.config.js`
-
- ```javascript
- export default defineConfig({
- server: {
- proxy: {
- '/api': {
- target: `${process.env.BACKEND_URL}`,
- changeOrigin: true,
- xfwd: false,
- },
- },
- ...
- ```
-
-2. В клиентском приложении переопределить адрес бэкенда на адрес фронтенда (обычно что-то вроде изменения переменной `BACKEND_URL` в `.env.local`).
-
-Теперь все запросы с префиксом `/api` будут проксироваться на бэкенд, заголовок `Cookie` с меткой триггера тоже будет передан.
-
-**Альтернативный вариант:**
-
-1. В DevTools во вкладке `Networks` найти запрос для отладки
-2. Скопировать его как `copy as cURL`
-3. Вставить в терминал и добавить к нему `-H 'Cookie: XDEBUG_TRIGGER=1`
-4. Отправить запрос