<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vladimir Apostolski</title>
    <description>The latest articles on DEV Community by Vladimir Apostolski (@vapostolski).</description>
    <link>https://dev.to/vapostolski</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F375262%2F1f086bb6-43e7-46d3-a57e-365d9a10caa9.png</url>
      <title>DEV Community: Vladimir Apostolski</title>
      <link>https://dev.to/vapostolski</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vapostolski"/>
    <language>en</language>
    <item>
      <title>Using Composer with WordPress for easy Deployments</title>
      <dc:creator>Vladimir Apostolski</dc:creator>
      <pubDate>Wed, 29 Apr 2020 11:13:18 +0000</pubDate>
      <link>https://dev.to/time2hack/using-composer-with-wordpress-for-easy-deployments-4o92</link>
      <guid>https://dev.to/time2hack/using-composer-with-wordpress-for-easy-deployments-4o92</guid>
      <description>&lt;p&gt;There are many ways to manage a WordPress application. Fortunately, it is possible to use Composer with WordPress.&lt;/p&gt;

&lt;p&gt;In this article, we will show how to &lt;strong&gt;use Composer with WordPress&lt;/strong&gt;, so that you can easily &lt;strong&gt;maintain&lt;/strong&gt; it, &lt;strong&gt;manage&lt;/strong&gt; it and &lt;strong&gt;deploy&lt;/strong&gt; it in different server environments.&lt;/p&gt;

&lt;p&gt;That means that you will be able to &lt;strong&gt;install WordPress core, themes, plugins&lt;/strong&gt; etc. as well as update and delete them when needed via Composer.&lt;/p&gt;

&lt;p&gt;To achieve this, we will use the following tools: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://getcomposer.org"&gt;Composer&lt;/a&gt; - for managing packages &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wpackagist.org/"&gt;WPackagist&lt;/a&gt; - repository for WordPress plugins and themes&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://laravel.com/docs/master/envoy"&gt;Laravel Envoy&lt;/a&gt; - for writing easy deployment scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Composer with WordPress
&lt;/h2&gt;

&lt;p&gt;Our first goal is to &lt;strong&gt;download the WordPress core, the plugins and themes as versioned Composer dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So in order to &lt;strong&gt;use Composer with WordPress&lt;/strong&gt;, we will first install Composer and then create a &lt;code&gt;composer.json&lt;/code&gt; file in the root directory of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"repositories"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"composer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"https://wpackagist.org"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since Composer uses &lt;a href="https://packagist.org/"&gt;Packagist&lt;/a&gt; by default as a package repository, we will need to tell Composer that we will need &lt;a href="(https://wpackagist.org/)"&gt;WPackagist&lt;/a&gt; instead. &lt;/p&gt;

&lt;p&gt;Now we would be able to &lt;strong&gt;install public WordPress plugins and themes as Composer dependencies&lt;/strong&gt;, for example like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"wpackagist-plugin/akismet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"^4.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"wpackagist-theme/twentytwenty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let's &lt;strong&gt;install the WordPress core via Composer&lt;/strong&gt;. We will be using &lt;a href="https://github.com/johnpbloch/wordpress"&gt;John P Bloch's mirror of WordPress Core&lt;/a&gt; to achieve that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"johnpbloch/wordpress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=5.4"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extra"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"installer-paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"wp-content/plugins/{$name}/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"type:wordpress-plugin"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"wp-content/themes/{$name}/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"type:wordpress-theme"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"wordpress-install-dir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wordpress"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"repositories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"composer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://wpackagist.org"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;       
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;require&lt;/code&gt; section, we added the dependency. Next, in the &lt;code&gt;extra&lt;/code&gt; section, we told &lt;strong&gt;Composer where to look for themes and plugins&lt;/strong&gt;. Lastly, we defined the WordPress installation directory to be &lt;code&gt;wordpress&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--prefer-dist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Composer will now install WordPress within the &lt;code&gt;wordpress&lt;/code&gt; directory in the root of our project.&lt;/p&gt;

