{"id":29786,"date":"2020-02-11T06:10:20","date_gmt":"2020-02-11T06:10:20","guid":{"rendered":"https:\/\/www.designbombs.com\/?p=29786"},"modified":"2020-02-06T06:13:11","modified_gmt":"2020-02-06T06:13:11","slug":"bootstrapping-wordpress-projects-with-composer-and-wp-cli","status":"publish","type":"post","link":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/","title":{"rendered":"Bootstrapping WordPress projects with Composer and WP-CLI"},"content":{"rendered":"<p><a href=\"https:\/\/getcomposer.org\/\">Composer<\/a> is a PHP-dependency manager, a tool to import and manage our PHP project dependencies (both our own and from 3rd-party providers). It works with PHP packages (where a package is essentially a directory containing PHP code), which are retrieved from package repositories, either public or private.<\/p>\n<p>Composer enables to bootstrap a new PHP-based application very easily: we define the list of dependencies our project depends on and, by executing a single command, Composer will have them installed and updated to their latest versions (or to whichever version we require).<\/p>\n<p>In this article we will learn how to automate the creation of <a href=\"https:\/\/wordpress.org\">WordPress<\/a> sites through Composer and <a href=\"https:\/\/wp-cli.org\/\">WP-CLI<\/a> (which allows to interact with WordPress by executing commands on the command-line), as to save time when testing, developing and deploying our websites.<\/p>\n<h2>Adding Composer to a project<\/h2>\n<p>To start using Composer, all we need is a <code>composer.json<\/code> file, a JSON file located at the root of our project, defining the package&#8217;s name and its dependencies:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"name\": \"packageVendor\/projectName\",\r\n    \"require\": {\r\n        \"packageName\": \"versionContraint\",\r\n        \"packageName\": \"versionContraint\",\r\n        \"...\": \"...\"\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>The package name is composed of a package vendor and project name, in format <code>\"packageVendor\/packageName\"<\/code>. This format enables to upload our package to the repository and not collide with packages from other vendors. In this case, my vendor name is &#8220;leoloso&#8221;, and the name I chose for my project is &#8220;wp-install&#8221;:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"name\": \"leoloso\/wp-install\"\r\n}\r\n<\/code><\/pre>\n<p>Our project dependencies are defined under the <code>require<\/code> entry. Each dependency declares the package name as its key and, as its value, the package&#8217;s <a href=\"https:\/\/getcomposer.org\/doc\/articles\/versions.md#writing-version-constraints\">version constraint<\/a>, which indicates which version of the package we want to install. We can define any package hosted in Composer&#8217;s default package repository, <a href=\"https:\/\/packagist.org\/\">Packagist<\/a>.<\/p>\n<p>For instance, we can install the latest version of logging library <a href=\"https:\/\/packagist.org\/packages\/monolog\/monolog\">Monolog<\/a> like this:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"require\": {\r\n        \"monolog\/monolog\": \"2.0.*\"\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Once we have <code>composer.json<\/code> configured, we can install all the project dependencies by running <code>composer install<\/code> in the terminal (at the root folder of our project), and update them to their latest versions by running <code>composer update<\/code>.<\/p>\n<h2>Installing WordPress through Composer<\/h2>\n<p>In order to install WordPress through Composer, we must treat WordPress as yet another dependency. In this sense, even though WordPress is the underlying CMS for our application, installing it is no different than installing a simple PHP library. Since there is no &#8220;official&#8221; WordPress composer package, we can use the one <a href=\"https:\/\/github.com\/johnpbloch\/wordpress\">created by John P. Bloch<\/a>, like this:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"require\": {\r\n        \"johnpbloch\/wordpress\": \"&gt;=5.3\"\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>WordPress themes and plugins, as available under the WordPress <a href=\"https:\/\/wordpress.org\/plugins\/\">plugin<\/a> and <a href=\"https:\/\/wordpress.org\/themes\/\">theme<\/a> directories, are hosted through a dedicated package repository, <a href=\"https:\/\/wpackagist.org\/\">WPackagist<\/a>. We will need to define it in our <code>composer.json<\/code> file, like this:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"repositories\": [\r\n        {\r\n            \"type\": \"composer\",\r\n            \"url\": \"https:\/\/wpackagist.org\"\r\n        }\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>When declaring themes and plugins as dependencies, their vendor names are <code>\"wpackagist-theme\"<\/code> and <code>\"wpackagist-plugin\"<\/code> respectively. For instance, installing the <a href=\"https:\/\/wordpress.org\/plugins\/gutenberg\/\">Gutenberg plugin<\/a> is done like this:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"require\": {\r\n        \"wpackagist-plugin\/gutenberg\": \"&gt;=7.2\"\r\n    }\r\n}\r\n<\/code><\/pre>\n<h2>Creating a Composer project<\/h2>\n<p>We saw how to define all our dependencies in our project and have Composer install them by running a command in the terminal. Next step is to convert our project into a &#8220;template&#8221; project, from which we can easily bootstrap any new WordPress site.<\/p>\n<p>For this, we first define our project being of type <code>\"project\"<\/code> (as opposed to the default type <code>\"library\"<\/code>) in the <code>composer.json<\/code> file:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"type\": \"project\"\r\n}\r\n<\/code><\/pre>\n<p>It is recommended to also define the project&#8217;s homepage, description, license and author information. In this case, the <a href=\"https:\/\/github.com\/leoloso\/wp-install\">project&#8217;s source code is in GitHub<\/a>, so I just define its repo URL:<\/p>\n<pre><code class=\"language-json\">{\r\n    \"homepage\": \"https:\/\/github.com\/leoloso\/wp-install\",\r\n    \"description\": \"Bootstrap a WordPress site through Composer and WP-CLI\",\r\n    \"license\": \"MIT\",\r\n    \"authors\": [\r\n        {\r\n            \"name\": \"Leonardo Losoviz\",\r\n            \"email\": \"...\",\r\n            \"homepage\": \"...\"\r\n        }\r\n    ]\r\n}\r\n<\/code><\/pre>\n<p>If we haven&#8217;t done so yet, we must upload our project as a package in some repository. The easiest option is to submit it to Packagist, for which we must just add the repo URL in the <a href=\"https:\/\/packagist.org\/packages\/submit\">Packagist submission page<\/a>:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-29789\" src=\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/packagist-submission-page.jpg\" alt=\"Packagist submission page\" width=\"998\" height=\"705\" srcset=\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/packagist-submission-page.jpg 998w, https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/packagist-submission-page-300x212.jpg 300w, https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/packagist-submission-page-768x543.jpg 768w, https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/packagist-submission-page-84x60.jpg 84w\" sizes=\"auto, (max-width: 998px) 100vw, 998px\" \/><\/p>\n<p>Once our package is available, we can bootstrap a new WordPress site by executing Composer&#8217;s <a href=\"https:\/\/getcomposer.org\/doc\/03-cli.md#create-project\"><code>\"create-project\"<\/code><\/a> command, which creates a new project from the indicated package.<\/p>\n<p>For instance, to spin up a new WordPress site using project <code>leoloso\/wp-install<\/code>, and create it under folder <code>new_wp_site<\/code>, we execute this command in the terminal:<\/p>\n<pre><code class=\"language-bash\">composer create-project leoloso\/wp-install new_wp_site\r\n<\/code><\/pre>\n<p>This commands means: <code>git clone<\/code> the project from https:\/\/github.com\/leoloso\/wp-install into folder <code>\"new_wp_site\"<\/code>, step into the folder, and execute <code>composer install<\/code> to download and install all of its dependencies.<\/p>\n<h2>Installing WordPress<\/h2>\n<p>So far so good: after executing the <code>create-project<\/code> command we will have WordPress, its theme and plugins downloaded into the project folder. Next step is to run a script to configure and install WordPress.<\/p>\n<p>If dealing with a single website, we may be tempted to upload file <code>wp-config.php<\/code> (where the WordPress configuration entries, such as the database name, user and password, are defined) to the repo. Even though this is wrong (since uploading credentials to the repo is a security risk, and it doesn&#8217;t allow to easily scale up deploying the software, as recommended by the <a href=\"https:\/\/12factor.net\/\">12-Factor App<\/a>), it would work. However, for using a project to spin up multiple websites it will not work, because each website will need its own configuration.<\/p>\n<p>The solution is to have file <code>wp-config.php<\/code> empty, and to fill it up through environment variables, which, in addition, enables to automate the creation of different websites from the same source repo, or the same website for different environments (DEV, STAGING, PROD).<\/p>\n<p>We will have WP-CLI achieve this strategy: retrieve the required configuration items from environment variables and define them on the configuration file. After setting up the configuration file, WP-CLI can proceed to install WordPress, which involves creating all the tables in the database, and configuring the application with the website name, URL, admin person&#8217;s email, username and password. This process will be triggered through Composer events, invoked right after the creation of a new project.<\/p>\n<p>Let&#8217;s proceed to do it. All the environment variables that will be required are the following:<\/p>\n<pre><code class=\"language-bash\"># For wp-config.php\r\n$DB_NAME: The name of the database for WordPress\r\n$DB_USER: MySQL database username\r\n$DB_PASSWORD: MySQL database password\r\n$DB_HOST: MySQL hostname\r\n\r\n# For installing WordPress\r\n$SITE_URL_WITHOUT_HTTP: Such as www.mywebsite.com\r\n$SITE_URL_WITH_HTTP: Such as https:\/\/www.mywebsite.com\r\n$SITE_NAME: Website name\r\n$ADMIN_USER: Admin person\\'s username\r\n$ADMIN_PASSWORD: Admin person\\'s password\r\n$ADMIN_EMAIL: Admin person\\'s email\r\n<\/code><\/pre>\n<p>Hence, before creating the new project, we will need to set-up its environment variables. For this, we can use the terminal to <code>export<\/code> their values, like this:<\/p>\n<pre><code class=\"language-bash\">export DB_NAME=my_wp_site_db\r\nexport DB_USER=admin\r\nexport DB_PASSWORD=saranbadangananga\r\nexport DB_HOST=127.0.0.1\r\nexport SITE_URL_WITHOUT_HTTP=www.mywebsite.com\r\nexport SITE_URL_WITH_HTTP=https:\/\/www.mywebsite.com\r\nexport SITE_NAME=\"My super awesome super cool new WP site\"\r\nexport ADMIN_USER=admin\r\nexport ADMIN_PASSWORD=ermenegildo\r\nexport ADMIN_EMAIL=admin@mywebsite.com\r\n<\/code><\/pre>\n<p>Composer enables to <a href=\"https:\/\/getcomposer.org\/doc\/articles\/scripts.md#defining-scripts\">execute scripts<\/a> during the lifecycle of the <code>create-project<\/code> command, for specific events. What scripts are executed for what events is configured in file <code>composer.json<\/code> under entry <code>\"scripts\"<\/code>.<\/p>\n<p>We must first validate that all required environment variables have been defined, which shall be done through a script file <code>install\/validate-env-variables.sh<\/code>, executed upon event <code>\"post-root-package-install\"<\/code> (which occurs after the root package has been installed):<\/p>\n<pre><code class=\"language-json\">{\r\n    \"scripts\": {\r\n        \"post-root-package-install\": [\r\n            \".\/install\/validate-env-variables.sh\"\r\n        ]\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Script file <code>validate-env-variables.sh<\/code> will check if every one of the required environment variables has been set and, if not, show an error message and terminate the process. Its content is the following:<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/bash\r\n\r\n# Flag to know if there are errors\r\nERROR_ENV_VARS=\"\"\r\n\r\n# Required for wp-config.php\r\nif [ -z \"$DB_NAME\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nDB_NAME\"\r\nfi\r\nif [ -z \"$DB_USER\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nDB_USER\"\r\nfi\r\nif [ -z \"$DB_PASSWORD\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nDB_PASSWORD\"\r\nfi\r\nif [ -z \"$DB_HOST\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nDB_HOST\"\r\nfi\r\n\r\n# Required for installing WordPress through WP-CLI\r\nif [ -z \"$SITE_URL_WITHOUT_HTTP\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nSITE_URL_WITHOUT_HTTP\"\r\nfi\r\nif [ -z \"$SITE_URL_WITH_HTTP\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nSITE_URL_WITH_HTTP\"\r\nfi\r\nif [ -z \"$SITE_NAME\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nSITE_NAME\"\r\nfi\r\nif [ -z \"$ADMIN_USER\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nADMIN_USER\"\r\nfi\r\nif [ -z \"$ADMIN_PASSWORD\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nADMIN_PASSWORD\"\r\nfi\r\nif [ -z \"$ADMIN_EMAIL\" ]\r\nthen\r\n    ERROR_ENV_VARS=\"$ERROR_ENV_VARS\\nADMIN_EMAIL\"\r\nfi\r\n\r\n# If there are errors, return an error state\r\nif [ -n \"$ERROR_ENV_VARS\" ]\r\nthen\r\n    RED='\\033[0;31m'\r\n    GREEN='\\033[0;32m'\r\n    NC='\\033[0m' # No Color\r\n\r\n    echo -e \"${RED}Fatal error:${NC} The following environment variable(s) cannot be empty: ${GREEN}$ERROR_ENV_VARS${NC}\"\r\n    echo \"Terminating process.\"\r\n    exit 1\r\nfi\r\n<\/code><\/pre>\n<p>If all environment variables are set, we can then instruct WP-CLI to read them, set them up in file <code>wp-config.php<\/code>, and proceed to install WordPress. We do this through a script in file <code>install\/install.sh<\/code>, executed upon event <code>\"post-create-project-cmd\"<\/code> (which occurs after the create-project command has been executed):<\/p>\n<pre><code class=\"language-json\">{\r\n\t\"scripts\": {\r\n        \"post-create-project-cmd\": [\r\n            \".\/install\/install.sh\"\r\n        ]\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Script <code>install.sh<\/code> will interact with WP-CLI to first set up file <code>wp-config.php<\/code>, and then install WordPress (but only after checking that the WordPress database has not been initialized yet; for instance, when developing websites for clients, we may have a pre-populated database that we want to re-use). Its content is the following:<\/p>\n<pre><code class=\"language-bash\">#!\/bin\/bash\r\nRED='\\033[0;31m'\r\nGREEN='\\033[0;32m'\r\nORANGE='\\033[0;33m'\r\nNC='\\033[0m' # No Color\r\n\r\n# 1. Fill wp-config.php\r\nwp config set DB_NAME $DB_NAME\r\nwp config set DB_USER $DB_USER\r\nwp config set DB_PASSWORD $DB_PASSWORD\r\nwp config set DB_HOST $DB_HOST\r\n# Create random SALT keys\r\nwp config shuffle-salts\r\n\r\n# 2. Proceed to install WordPress (if not installed yet)\r\necho \"Checking if WordPress is installed: \"\r\nif ! $(wp core is-installed); then\r\n\r\n    echo \"WordPress is not installed yet. Installing WordPress through WP-CLI...\"\r\n    wp core install --url=$SITE_URL_WITHOUT_HTTP --title=\"$SITE_NAME\" --admin_user=$ADMIN_USER --admin_password=$ADMIN_PASSWORD --admin_email=$ADMIN_EMAIL\r\n    wp option update home $SITE_URL_WITH_HTTP\r\n    wp option update siteurl $SITE_URL_WITH_HTTP\r\n\r\n    # Check if the installation was successful. If not, show an error message\r\n    if ! $(wp core is-installed); then\r\n        echo -e \"\u274c ${RED}Installation unsuccessful.${NC} Please check the error messages displayed in the console to solve the issue, and then try again.\"\r\n        exit 1;\r\n    fi\r\n\r\n    echo -e \"\u2705 ${GREEN}Installation successful!${NC}\"\r\nelse\r\n    echo -e \"\u2705 ${ORANGE}WordPress is already installed${NC}\"\r\nfi\r\n<\/code><\/pre>\n<h2>Checking the results<\/h2>\n<p>I have created a <a href=\"https:\/\/github.com\/leoloso\/wp-install\/\">GitHub project<\/a> containing (a slightly longer version of) this code. When we run the following command in the terminal&#8230;<\/p>\n<pre><code class=\"language-bash\">composer create-project leoloso\/wp-install new_wp_site\r\n<\/code><\/pre>\n<p>&#8230;it produces the following results:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-29787\" src=\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/install-wp-thru-composer-script.gif\" alt=\"Running the script to install WordPress\" width=\"614\" height=\"328\" \/><\/p>\n<p>And our WordPress site will be duly created:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-29788\" src=\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/new-wp-site.png\" alt=\"New WordPress site\" width=\"891\" height=\"624\" srcset=\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/new-wp-site.png 891w, https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/new-wp-site-300x210.png 300w, https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/new-wp-site-768x538.png 768w, https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/01\/new-wp-site-84x60.png 84w\" sizes=\"auto, (max-width: 891px) 100vw, 891px\" \/><\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we learnt how Composer can help us automate the <a href=\"https:\/\/www.designbombs.com\/how-to-make-a-website\/\">creation of WordPress sites<\/a>.<\/p>\n<p>The benefits of using this process are several: we can launch a new WordPress instance as part of our deployment process (for instance, through continuous integration), we can quickly instantiate our websites for the different environments (DEV, STAGING, QA) or different clients, and we can share configuration of themes and plugins with colleagues and open source project contributors, among other benefits.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Composer is a PHP-dependency manager, a tool to import and manage our PHP project dependencies (both our own and from&#8230;<\/p>\n","protected":false},"author":50,"featured_media":30015,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[51],"tags":[],"class_list":{"0":"post-29786","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-coding","8":"entry"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v18.1 (Yoast SEO v26.4) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Bootstrapping WordPress projects with Composer and WP-CLI<\/title>\n<meta name=\"description\" content=\"Learn how to automate creating WordPress sites through Composer and WP-CLI, and save time during testing, development and deployment.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Bootstrapping WordPress projects with Composer and WP-CLI\" \/>\n<meta property=\"og:description\" content=\"Composer is a PHP-dependency manager, a tool to import and manage our PHP project dependencies (both our own and from 3rd-party providers). It works with\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\" \/>\n<meta property=\"og:site_name\" content=\"Design Bombs\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/designbombs\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-02-11T06:10:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png\" \/>\n\t<meta property=\"og:image:width\" content=\"770\" \/>\n\t<meta property=\"og:image:height\" content=\"320\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Leonardo Losoviz\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@losoviz\" \/>\n<meta name=\"twitter:site\" content=\"@designbombs\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Leonardo Losoviz\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\"},\"author\":{\"name\":\"Leonardo Losoviz\",\"@id\":\"https:\/\/www.designbombs.com\/#\/schema\/person\/4259b761dbd3ee01f8c7e2cd9d74df39\"},\"headline\":\"Bootstrapping WordPress projects with Composer and WP-CLI\",\"datePublished\":\"2020-02-11T06:10:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\"},\"wordCount\":1237,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.designbombs.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png\",\"articleSection\":[\"Coding\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\",\"url\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\",\"name\":\"Bootstrapping WordPress projects with Composer and WP-CLI\",\"isPartOf\":{\"@id\":\"https:\/\/www.designbombs.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png\",\"datePublished\":\"2020-02-11T06:10:20+00:00\",\"description\":\"Learn how to automate creating WordPress sites through Composer and WP-CLI, and save time during testing, development and deployment.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage\",\"url\":\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png\",\"contentUrl\":\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png\",\"width\":770,\"height\":320,\"caption\":\"Bootstrapping WordPress projects with Composer and WP-CLI\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.designbombs.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Coding\",\"item\":\"https:\/\/www.designbombs.com\/category\/coding\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Bootstrapping WordPress projects with Composer and WP-CLI\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.designbombs.com\/#website\",\"url\":\"https:\/\/www.designbombs.com\/\",\"name\":\"Design Bombs\",\"description\":\"Droppin&#039; design bombs everyday!\",\"publisher\":{\"@id\":\"https:\/\/www.designbombs.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.designbombs.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.designbombs.com\/#organization\",\"name\":\"DesignBombs\",\"url\":\"https:\/\/www.designbombs.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.designbombs.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2019\/04\/db-logo.png\",\"contentUrl\":\"https:\/\/www.designbombs.com\/wp-content\/uploads\/2019\/04\/db-logo.png\",\"width\":219,\"height\":92,\"caption\":\"DesignBombs\"},\"image\":{\"@id\":\"https:\/\/www.designbombs.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/designbombs\/\",\"https:\/\/x.com\/designbombs\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.designbombs.com\/#\/schema\/person\/4259b761dbd3ee01f8c7e2cd9d74df39\",\"name\":\"Leonardo Losoviz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.designbombs.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bb059a4470fd73113804d5dd7430f6a66aaba66ba161798d0fac79b124c74611?s=96&d=https%3A%2F%2Fwww.designbombs.com%2Fwp-content%2Fthemes%2FDesignBombs%2Fimages%2Fgravatar.jpg&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bb059a4470fd73113804d5dd7430f6a66aaba66ba161798d0fac79b124c74611?s=96&d=https%3A%2F%2Fwww.designbombs.com%2Fwp-content%2Fthemes%2FDesignBombs%2Fimages%2Fgravatar.jpg&r=g\",\"caption\":\"Leonardo Losoviz\"},\"description\":\"Leonardo Losoviz is an open source developer and technical writer, author of GraphQL by PoP, a CMS-agnostic GraphQL server in PHP. Find him on his blog leoloso.com and on Twitter @losoviz.\",\"sameAs\":[\"https:\/\/leoloso.com\",\"https:\/\/x.com\/losoviz\"],\"url\":\"https:\/\/www.designbombs.com\/author\/leo\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Bootstrapping WordPress projects with Composer and WP-CLI","description":"Learn how to automate creating WordPress sites through Composer and WP-CLI, and save time during testing, development and deployment.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/","og_locale":"en_US","og_type":"article","og_title":"Bootstrapping WordPress projects with Composer and WP-CLI","og_description":"Composer is a PHP-dependency manager, a tool to import and manage our PHP project dependencies (both our own and from 3rd-party providers). It works with","og_url":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/","og_site_name":"Design Bombs","article_publisher":"https:\/\/www.facebook.com\/designbombs\/","article_published_time":"2020-02-11T06:10:20+00:00","og_image":[{"width":770,"height":320,"url":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png","type":"image\/png"}],"author":"Leonardo Losoviz","twitter_card":"summary_large_image","twitter_creator":"@losoviz","twitter_site":"@designbombs","twitter_misc":{"Written by":"Leonardo Losoviz","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#article","isPartOf":{"@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/"},"author":{"name":"Leonardo Losoviz","@id":"https:\/\/www.designbombs.com\/#\/schema\/person\/4259b761dbd3ee01f8c7e2cd9d74df39"},"headline":"Bootstrapping WordPress projects with Composer and WP-CLI","datePublished":"2020-02-11T06:10:20+00:00","mainEntityOfPage":{"@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/"},"wordCount":1237,"commentCount":0,"publisher":{"@id":"https:\/\/www.designbombs.com\/#organization"},"image":{"@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage"},"thumbnailUrl":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png","articleSection":["Coding"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/","url":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/","name":"Bootstrapping WordPress projects with Composer and WP-CLI","isPartOf":{"@id":"https:\/\/www.designbombs.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage"},"image":{"@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage"},"thumbnailUrl":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png","datePublished":"2020-02-11T06:10:20+00:00","description":"Learn how to automate creating WordPress sites through Composer and WP-CLI, and save time during testing, development and deployment.","breadcrumb":{"@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#primaryimage","url":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png","contentUrl":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png","width":770,"height":320,"caption":"Bootstrapping WordPress projects with Composer and WP-CLI"},{"@type":"BreadcrumbList","@id":"https:\/\/www.designbombs.com\/bootstrapping-wordpress-projects-with-composer-and-wp-cli\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.designbombs.com\/"},{"@type":"ListItem","position":2,"name":"Coding","item":"https:\/\/www.designbombs.com\/category\/coding\/"},{"@type":"ListItem","position":3,"name":"Bootstrapping WordPress projects with Composer and WP-CLI"}]},{"@type":"WebSite","@id":"https:\/\/www.designbombs.com\/#website","url":"https:\/\/www.designbombs.com\/","name":"Design Bombs","description":"Droppin&#039; design bombs everyday!","publisher":{"@id":"https:\/\/www.designbombs.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.designbombs.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.designbombs.com\/#organization","name":"DesignBombs","url":"https:\/\/www.designbombs.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.designbombs.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2019\/04\/db-logo.png","contentUrl":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2019\/04\/db-logo.png","width":219,"height":92,"caption":"DesignBombs"},"image":{"@id":"https:\/\/www.designbombs.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/designbombs\/","https:\/\/x.com\/designbombs"]},{"@type":"Person","@id":"https:\/\/www.designbombs.com\/#\/schema\/person\/4259b761dbd3ee01f8c7e2cd9d74df39","name":"Leonardo Losoviz","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.designbombs.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/bb059a4470fd73113804d5dd7430f6a66aaba66ba161798d0fac79b124c74611?s=96&d=https%3A%2F%2Fwww.designbombs.com%2Fwp-content%2Fthemes%2FDesignBombs%2Fimages%2Fgravatar.jpg&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bb059a4470fd73113804d5dd7430f6a66aaba66ba161798d0fac79b124c74611?s=96&d=https%3A%2F%2Fwww.designbombs.com%2Fwp-content%2Fthemes%2FDesignBombs%2Fimages%2Fgravatar.jpg&r=g","caption":"Leonardo Losoviz"},"description":"Leonardo Losoviz is an open source developer and technical writer, author of GraphQL by PoP, a CMS-agnostic GraphQL server in PHP. Find him on his blog leoloso.com and on Twitter @losoviz.","sameAs":["https:\/\/leoloso.com","https:\/\/x.com\/losoviz"],"url":"https:\/\/www.designbombs.com\/author\/leo\/"}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.designbombs.com\/wp-content\/uploads\/2020\/02\/composer-wp-cli-bootstrapping.png","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/posts\/29786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/users\/50"}],"replies":[{"embeddable":true,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/comments?post=29786"}],"version-history":[{"count":3,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/posts\/29786\/revisions"}],"predecessor-version":[{"id":30016,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/posts\/29786\/revisions\/30016"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/media\/30015"}],"wp:attachment":[{"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/media?parent=29786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/categories?post=29786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.designbombs.com\/wp-json\/wp\/v2\/tags?post=29786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}