A room similar to workshop visible. Instead of the tools, on shelves there are logos of different programmes and technologies like docker, ubuntu, ngnix. At the center of the picture there is laptop with Drupal logo on the screen

IDE and Linux configuration with PHP and Drupal

Projects implemented by Droptica often require a large amount of coding in PHP. Taking advantage of various tool and configurations allows us to streamline the process and make it far more convenient and pleasant. In this post, we wanted to share our experiences and describe an ideal software configuration for coding in PHP (mainly in Drupal, since we are a Drupal agency). The base software that we use includes Linux (most people use Ubuntu) and PHPStorm as IDE. We also use Docker for setting up and running services like Apache, MySQL, Solr, etc.

Docker instead of locally installed Apache and PHP

Many web developers prefer installing a full LAMP stack on their local server, with Apache/MySQL and PHP installed on top of Linux. This is not a bad solution, but such a local installation is always going to be different from the client’s server environment. And in this case, the more differences, the more work and potential conflicts you will face, along with the “works for me” responses. :-)

Docker offers a nice solution to this issue, as it allows you to run identical server configurations in both development and production environments. However, the most crucial advantage of Docker is the fact that the developer is no longer required to manually configure all the .conf and .ini files. Thanks to Docker, you can focus on coding and leave all the server matters in the hands of experts.

At Droptica, we use a custom piece of software called docker-console, which allows our developers to quickly start a new or existing project in Drupal. Tools such as Composer, Drush, Sass/Compass are in their containers and they work without the need to install them locally on the developer’s machine. Usually, they also have a range of tools for making debugging easier at their disposal. One of such tools is Mailcatcher, which catches all the e-mails sent by Drupal.

Nginx proxy for Docker

The nginx proxy image for Docker allows for using hosts (local domains) in order to display websites running on Docker in a web browser. In short, thanks to nginx proxy, we can type in http://www.droptica.local instead of an IP address (for example: "172.17.0.4".) Nginx proxy is very useful when we are running a Drupal multisite and there are multiple domains under a single container’s IP address (e.g. sites/droptica.com, sites/droptica.pl).

Installing nginx proxy:

1. Before installation, make sure to remove all the existing versions of nginx proxy. Depending on the name, it is going to look more or less like:

docker stop ngnix-proxy && docker rm ngnix-proxy

2. Clone the repository: https://github.com/droptica/nginx-proxy 

3. Enter the repository directory and run it using the command:

docker-compose up -d

4. Check nginx IP, if the address changed, change it in the /etc/hosts file:

docker inspect --format "{{ .NetworkSettings.IPAddress }}" nginx-proxy

5. If you want to add https for a xxx.local domain, copy default.crt and default.key files to xxx.local.crt and xxx.local.key. It is possible that you will have to do chmod 777 on them and then restart the nginx container:

sudo chmod 777 -Rf certs && docker-compose restart

6. Add the code responsible for https to the configuration file (example for the xxx.local domain):

if (strpos($_SERVER['SERVER_NAME'], 'xxx') !== FALSE) {
  $base_url = 'https://'.$_SERVER['SERVER_NAME'];
  $conf['https'] = TRUE;
}

7. When the machine runs something on port 80 (apache/nginx), comment the following lines in docker-compose.yml:

ports:
  - 80:80 
  - 443:443 

8. Docker compose version 2 and higher with nginx-proxy. On versions newer than 1, docker-compose sets private network for the containers, and because of that nginx-proxy cannot connect to it by default. In order to get it running, you have to find out the network and add it manually.

# list networks
docker network ls

# connect you nginx_proxy to your network
docker connect you_network_name nginx_proxy

PHP CodeSniffer

PHP CodeSniffer is a very useful tool, which helps you maintain clear codebase, conforming to standards. As you can read in the Readme file, CodeSniffer is made up of two scripts. One is used for detecting violations of a defined coding standard (phpcs), and the other is used to automatically correct coding standard violations (phpcbf).

PHPStorm, however, only allows you to use the former one (phpcs). After configuration, all the lines containing code violating the standard will be highlighted in the currently edited file.

In order to be able to use PHP CS, you have to install it first, for example by using Composer or in any other way described in the project’s README file.

For instance:

composer global require "squizlabs/php_codesniffer=*"

If you did not add the $HOME/.composer/vendor/bin path to your $PATH variable, you should do it now. To do this, in the case of Linux, add the following line at the end of the ~/.bashrc file:

export PATH="$PATH:$HOME/.composer/vendor/bin"

The Composer path can be slightly different for your Linux distribution (~/.config/composer for Ubuntu 18.04). In order to apply the changes, log out and log back in or execute the following command:

source ~/.bashrc

Another thing that you have to do is adding Drupal coding standards to PHP CS. Simply install the coder module.

The easiest way to do it is by using Composer:

composer global require drupal/coder

The detailed installation instructions can be found here: https://www.drupal.org/node/1419988