&lt;p&gt;To be able to &lt;strong&gt;fully manage WordPress with Composer&lt;/strong&gt;, we need to use a different directory for &lt;code&gt;wp-content&lt;/code&gt; instead of the default one, &lt;code&gt;wordpress/wp-content&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's create a new directory in the project's root, called &lt;code&gt;wp-content&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's go ahead and create the standard &lt;code&gt;wp-config.php&lt;/code&gt; file and then add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'mydomain.test'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WP_SITEURL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/wordpress"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WP_HOME'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"http:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$httpHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nb"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'HTTP_HOST'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'HTTP_HOST'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'WP_CONTENT_DIR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/wp-content'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'WP_CONTENT_URL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'http://'&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$httpHost&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/wp-content'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cd"&gt;/** Absolute path to the WordPress directory. */&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ABSPATH'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ABSPATH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/wordpress'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cd"&gt;/** Sets up WordPress vars and included files. */&lt;/span&gt;
&lt;span class="k"&gt;require_once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ABSPATH&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'wp-settings.php'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let's create an &lt;code&gt;index.php&lt;/code&gt; file within our project's root directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WP_USE_THEMES'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/wordpress/wp-blog-header.php'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since the &lt;code&gt;wp-config.php&lt;/code&gt; file contains sensitive data, we will not commit it to our repository by creating a &lt;code&gt;.gitignore&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/wp-config.php
/wordpress/
/wp-content/
/vendor/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;wordpress&lt;/code&gt;, &lt;code&gt;wp-content&lt;/code&gt; and &lt;code&gt;vendor&lt;/code&gt; directories also need to be ignored, so we will add them to the &lt;code&gt;.gitignore&lt;/code&gt; file as well.&lt;/p&gt;

&lt;p&gt;Now we end up with a very simple project structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vendor/&lt;/li&gt;
&lt;li&gt;wordpress/&lt;/li&gt;
&lt;li&gt;wp-content/&lt;/li&gt;
&lt;li&gt;composer.json&lt;/li&gt;
&lt;li&gt;composer.lock&lt;/li&gt;
&lt;li&gt;wp-config.php&lt;/li&gt;
&lt;li&gt;.gitignore&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using composer to install WordPress plugins and themes from private repositories
&lt;/h3&gt;

&lt;p&gt;You may want to install plugins or themes that are hosted in &lt;strong&gt;private repositories&lt;/strong&gt; on &lt;strong&gt;Github, Bitbucket&lt;/strong&gt; or somewhere else, but not on WPackagist.&lt;br&gt;
That is possible, but there are two things you need to do:&lt;br&gt;
1) provide your credentials in an &lt;code&gt;auth.json&lt;/code&gt; file&lt;br&gt;
2) within the &lt;code&gt;composer.json&lt;/code&gt;, in the &lt;code&gt;repositories&lt;/code&gt; section, you need to tell Composer where to look for the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vcs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bitbucket.org/your-company/your-theme.git"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Envoy to deploy WordPress with Composer
&lt;/h2&gt;

&lt;p&gt;Now that we have our WordPress project set up with Composer, let's see how to deploy it.&lt;/p&gt;

&lt;p&gt;As we mentioned previously, we will be using &lt;a href="https://laravel.com/docs/master/envoy"&gt;Laravel Envoy&lt;/a&gt; to &lt;strong&gt;write a deployment script for WordPress&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reason why we are using Envoy is because of simplicity. You can also decide to use a different tool like &lt;a href="https://deployer.org/"&gt;Deployer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's go ahead and download Envoy.&lt;/p&gt;

&lt;p&gt;With the deployment script, we can &lt;strong&gt;deploy our WordPress application to different servers&lt;/strong&gt;: development, staging and production.&lt;/p&gt;

&lt;p&gt;Because the project structure is so lightweight, now it will be easy to write the deployment steps.&lt;/p&gt;

&lt;p&gt;Here is what our &lt;strong&gt;deployment script for WordPress&lt;/strong&gt; will look do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a new release with a timestamp in a &lt;code&gt;releases&lt;/code&gt; directory on your server&lt;/li&gt;
&lt;li&gt;clone the repository&lt;/li&gt;
&lt;li&gt;install all the dependencies&lt;/li&gt;
&lt;li&gt;copy &lt;code&gt;wp-config&lt;/code&gt;, &lt;code&gt;.htaccess&lt;/code&gt; and other files specific to the server environment (e.g production)&lt;/li&gt;
&lt;li&gt;create a symlink of the &lt;code&gt;uploads&lt;/code&gt; directory to the new release&lt;/li&gt;
&lt;li&gt;create a symlink of the new release to the domain's document root directory on the server&lt;/li&gt;
&lt;li&gt;clean up old releases from the server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, let's go to our server and set up a directory called &lt;code&gt;current&lt;/code&gt; as the domain document root directory on the server.&lt;/p&gt;

&lt;p&gt;If you are not familiar that, you can follow a &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-move-an-apache-web-root-to-a-new-location-on-ubuntu-16-04"&gt;tutorial&lt;/a&gt; on how to do it.&lt;/p&gt;

