Multiple computers, the benefit

A shot of multiple devices and computers

Multiple computers can help you find more bugs in your Apps

I have a few computers that I use, most people would say too many, for me though, it works. Having multiple computers gives me the freedom to work in more than one location. I have my main desktop in my office, my old still usable desktop in my wife’s office space and two laptops, a Surface Book and a Macbook Pro. Both the Macbook Pro and Surface Book are a little long in the tooth, but they still work well enough for when I need to take a machine onsite for freelance or contract work.

Why am I mentioning I have a use multiple PCs, well, there are a whole host of development problems that you solve because you use multiple machines. Additionally, because I use multiple machines, I tend to make fewer changes to my setup than I used to. Other than my IDE of choice and Docker, my setup is simple, this makes it easier to replicate across my computers.

What is the gain?

So, what is the gain? Well, you can only use multiple PCs if your Apps are setup on each of them, this is the benefit, because you have to setup each App more than once you quickly get to spot any issues, if you added an extension when you developed a feature, boom, you’ll notice, if it isn’t easy to get your tests to run, boom you’ll notice. It also gives you the opportunity to test the first install process for your Apps, you’ll quickly notice the necessary data you added outside of a migration or the path that isn’t mapped.

Yes, having multiple computers is a luxury, the thing is though, keep your old stuff, it is more functional than you realise.

If you don’t have multiple machines, you can always use someone else’s, add an account to your partner, child’s, siblings, or parents’ computer, with their permission of course. Even if you only rarely setup one of your projects on another machine, you are bound to spot an issue you didn’t know existed.

Simpler than years ago

These days tools like Docker have solved a lot of the problems we used to experience but I still think you will find an issue or two when you setup an App fresh on another computer, especially if that App has been in development for a while or moved beyond basic functionality.

My typical project setup for Laravel

Laptop with movie style code

This is one of those posts that is more of a reference for me rather than general information, if however, you use PHP, Docker, MySQL, Windows, WSL2 and PHPStorm this post about my typical project setup may be of interest to you.

Docker and WSL 2

I use Docker, specifically docker compose. Typically, I define two services in the docker-compose.yml file, [project_name].app and [project_name].mysql. If the project is part of a service I will define a network, this is to make it easier for containers to communicate. All the Costs to Expect Apps rely on the Costs to Expect API so they all share the same network.

Below is an example of a docker-compose.yml file for Budget, our free budgeting tool.

version: '3'
services:
    costs.budget.app:
        build:
            context: .
            dockerfile: .docker/app/Dockerfile
        image: costs.budget.app
        container_name: costs.budget.app
        ports:
            - "80:80"
        volumes:
            - .:/var/www/html
        env_file: .env
        environment:
            TZ: UTC
            DB_HOST: ${DB_HOST}
            DB_DATABASE: ${DB_DATABASE}
            DB_USERNAME: ${DB_USERNAME}
            DB_PASSWORD: ${DB_PASSWORD}
    costs.budget.mysql:
        build:
            context: .
            dockerfile: .docker/mysql/Dockerfile
        image: costs.budget.mysql
        container_name: costs.budget.mysql
        ports:
            - "3306:3306"
        env_file: .env
        environment:
            TZ: UTC
            MYSQL_DATABASE: ${DB_DATABASE}
            MYSQL_USER: ${DB_USERNAME}
            MYSQL_PASSWORD: ${DB_PASSWORD}
            MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
        volumes:
            - ./.docker/mysql/data:/var/lib/mysql
networks:
    default:
        name: costs.network
        external: true

I typically leave the ports at their default values; the exception is when I know I will need to run more than Docker container at a time. I always need to run the Costs to Expect API at the same time as another App so will typically map the ports on the API to 8080 and 3308.

The dockerfiles for each of the services exist in a .docker folder. I typically end up with .docker/app/Dockerfile and .docker/mysql/Dockerfile. The .docker/mysql folder will also contain a data folder, this is the volume for the MySQL data.

The MySQL Dockerfile doesn’t include any configuration, just FROM mysql:8, the example below shows a Dockerfile for a typically Laravel application.

I used to include Composer and PHPUnit but have moved away from the additional complexity as it didn’t really offer any benefits and just made configuration in PPHStorm more compleicated.

FROM php:8.1-apache

COPY . /var/www/html
COPY .docker/app/vhost.conf /etc/apache2/sites-available/000-default.conf

RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libpng-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd

RUN apt-get update && apt-get install -y \
    zip libzip-dev \
    && docker-php-ext-configure zip \
    && docker-php-ext-install zip

RUN docker-php-ext-install pdo_mysql bcmath

RUN chown -R www-data:www-data /var/www/html \
    && a2enmod rewrite

WORKDIR /var/www/html

PHPStorm, Composer and PHPUnit

PHPStorm works relatively flawlessly with WSL2, well it did and will again without a tweak after the 16th of January.

I store all my project files in WSL2, specifically Ubuntu, the project root for PHPStorm will normally be something like \\wsl$\Ubuntu\home\[user]\Projects\[project_name]. I have a Projects folder inside my home directory and a folder for each project. The Projects folder includes any phar files I might need so as not to duplicate them across projects.

The CLI Interpreter is set to my distro of choice, so in my case Ubuntu.

Composer settings are as defined as below.

  • Path to composer.json //wsl$/Ubuntu/home/[user]/Projects/[project_name]/composer.json
  • Execution, composer.phar
  • Composer.phar location \wsl$\Ubuntu\home\[user]\Projects\composer.phar

PHPUnit settings are defined as below

  • Remote Interpreter
  • Use composer autoloader
  • Path to script /home/[user]/Projects/[project_name]/vendor/autoload.php
  • Test runner default configuration file /home/[user]/Projects/[project_name]/phpunit.xml.dist

This project setup works well for all my projects as if I ever need to use a different version of PHP or MySQL I can update the dockerfiles for each service and rebuild. I recently needed to upgrade an App form PHP5.6 to 8.0, this setup made it easy to upgrade to each version of PHP and MySQL along the way and test at each step.

If I need to use Tailwind, SASS or other tools, I try to use them via WSL2 before going the Windows route.

After reading this you may wonder why I use Windows for development, there are three main reasons, one, I’m comfortable with Windows, two, I play games, three, I build my own PCs. The setup above will work regardless of your operating system of choice.