Before you move on to the next step, make sure that there is no second instance of PHP CS installed anywhere in the system, you can do this by executing the following command:

whereis phpcs

It should return an output that is similar to the one below:

phpcs: /home/<username>/.composer/vendor/bin/phpcs

If the command returns more locations, you should get rid of the unnecessary versions, so that only one remains on your machine.

Then, register Drupal standards from the coder module:

phpcs --config-set installed_paths ~/.composer/vendor/drupal/coder/coder_sniffer

After installing PHP CS and Coder in the system, you can move on to configuring PHPStorm:

Settings → Languages & Frameworks → PHP → Quality Tools → Code Sniffer

In the “Development environment” section, click three dots next to the “Configuration” option.

PHPStorm window visible. There is box with "local" text inside and an arrow. Further right there is a button with three dots on it

In the Code Sniffer window, provide the path to the phpcs script (the one returned by the whereis phpcs command) in the “PHP Code Sniffer (phpcs) path” for the “Local” configuration.

A path to the "Local" configuration pasted in the box in the upper right corner of the window

After entering the path, click Validate in order to make sure that PHP CS works fine. If everything works, you should see the following message on a green background:

Validated file. The label "ok, PHP_CodeSniffer version 3.0.2 (stable) by Squiz (http://squiz.net) visible on the green background, as described in the text.

Then, turn on inspecting code by Code Sniffer. You can do it by going to the settings:

Settings → Editor → Inspections 

Select PHP → Quality Tools from the list of languages, and then turn on PHP Code Sniffer validation. After ticking the checkbox, refresh the list of available coding standards A PHPStorm "reload icon" and then choose Coding standard →Drupal

Drupal Coding standards chosen in PHPStorm settings

After applying the settings, you can open a PHP file and check how Code Sniffer works.

Xdebug (working on every project)

XDebug enables debugging web applications developed in PHP in a “classic” style, using breakpoints and running code line-by-line. XDebug is fully compatible with PHPStorm, and connecting the IDE to the debugger is very simple. 

Regardless of whether you use docker or set up the entire environment all by yourself, XDebug should broadcast information about the scripts on port 9000. In order to make PHPStorm listen to this port, click “Run → PHPStorm "Start listening" icon Start listening for PHP Debug Connections”. After refreshing the debugged page in the editor, a window will open, confirming that the connection with XDebug has been successfully established. Sometimes it may be necessary to adjust directory mapping between the server’s webroot and project directory in PhpStorm.

If the connection was not established properly, first make sure that XDebug works at all (by running php --version or phpinfo()). Then check whether you need any bookmarklets (specially prepared links added to bookmarks) activating debugging. You can find them at https://www.jetbrains.com/phpstorm/marklets/ 

A very good and in-depth manual regarding connecting XDebug and PHPStorm is available here:

https://confluence.jetbrains.com/display/PhpStorm/Zero-configuration+Web+Application+Debugging+with+Xdebug+and+PhpStorm 

XDebug plug-in for Chrome/Firefox

There are many plug-ins available, just install it, enable it for a given page and enjoy the possibilities offered by XDebug.

Some examples:

MySQL Workbench

A piece of software for managing MySQL databases. It allows you to import and export databases, view tables, as well as query databases, regardless of whether they are local, in docker or remote via ssh. It does not have any limits regarding the size of an imported database (compared to the default PHPMyAdmin configuration).

The packages can be downloaded at https://dev.mysql.com/downloads/workbench/, after downloading just install them.

Chrome plug-in for JS debugging

The add-on is available for Chrome only:

https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji 

Code formatting in PHPStorm:

Drupal has a very specific code formatting standards. Some of the most important things to remember are indent of two spaces, as well as putting else/elseif/catch/while always in a new line. PHPStorm is compatible with Drupal out of the box.

Simply go to Settings → Editor → Code Style → PHP and select Set From → Predefined Style → Drupal. Do not forget about formatting settings for CSS, JS, SASS/LESS.

A drop-down menu of described configuration visible. The cursor highlights Drupal among the others visible on the list

Additional PHPStorm configuration

Below you can find some additional PHPStorm configuration options, which also make your work easier by automatically formatting your code according to the accepted standards:

Automatically adding an empty line at the end of the file when saving: 
Settings → Editor → General, select Ensure line feed at file end on Save

Automatically removing white spaces at the end of the lines when saving the file.
Settings → Editor → General, change Strip trailing spaces on Save, select 'All'.

You can also choose ‘Modified Lines’ if you do not want white spaces to be removed from other places in the code, which were not modified. Automatically formatting the code after typing in the closing curly bracket.
Settings → Editor → General → Smart Keys, select Reformat block on typing '}'

Summary

The above article features our current recommendations. They are different now from what we recommended a year or two ago, and they will probably be different in the future – the configuration will get even better. :)

Is there anything that we should improve in your opinion? Perhaps you have your own way to configure your development environment? Share your insights and ideas in the comments!

3. Best practices for software development teams