&lt;p&gt;You can create the following directory structure on your server: &lt;code&gt;~/sites/yoursite&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's install Envoy with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;composer&lt;/span&gt; &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="nx"&gt;laravel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;envoy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let's write the &lt;strong&gt;deployment script for WP&lt;/strong&gt;. Let's create a new file in our project root directory called &lt;code&gt;Envoy.blade.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Envoy, we will use the following directives: &lt;code&gt;@servers&lt;/code&gt;, &lt;code&gt;@setup&lt;/code&gt;, &lt;code&gt;@task&lt;/code&gt; and &lt;code&gt;@story&lt;/code&gt;. It's very straightforward, here is what they mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@servers&lt;/code&gt; - this is where you define all your servers with their corresponding IPs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@setup&lt;/code&gt; - section where you can define variables or configurations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@task&lt;/code&gt; - a single action that should be executed on the specified server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@story&lt;/code&gt; - a sequence of tasks that need to be executed on the specified server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The way Envoy works is, it will ssh to the specified servers and execute the defined script, by following the directives.&lt;/p&gt;

&lt;p&gt;Inside the directives you can use PHP to define which UNIX commands need to be executed on the servers.&lt;/p&gt;

&lt;p&gt;The first step will be to define multiple server environments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'local'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'staging'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'w.x.y.z'&lt;/span&gt; &lt;span class="s1"&gt;'production'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a.b.c.d'&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let's define some variables for our setup steps. These are the things we can configure, depending on our needs.&lt;/p&gt;

&lt;p&gt;In our case, we will assume we have a private repository on Bitbucket for the project.&lt;/p&gt;

&lt;p&gt;The deployment script will clone the master branch and set up the releases directory structure, as discussed above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;

    &lt;span class="c1"&gt;// the repository to clone&lt;/span&gt;
    &lt;span class="nv"&gt;$repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'git@bitbucket.org:your-company/your-wp-composer-project.git'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// the branch to clone&lt;/span&gt;
    &lt;span class="nv"&gt;$branch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'master'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// set up timezones&lt;/span&gt;
    &lt;span class="nb"&gt;date_default_timezone_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Europe/Berlin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// we want the releases to be timestamps to ensure uniqueness&lt;/span&gt;
    &lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'YmdHis'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// the application directory on your server&lt;/span&gt;
    &lt;span class="nv"&gt;$appDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'~/sites/yoursite'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// this is where the releases will be stored&lt;/span&gt;
    &lt;span class="nv"&gt;$buildsDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$appDir&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/releases'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// this is where the deployment will be&lt;/span&gt;
    &lt;span class="nv"&gt;$deploymentDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$buildsDir&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// and this is the document root directory&lt;/span&gt;
    &lt;span class="nv"&gt;$serve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$appDir&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/current'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endsetup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let's create a task to actually create the directory for the new release:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'dir'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Preparing new deployment directory..."&lt;/span&gt;

    &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$buildsDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Preparing new deployment directory complete."&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endtask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, it's using Blade syntax for the UNIX commands, with the variables we defined in &lt;code&gt;@setup&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following task will clone the repository and the specified branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'git'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cloning repository..."&lt;/span&gt;

    &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$deploymentDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;depth&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$branch&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="s2"&gt;"{{ &lt;/span&gt;&lt;span class="nv"&gt;$repo&lt;/span&gt;&lt;span class="s2"&gt; }}"&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$deploymentDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cloning repository complete."&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endtask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Of course, you will need to make sure your server can access the git repository.&lt;/p&gt;

&lt;p&gt;The next task, will install the dependencies and copy the &lt;code&gt;wp-config.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'install'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Installing dependencies..."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;composer&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;prefer&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;
    &lt;span class="nx"&gt;cp&lt;/span&gt; &lt;span class="o"&gt;../../&lt;/span&gt;&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Installing dependencies complete."&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endtask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The next task will create the symlinks to the new release and to the &lt;code&gt;uploads&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'live'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating symlinks for the live version..."&lt;/span&gt;

    &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$deploymentDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nx"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nfs&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$deploymentDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$serve&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nx"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nfs&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$appDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$serve&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating symlinks completed."&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endtask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The last task will perform a cleanup and delete old releases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deployment_cleanup'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cleaning up old deployments..."&lt;/span&gt;

    &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$buildsDir&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nx"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;xargs&lt;/span&gt; &lt;span class="nx"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rf&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cleaned up old deployments."&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endtask&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can configure the number of old releases we want to keep on the server. In our case it is 4.&lt;/p&gt;

&lt;p&gt;Now let's write a &lt;code&gt;@story&lt;/code&gt; directive where we can group the tasks we just wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deploy-staging'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'on'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'staging'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nb"&gt;dir&lt;/span&gt;
    &lt;span class="nx"&gt;git&lt;/span&gt;
    &lt;span class="nx"&gt;install&lt;/span&gt;
    &lt;span class="nx"&gt;live&lt;/span&gt;
    &lt;span class="nx"&gt;deployment_cleanup&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endstory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deploy-production'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'on'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'production'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nb"&gt;dir&lt;/span&gt;
    &lt;span class="nx"&gt;git&lt;/span&gt;
    &lt;span class="nx"&gt;install&lt;/span&gt;
    &lt;span class="nx"&gt;live&lt;/span&gt;
    &lt;span class="nx"&gt;deployment_cleanup&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endstory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, we used the names of the tasks inside the &lt;code&gt;@story&lt;/code&gt; to define the order of execution.&lt;/p&gt;

