Intro

This is going to be a pretty quick post, but there may be some longer posts about Lando later. Today though, I want to share part of a setup file I added to my Lando configuration for WordPress. The approach here is based on some work that was done by Brian Daley to set up to use composer and WordPress about 4 years ago at UConn Communications.

Composer for WordPress

At work, we use composer to create and manage our WordPress projects. Each project has a composer.json file which defines what dependencies that project needs. For instance, let's say I want to work on a new plugin. For development, I'll want to define some dependencies such as: other plugins, themes, and of course WordPress itself.

So at the root of my project I have the composer.json file and when I start the project I want to run the CLI command composer install after the project is set up but before I start working on it. After that, we can use docker and docker-compose to actually start working. But there's an issue here. What happens if those plugins or themes have their own dependencies? We're trying to eliminate those in our projects, but it still happens sometimes. We have ways to deal with this in our composer/docker set up. But I was curious to see if I could get this approach to work with lando. Lando has a pre-built "receipe" for WordPress. In order to help standardize and simplify our projects, this was the solution I wanted to try.

Lando build steps

As a local development tool, Lando supprts build steps. There are four of them as defined by the documentation:

  • build runs as "you" and before your service boots up
  • build_as_root runs as root and before your service boots up
  • run runs as "you" and after your service boots up
  • run_as_root runs as root and after your service boots up

These steps let you define actions to take the first time (and only the first time) a project starts. I'll get more into how I'm learning how to set up a lando project another time. For now though, all you need to know is that to run a lando project you need a .lando.yml file which will configure it. These can be really complex or extremely simple depending on your needs.

In this case, to run a build step on my apache/PHP web server, my file has a section like this:

services:
  appserver:
    type: php:7.4
    run:
      - ./composer-setup.sh
      - ./wp-setup.sh

Each line after the run key will be gone through in order after the service has finished booting up, but before it's available for use. So this section of the file basically says "After creating a PHP server, run these two files in order." This is the perfect time to install and manage composer dependencies.

I want to first focus on the composer-setup.sh file. In that file, I do two things

  • Install composer dependencies for the current project.
  • Install composer dependencies for any plugin (or theme) that project needs

Managing Composer

#!/bin/bash

# install composer dependencies for the theme itself.
composer install

# once that's done, find all installed plugins and themes and run these commands

find ./www/content/plugins -maxdepth 1 -type d ! -name . -exec bash -c "cd '{}' && ls composer.json && composer install --no-dev --no-scripts" \;

The first command takes care of the first part. But it's the find command that's really special. This command will traverse the plugins directory and install composer dependencies for any plugin which requires them.

It looks complicated though so let's break it down.

  • find get ready to find something!
  • ./www/content/plugins in the plugins directory
  • -maxdepth 1 but only go down one level
  • -type d and only look at directories
  • ! -name . but don't look at the plugins directory itself
  • exec bash -c now that you're looking at those directories, do something with bash. Wait a moment, I'll give you the command to run...
  • cd '{}' actually go into each plugin directory. The {} is like a placeholder for wherever the find command is at that moment
  • && ls composer.json and when you get there, look for a composer.json file.
  • && composer install --no-dev --no-scripts and if the file is there, run the composer install command. But only install things the project actually needs and don't run any scripts after your done.
  • \; finally exit the find command.

Managing WordPress

Our projects customize the WordPress wp-config file. Initally I was a little confused about how this was going to work with the docker image lando provides. The issue is that you can't mount a custom wp-config file directly into the container that lando runs. In their documentation, they suggest re-writing your wp-config file. This seemed like a less than ideal approach to me. In local development, each of our plugins or themes is a separate WordPress installation. I didn't want to go through all of them and adjust all the wp-config files if lando was a success in my trial.

However after a little experimentation, I came up with a solution. Rather than mount a new file, lando comes with wp-cli as part of its wordpress image. That means you can use it in a build step to create a different wp-config file.

That's the first thing the wp-setup.sh file does. After that, it sets the custom configuration we need using wp-cli's config set command. Note the use of the --path flag. The path given is the one inside the running lando container; /app/www/ is the webroot I defined elsewhere in my configuration file.

# create a config file with the default lando credentials for the db
wp config create --force --path=/app/www/wordpress --dbname=wordpress --dbuser=wordpress --dbpass=wordpress --dbhost=database

# for each thing, create a config setting create the raw value
# probably need to figure out how to get this into a loop
wp --path=/app/www/wordpress config set WP_DEBUG true --raw
wp --path=/app/www/wordpress config set WP_HOME "'http://' . \$_SERVER['HTTP_HOST']" --raw
wp --path=/app/www/wordpress config set WP_SITEURL "WP_HOME . '/wordpress'" --raw
wp --path=/app/www/wordpress config set WP_CONTENT_DIR "dirname(__DIR__) . '/content'" --raw
wp --path=/app/www/wordpress config set WP_CONTENT_URL "WP_HOME . '/content'" --raw

Using this approach, the wp-config file is created at the time the container is started up. However, before the server finishes being built for the first time, the run command lets me adjust this file. That way, at the time the server is available for use, it will always use my custom configuration.

Conclusion

I'd like to talk more about the direction I'm trying with lando in the future. For now, though, this was definitely the most complicated part of the set up. It took quite a while to figure it out, but in the end I think it was time well spent. I hope you enjoyed this!