Tag Archives forcli

XDebug for PHPUnit in Docker with PHPStorm

[ update ] Set the IP-address to the following DNS-name: docker.for.mac.localhost (yes, literally)!
Working with the IP-address doesn’t work anymore
[ /update ]

Want to get XDebug working for your PHPUnit tests which run in Docker? Or for behat? Or any other CLI application? Follow me!

Roughly this is what you’ll need to do: Continue reading

Watch files and execute command upon change

Find yourself executing the same command over and over again after applying changes to certain files? Pywatch will be you best friend!

Meet pywatch: a cool little app that watches directories and files. Whenever it finds a file that changed, it executes the command you provided.


As an example; I use this to build a Docker image whenever I save a change to my Dockerfile.

pywatch "docker build . -t pauledenburg/behat" Dockerfile

Or execute tests whenever I make a change to one of the sourcefiles.

commandToExecute='docker exec -i hangman_app_1 behat -c tests/behat/behat.yml'
find ./tests -name "*.php" -o -name "*.feature" \
  | xargs pywatch "$commandToExecute"

This keeps an eye on all *.php and *.feature files under ./tests.

When one of these files changes, it executes $commandToExecute which resolves to executing behat in a Docker container.


Download the pywatch app from github: https://github.com/cmheisel/pywatch.

Then unzip and install with python.

unzip pywatch-master.zip
cd pywatch-master
sudo python setup.py install

Advanced usage

Nice one: run tests when files change and create a Mac notifier whenever the tests fail.

This way you can keep the tests running in the background and you’ll be notified whenever a test failed.

find src tests -name "*.php" -o -name "*.feature" \
  | xargs pywatch "./dev test phpunit" \
  | grep "([0-9]* failed)" \
  | sed -e 's/.*(\([0-9]* failed\)).*/\1/' \
  | while read failure; 
      terminal-notifier -message "Test output: $failure" -title "Tests Failed!"



Free SSL certificates with LetsEncrypt

Getting your website on https can be done in a matter of minutes. So there is no excuse anymore to go without it. Not even on your test and dev websites.

As this example is on CentOS, it really goes for any other linux distro.

Excellent, tailor-made instructions per webserver and OS are found on the website of Certbot:

Here, a short recap of that for my own archive.

You’ll need the repel repository for this. After that, install the certbot software.

$ sudo yum install epel-release
$ sudo yum install certbot-nginx


Getting your website secured with SSL is now as simple as answering some questions on the following command.

Note: I’m using a method which takes a bit of downtime because LetsEncrypt is in the middle of an update. Read all about it

$ sudo certbot --authenticator standalone --installer nginx --pre-hook "service nginx stop" --post-hook "service nginx start"

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer nginx
Which names would you like to activate HTTPS for?
1: yoursite.pauledenburg.com
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 2

Running pre-hook command: service nginx stop
Error output from service:
Redirecting to /bin/systemctl stop nginx.service
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for es.git.innospense.com
Waiting for verification...
Cleaning up challenges
Running post-hook command: service nginx start
Error output from service:
Redirecting to /bin/systemctl start nginx.service
Deployed Certificate to VirtualHost /etc/nginx/sites-enabled/yoursite.pauledenburg.com.conf for set(['yoursite.pauledenburg.com'])
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/yoursite.pauledenburg.com.conf
Congratulations! You have successfully enabled https://yoursite.pauledenburg.com
You should test your configuration at:
 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2018-04-24. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le


Things which might throw you an error

python-urllib3 version

First caveat for CentOS7 is that you need specific version 1.21 for urllib3. I had 1.22 installed via yum which gave me the following error.

ImportError: No module named 'requests.packages.urllib3'

You can see the currently installed version with pip:

pip freeze | grep urllib

To resolve this, first remove the old version it with yum and then add it with pip:

sudo yum remove python-urllib3 
sudo pip install -Iv https://github.com/shazow/urllib3/archive/1.21.1.tar.gz

pyOpenSSL version

Just like urllib3, pyOpenSSL was of an unsupported version.

sudo yum remove pyOpenSSL
sudo pip install pyOpenSSL

Error message stating that the CA can’t be satisfied

After running

certbot --nginx

you get the following error:

Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.

Due to legal reasons there currently is no

From the github certbot website:

If you’re serving files for that domain out of a directory on Nginx, you can run the following command:

# Webroot method
$ sudo certbot --authenticator webroot --installer nginx \
  --webroot-path <path to served directory> -d <domain>

If you’re not serving files out of a directory (for instance if you are using proxy_pass), you can temporarily stop your server while you obtain the certificate and restart it after Certbot has obtained the certificate. This would look like:

# Temporary outage method
$ sudo certbot --authenticator standalone --installer nginx \
  -d <domain> --pre-hook "service nginx stop" --post-hook "service nginx start"


Disable xdebug for one run

This script disables xdebug for one run. No more error-messages like:

$ composer update
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug


$ php-cs-fixer fix --dry-run .
You are running PHP CS Fixer with xdebug enabled. This has a major impact on runtime performance.
If you need help while solving warnings, ask at https://gitter.im/PHP-CS-Fixer, we will help you!