&lt;p&gt;Finally we would be able to run the following &lt;strong&gt;commands to deploy our WordPress to the server&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;envoy run deploy-staging
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;envoy run deploy-production
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and so on, for each environment we want.&lt;/p&gt;

&lt;p&gt;So now we can manage our WP installation completely via Composer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping WordPress in sync with Composer
&lt;/h2&gt;

&lt;p&gt;As you already know, it is possible to update plugins via Wordpress Admin panel. So if the WordPress administrator updates a plugin manually, it will make the site out of sync with the Composer file, which will &lt;strong&gt;beat the purpose of using Composer&lt;/strong&gt; and it might cause the website to stop functioning properly.&lt;/p&gt;

&lt;p&gt;So, how to avoid this situation?&lt;/p&gt;

&lt;p&gt;It will be best to tell administrators not to update plugins on their own, especially not in production.&lt;/p&gt;

&lt;p&gt;Once you have that settled, you can write a simple task in Envoy to update a given plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'update-plugin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;  &lt;span class="nv"&gt;$deploymentDir&lt;/span&gt;  &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$plugin&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;$pluginVersion&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endtask&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;story&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'update'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;endstory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we are using &lt;a href="https://wp-cli.org/"&gt;WP-CLI&lt;/a&gt; to perform the update ( but you can also do it via the admin panel if you prefer )&lt;/p&gt;

&lt;p&gt;You can execute it by typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nx"&gt;envoy&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;bbpress&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.6&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we assume we want to update the plugin bbpress to the version 2.6.4&lt;/p&gt;

&lt;p&gt;Once this is executed, you can also update your &lt;code&gt;composer.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require wpackagist-plugin/bbpress 2.6.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And finally, let's deploy our change to the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;envoy run deploy-production
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Other ways to use Composer with WordPress
&lt;/h2&gt;

&lt;p&gt;We have showed &lt;strong&gt;how to manage WordPress with Composer&lt;/strong&gt; and how to deploy it with your own customizable deployment script.&lt;/p&gt;

&lt;p&gt;There are, of course, &lt;strong&gt;other ways to manage WordPress sites with Composer&lt;/strong&gt;. One of the popular ways to do so, is with &lt;a href="https://roots.io/bedrock/"&gt;Bedrock&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bedrock is a WordPress boilerplate project, with pre-defined directory structure.&lt;/p&gt;

&lt;p&gt;It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;composer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;environments&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;development&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;staging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;production&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;vendor&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;web&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;plugins&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;themes&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;uploads&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;wp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Bedrock will help you move WordPress to a directory called &lt;code&gt;wp&lt;/code&gt; and set up different environments: development, staging and production.&lt;/p&gt;

&lt;p&gt;It also does a good job setting up config values in a .env file with the help of &lt;a href="https://github.com/vlucas/phpdotenv"&gt;PHP Dotenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;wp-config.php&lt;/code&gt; reads the .env file which is not located in the &lt;code&gt;web&lt;/code&gt; directory and that improves the security of the website.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;wp-content&lt;/code&gt; is renamed to &lt;code&gt;app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once you have it set up, you can add plugins as Composer dependencies, similar to what we showed earlier.&lt;/p&gt;

&lt;p&gt;For deployment, you can write a deployment script with either Envoy, Deployer or some other tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion - managing and deploying WordPress Sites with Composer
&lt;/h2&gt;

&lt;p&gt;In this article, we showed two ways (manually and with Bedrock) of managing WordPress with Composer and a way how to easily deploy WordPress to multiple environments when it is used with Composer.&lt;/p&gt;

&lt;p&gt;First we defined a &lt;code&gt;composer.json&lt;/code&gt; file which enabled us to install the WordPress Core, as well as the themes and the plugins as dependencies.&lt;/p&gt;

&lt;p&gt;This made the project very lightweight and easy to deploy with a script.&lt;/p&gt;

&lt;p&gt;While WordPress is not initially thought to be used as a Composer dependency, it is a great advantage to use it in modern development workflows as it &lt;strong&gt;ensures fairly easy deployments with zero downtime and quick rollbacks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you have any experience using &lt;strong&gt;WordPress with Composer&lt;/strong&gt; (and deploying it), we would like to hear about it in the comments.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="http://time2hack.com/composer-wordpress-deployment/"&gt;https://time2hack.com&lt;/a&gt; on April 27, 2020.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>composer</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