This is what you’ll get

We’ll create a script which will:

  • disable xdebug
  • run your command
  • enable xdebug

the script we’ll name php-no-xdebug (or whatever you like)

With Xdebug (note the last line)

$ php --version
PHP 7.1.10 (cli) (built: Oct  6 2017 01:08:19) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans

Without Xdebug (note the missing last line)

$ php-no-xdebug --version
PHP 7.1.10 (cli) (built: Oct  6 2017 01:08:19) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

The script php-no-xdebug

Create the script /usr/local/bin/php-no-xdebug with the following contents.

# file /usr/local/bin/php-no-xdebug

php=$(which php)

# get the xdebug config
xdebugConfig=$(php -i | grep xdebug | while read line; do echo $line; exit; done)

# no xdebug? Nothing to do!
if [ "$xdebugConfig" == "" ]; then
    $php "$@"

# get the configfile (which should be the first value)
# so strip off everything after the first space of the xdebug-config
xdebugConfigFile=$(php -i | grep xdebug | while read line; do echo $line; exit; done)

# test whether we got it right
if [ ! -f "$xdebugConfigFile" ]; then
    echo "No XDebug configfile found!"
    exit 1

# disable xdebug by renaming the relevant .ini file
mv ${xdebugConfigFile}{,.temporarily-disabled}

# dissect the argument to extract the first one (which should be a script or an application in $PATH) from the rest
for arg in $(echo $@ | tr ' ' "\n")
    if [ "$index" == "0" ]; then
      restArg="$restArg $arg"


# check whether the command to be executed is a local PHP file or something in the $PATH like composer or php-cs-fixer
fullPath="$(which $firstArg)"
if [ "$fullPath" == "" ]; then
    # check whether it's a local file
    if [ ! -f  $firstArg ]; then
        echo "Could not find $firstArg. No such file or directory"
        exit 1
        # just run the commands
        $php $@
    # run the command with the fullpath followed by the rest of the arguments provided
    $php $fullPath $restArg

# execute the command
$php "$@"

# re-enable xdebug
mv ${xdebugConfigFile}{.temporarily-disabled,}

# test whether the conf file is restored correctly
if [ ! -f "$xdebugConfigFile" ]; then
    echo "Something went wrong with restoring the configfile for xdebug!"
    exit 1

and make it executable

$ chmod +x /usr/local/bin/php-no-xdebug

That’s it! Run it like this:

$ php-no-xdebug composer update

Switch between multiple PHP versions on your mac

This article is a slimmed-down, firing-from-the-hips, get right to the action version based on the ones listed below. If you miss some background info or want a more spelled out version, please do visit these articles:

  • https://getgrav.org/blog/macos-monterey-apache-multiple-php-versions

Install multiple PHP

If you want to install deprecated versions of PHP (< PHP7.2), then you’ll need to add this tap to homebrew:

brew tap shivammathur/php
#versions=(php@7.2 php@7.3 php@7.4) # in ZSH
versions="php@7.2 php@7.3 php@7.4 php@8.0 php@8.1" # in bash
for version in $versions; do
    echo "installing ${version}"
    brew install shivammathur/php/${version}

# install xdebug for php >= 7.2
pecl uninstall -r xdebug
pecl install xdebug

If you receive the error configure: error: Cannot find libz you need to install required libraries via XCode:

xcode-select --install 
brew upgrade

Install easy switch-script

To easily switch PHP versions, install the following script.

curl -L https://gist.githubusercontent.com/rhukster/f4c04f1bf59e0b74e335ee5d186a98e2/raw > /usr/local/bin/sphp
$ chmod +x /usr/local/bin/sphp

As I don’t add Apache on my host machine, change
apache_change=1 to apache_change=0 in the script.

vi `which sphp`

Switch PHP-version

Without arguments, this command returns useful information like which versions are installed and which is the active one right now:

$ sphp 7.4
If you need to enter your administrator password, then you probably need to disable the part where Apache is restarted (see chapter above).
Switching to php@7.4
Switching your shell
Unlinking /usr/local/Cellar/php@5.6/5.6.40... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.0/7.0.33... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.1/7.1.33... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.2/7.2.31_1... 0 symlinks removed
Unlinking /usr/local/Cellar/php@7.3/7.3.19... 25 symlinks removed
Unlinking /usr/local/Cellar/php/7.4.7... 0 symlinks removed
Linking /usr/local/Cellar/php/7.4.7... 24 symlinks created

PHP 7.4.7 (cli) (built: Jun 12 2020 00:04:10) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies

All done!

NOTE FOR XDEBUG: if you want to use xdebug you’re switch command needs to be expanded to:

sphp 7.4 && pecl uninstall -r xdebug && pecl install xdebug

Now you’ll see that xdebug is enabled for PHP:

php -v
PHP 7.4.7 (cli) (built: Jun 12 2020 00:04:10) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans
    with Zend OPcache v7.4.7, Copyright (c), by Zend Technologies

That’s it!

Again; take a look at the great, kept up-to-date, article of Andy Miller over at his website: https://getgrav.org/blog/macos-monterey-apache-multiple-php-versions