Andrew Welch

Andrew Welch · Insights · #craftcms #devops #craft-3

Making the web better one site at a time, with a focus on performance, usability & SEO

Published , updated · 5 min read ·


For more tools, technologies, and techniques, check out the devMode.fm podcast!

Setting up a New Craft CMS 3 Project

With the release of Craft CMS 3 RC1, you might want to kick the tires. Read this before you do.

Craft Cms 3 Rc 1

Now that Craft CMS 3 RC1 has been released, you’re likely eager to give it a go. This article is something you might want to read first, to give you a roadmap for setting up your project.

This article will discuss setting up a new Craft 3 project so you can experiment with it. It will not cover updating an existing Craft 2.x project to Craft 3; expect that to come in a future article.

First, let’s talk lingo. “RC” stands for Release Candidate. This does not mean that Craft 3 is done. It means that there is a freeze on the features that will be added, and only critical bugs will be fixed going forward.

When developers cut a given RC release, they believe this actually could be the release version. It’s a candidate to be the actual General Availability (GA) release.

Release Candidate Features Frozen

This makes it an excellent time to start getting familiar with it, whether you’re a frontend developer, a plugin developer, or both. With the feature set frozen, you’re working against a known quantity.

I won’t rehash what is new in Craft 3; if you’re interested in that, check out the Craft 3 Beta Executive Summary article.

The canonical reference will always be the Craft CMS documentation for Server Requirements, Installation, Configuration, and Directory Structure. But there are a few tips, tricks, and hints I’d like to add to the subject as well.

So, let’s dive in!

Link Should I Use Craft 3 in Production?

One of the most commonly asked questions with the release of Craft CMS 3 RC1 is:

Should I Use Craft 3 in Production?

The answer is it depends. I personally am using Craft 3 RC1 in production for a client site, as well as a for a new project of my own.

The biggest drawback is that your favorite plugin may not be ported yet, but Craft is flexible enough that you can generally do without many plugins if you have to. There are also quite a few Craft 3 plugins available already.

I think it makes sense to at the very least fire up a test site to kick Craft 3 RC1’s tires. For some client sites, I think it’s also very reasonable to start using it now as well. The speed and infrastructure improvements are well worth it.

Link Changes from Craft 2.x

There are a few changes in terms of how things are set up in Craft 3 compared to Craft 2.x, and all for the better in my opinion.

Changes Craft 2 To Craft 3

Some of these changes will take some getting used to:

  • Craft 3 now uses Composer for installation & updating of Craft and any plugins you might have
  • The default directory structure has some changes; but these are just suggestions. You can use whatever you like
  • Plugins written for Craft 2.x will not work with Craft 3, they will need to be updated by developers
  • Craft 3 now uses a phpdotenv .env file by default for handling environmental-specific things like passwords, database names, etc.
  • There are some minor template changes for you to make; most are just deprecations, so they still work, but you’ll need to update them by the time Craft 4 rolls around

Link Composer

The first major change is that Craft 3 relies on Composer for things like installation and updates of both Craft CMS itself, and any plugins you may be using.

  • Composer is a tool that allows for the installation of PHP packages, much like npm and yarn for JavaScript
  • Packagist.org is a website that’s a public listing of Composer packages, similar to npmjs.com for JavaScript

If you don’t have Composer installed on your local dev setup yet, here are instructions on how to Install Composer.

Pixel & Tonic has mentioned that they plan to allow a non-Composer installation path, but as developers it actually makes our lives much easier to embrace Composer.

So if you aren’t familiar with Composer, investing some time to learn it now will pay dividends down the road. Let’s dive in!

Craft 3 Cms Composer

To install a new Craft 3 project, all we need to do is the following:

composer create-project craftcms/craft PATH -s RC

Let’s break this down:

  • composer is just the globally installed Composer command
  • create-project tells Composer that we want to create a new project from an existing template (more on this later)
  • craftcms/craft is the packagist.org package we want to use as a template when creating our project
  • PATH is the relative or absolute path to where we want our project created; normally it’d be something like craft3 or ~/webdev/sites/mysitename or what have you
  • -s RC tells Composer that the minimum-stability we’ll accept is Release Candidate (RC for short)

So out of my Homestead VM that I use for local development, the command I’d run is:

vagrant@homestead ~/sites $ composer create-project craftcms/craft craftrc1 -s RC

A whole bunch of text will fly by, but let’s talk about what’s actually happening. Composer is going out to packagist.org to look for a package named craftcms/craft and then it’s essentially git clone’ing that repository, but without actually pulling down the .git data.

We’re creating a new project, after all, so we want to use the package as a template to get the files in it as a starting point.

Have a look at the actual craftcms/craft repository on GitHub.com, and you’ll see that there isn’t a whole lot to it, really. It’s just some Craft configuration files, composer.json, etc. So it’s just a bare bones project that gets made for us as a starting point.

Then it will run a composer install to install any of the Composer packages that craftcms/craft claims as dependencies, much like npm install or yarn does for npm packages.

The critical thing to understand here is that the craftcms/craft package is just scaffolding that Pixel & Tonic set up with what they think is a nice starting point for your new Craft 3 project. This actually could be any packagist.org package that is of "type": "project"!

For instance, I have set up a package nystudio107/craft that allows me to set up Craft 3 with the directory structure and dependencies that I want, and I can start a new Craft 3 project with my scaffolding by doing:

vagrant@homestead ~/sites $ composer create-project nystudio107/craft craftrc1 -s RC

The nystudio107/craft project package does everything the Pixel & Tonic craftcms/craft project package does, and then installs a number of tools and scaffolding that I use, and has been described in articles in this blog. So it makes a great starting point.

Not only is this pretty useful should you want to set up your own scaffolding, it’s a key point to understand what’s going on. Let’s have a look at the composer.json file that comes with the craftcms/craft package:

{
  "name": "craftcms/craft",
  "description": "Craft CMS",
  "keywords": [
    "craft",
    "cms",
    "craftcms",
    "project"
  ],
  "license": "MIT",
  "homepage": "https://craftcms.com/",
  "type": "project",
  "support": {
    "email": "support@craftcms.com",
    "issues": "https://github.com/craftcms/cms/issues",
    "forum": "https://craftcms.stackexchange.com/",
    "source": "https://github.com/craftcms/cms",
    "docs": "https://craftcms.com/docs",
    "rss": "https://craftcms.com/changelog.rss"
  },
  "minimum-stability": "RC",
  "require": {
    "php": ">=7.0.0",
    "craftcms/cms": "^3.0.0-rc.1",
    "vlucas/phpdotenv": "^2.4.0",
    "roave/security-advisories": "dev-master"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
    }
  },
  "config": {
    "optimize-autoloader": true
  },
  "scripts": {
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ],
    "post-create-project-cmd": [
      "@composer dump-autoload -o",
      "@php craft setup/welcome"
    ]
  }
}

So this is pretty interesting! The craftcms/craft project package lists craftcms/cms as a dependency. It can get a little confusing, so remember:

  • craftcms/craft is the starter project scaffolding package for your Craft 3 projects
  • craftcms/cms is the actual Craft 3 package that contains all of the code that collectively makes up Craft CMS

So Craft itself is just another Composer package that gets pulled in. It works the same way for any plugins you might want to use, you can just add them to your composer.json and they’ll get installed as PHP packages.

Of course, Craft provides a nice GUI for doing all of this as well, but it’s useful to understand how things work under the hood.

If you want to do a deep-dive on Composer, I’d suggest checking out the articles Composer Stability Flags & Composer Autoload Features (there are several parts to this article, make sure to read them all!).

Also extremely useful for understanding Composer/Packagist semver naming is the Packagist Semver Checker.

Link Craft 3 Initial Setup

Okay, so after we’ve created a Craft 3 project, now we need to do a little bit of work setting it up.

Craft 3 Cms Setup Instructions

At the tail end of the installation, you’ll see a message like this from Craft:

Generating a security key...
done (UDRBoBjQAzfgY5J9S-543Ie0PrxwCwZG)

Welcome to Craft CMS! Run the following command if you want to setup Craft from your terminal:

    ~/sites/craftrc1/craft setup

The security key that it generates is just a random string of characters (like a password) that’s unique on a per-project basis. For multi-environment setups, you’ll want to be using the same security key in each environment.

Craft uses this for encrypting data, so it’s just a unique seed that’s set in general.php.

If you run the command ~/sites/craftrc1/craft setup (or whatever it outputs for your project), it’ll set up your .env file for you:

vagrant@homestead ~/sites $ ~/sites/craftrc1/craft setup
Which database driver are you using? [mysql,pgsql,?]: mysql
Database server name or IP address: [localhost]
Database port: [3306]
Database username: [root] homestead
Database password:
Database name: craftrc1
Database table prefix:
Testing database credentials... success!
Saving database credentials to your .env file...
done

Your (empty) database needs to have been created already, just like on Craft 2.x. It’ll then ask you if you want to install Craft now. If you say yes, it’s essentially just a command line equivalent of the familiar setup wizard:

Install Craft now? (yes|no) [yes]:

Username: [admin]
Email: andrew@nystudio107.com
Password:
Confirm:
Site name: craftrc1
Site URL: http://craftrc1.dev
Site language: [en-US]

Of course, you don’t have to do it this way. You can say no, and install it by going to the http://mysite.dev/admin URL just as you did for Craft 2.x if you like.

Either way, you’ll now have a phpdotenv .env file in your project root that has your credentials in it:

vagrant@homestead ~/sites $ cat craftrc1/.env
# The environment Craft is currently running in ('dev', 'staging', 'production', etc.)
ENVIRONMENT="dev"

# The secure key Craft will use for hashing and encrypting data
SECURITY_KEY="UDRBoBjQAzfgY5J9S-543Ie0PrxwCwZG"

# The database driver that will used ('mysql' or 'pgsql')
DB_DRIVER="mysql"

# The database server name or IP address (usually this is 'localhost' or '127.0.0.1')
DB_SERVER="localhost"

# The database username to connect with
DB_USER="homestead"

# The database password to connect with
DB_PASSWORD="secret"

# The name of the database to select
DB_DATABASE="craftrc1"

# The database schema that will be used (PostgreSQL only)
DB_SCHEMA="public"

# The prefix that should be added to generated table names (only necessary if multiple things are sharing the same database)
DB_TABLE_PREFIX=""

# The port to connect to the database with. Will default to 5432 for PostgreSQL and 3306 for MySQL.
DB_PORT="3306"

Remember, this file is never checked into git, so we’ll need a manually created .env file for each environment we deploy Craft to, including our staging and live production servers.

The constants in the .env file are parsed, and set as PHP Environment variables that are read by the general.php, db.php, etc. Craft 3 config/ files:

<?php
/**
 * Database Configuration
 *
 * All of your system's database connection settings go in here. You can see a
 * list of the available settings in vendor/craftcms/cms/src/config/DbConfig.php.
 */

return [
    'driver' => getenv('DB_DRIVER'),
    'server' => getenv('DB_SERVER'),
    'user' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'database' => getenv('DB_DATABASE'),
    'schema' => getenv('DB_SCHEMA'),
    'tablePrefix' => getenv('DB_TABLE_PREFIX'),
    'port' => getenv('DB_PORT')
];

While .env files are great for development, for live production I’d recommend moving the environmental variables to your webserver config, or using something like Craft 3 Multi-Environment as described in the Multi-Environment Config for Craft CMS article.

Link The Craft 3 Directory Structure

Alrighty, now that we have a fresh Craft 3 project installed & set up, let’s take a little survey of what we actually have installed.

Craft 3 Cms Directory Structure

Here’s what our freshly installed project directory looks like:

vagrant@homestead ~/sites/craftrc1 $ tree -L 2 -a .
.
├── composer.json
├── composer.lock
├── config
│   ├── app.php
│   ├── db.php
│   ├── general.php
│   ├── redactor
│   └── routes.php
├── craft
├── craft.bat
├── .DS_Store
├── .env
├── .env.example
├── .gitignore
├── LICENSE.md
├── modules
│   └── Module.php
├── README.md
├── storage
│   ├── .gitignore
│   ├── logs
│   └── runtime
├── templates
│   └── .gitkeep
├── vendor
│   ├── autoload.php
│   ├── bin
│   ├── cebe
│   ├── composer
│   ├── craftcms
│   ├── creocoder
│   ├── danielstjules
│   ├── .DS_Store
│   ├── enshrined
│   ├── ezyang
│   ├── guzzlehttp
│   ├── justinrainbow
│   ├── league
│   ├── mikehaertl
│   ├── paragonie
│   ├── pixelandtonic
│   ├── psr
│   ├── seld
│   ├── swiftmailer
│   ├── symfony
│   ├── twig
│   ├── vlucas
│   ├── yiisoft
│   └── zendframework
└── web
    ├── cpresources
    ├── .htaccess
    ├── index.php
    └── web.config

33 directories, 22 files

The first thing you’ll notice is that there is no craft/ directory here at all anymore, which is something we were used to seeing in Craft 2.x. Every directory that was inside of the craft/ directory in Craft 2.x is now in our root project directory.

This makes sense if you think about it, since Craft itself is now just installed as another Composer dependency in the vendor/craftcms directory.

So let’s take a look at some notable files/directories that we have in our projects now:

  • composer.json has all of the information for our project, including the PHP package dependencies and their minimum semver versions
  • composer.lock has information on what PHP packages & their versions are actually installed (they may be newer than our minimum versions)
  • config/ is what used to be craft/config/, and has all of the familiar Craft CMS config files
  • craft is a command line tool that is exactly analogous to the web-facing index.php. It’s what you use to run Craft 3 via the command line (more on this below)
  • .env is our phpdotenv .env file that has our environment-specific things like database passwords, etc. stored
  • .gitignore tells git what file patterns to ignore completely, and never check into git
  • storage/ is what used to be craft/storage/ and is where temporary runtime files, logs, etc. are kept, just like in Craft 2.x
  • templates/ is what used to be craft/templates/ and is where your Twig templates are stored
  • vendor/ is where all of the PHP package dependencies that your project uses (including Craft itself) are stored
  • web/ is what used to be the public/, which contains our index.php, .htaccess, etc. files, and is where the web server root should be pointed

It’s important to note that Craft doesn’t really care what you use as a directory structure, this is just what Pixel & Tonic is providing you as a base setup. If you don’t like the change from public/ to web/, that’s fine. Just rename it!

The craft command line tool is actually what we used earlier to set up the .env file, and optionally install Craft. Just think of it is a way to run Craft from the command line. It inherits a number of tools from Yii2 Console Commands, and Pixel & Tonic has added a number of Craft-specific things to it as well.

For instance, you can use ./craft install/plugin my-plugin-handle to install plugins from the command line. Cool!

Link Deploying Craft CMS

The change in how Composer is used for Craft 3 discussed earlier leads directly to how we should be updating, testing, and deploying Craft 3.

For Craft 2.x, we just checked all of craft/ (including the vendor/ sub-directory) into git, updated & tested it in local dev, and then deployed it to staging/live production via our deployment tool of choice, such as Laravel Forge, Buddy.works, Laravel Envoyer, DeployBot, etc.

Deploying Craft 3 Cms

There are a few important bits from Composer that we need to understand first, to see how this needs to change for Craft 3:

  • composer.json has all of the information about our project, and what PHP package dependencies it requires as minimum semver versions
  • composer.lock has information on what PHP package dependencies are actually installed (we might have newer versions than what our minimum versions require)
  • vendor/ is a directory that has all of the actual PHP packages installed (including Craft CMS itself!)
  • .gitignore tells git what file patterns to ignore when tracking changes in git

Here’s the default .gitignore file provided by the craftcms/craft package:

/.env
/.idea
/vendor
.DS_Store

The implications are that we’re never checking our .env files into git (because putting sensitive things like passwords into version control is a bad idea), but we’re also ignoring the entire /vendor directory.

So if we’re not checking any of our PHP packages in the /vendor directory into git (this includes Craft CMS itself, remember!), how do we update and deploy things?

By embracing Composer, that’s how!

We’ll take advantage of how Composer works:

  • In local dev, we’ll update everything via composer update (or we can update just specific packages via composer update packagevendor/package)
  • The above step can also be done via the AdminCP UI by clicking on Update, either for Craft CMS itself, or any of its plugins. Under the hood, it ends up running Composer just as described above
  • This causes Composer to download & install the updated package(s), and then it writes out what’s installed to the composer.lock file
  • Then we test everything in local dev just as we used to, to make sure it’s ready for prime time
  • Since we ignore all of the /vendor directory, the only thing that will be changed as far as git is concerned is the composer.lock file that lists what versions of what packages are actually installed

Then on the server-side deployment of things, we’ll run the following from our project directory on the server:

composer install

What composer install does is look at whatever is in the composer.lock file, and if it’s newer than what it sees installed locally, it updates & installs it!

The neat thing about doing it this way is we have less cruft checked into our git repos, and we can also discretely update only specific things.

Maybe we only want to update a specific plugin, we can do that by updating only that plugin via composer update pluginvendor/plugin from local dev. Since that’s the only change that gets written out to the composer.lock file, that’s the only thing that gets updated when our server runs composer install

Nice.

The only downside to this is that composer install can take a bit longer than a simple git pull to execute, so looking into atomic deployments via Buddy.worksLaravel EnvoyerDeployBot, etc. might not be a bad idea.

Link Craft 3 Plugins

The bad news about plugins is that plugin developers will need to rewrite their plugins for Craft 3.

Craft 3 Cms Plugins

The good news is that Pixel & Tonic has made a nice guide on Craft 3 Plugin Development, and many plugins have already been ported. Check out the Craft 3 Plugins page to see what’s available already.

Also, tools like pluginfactory.io and articles like So You Wanna Make a Craft 3 Plugin? are available to help developers.

The best thing you can do is check with your plugin vendor to see how far along they are on porting their plugins to Craft 3.

Pixel & Tonic has stated that a beta version of the Plugin Store (which is integrated into the Craft 3 AdminCP) will ship with Craft 3 CMS RC 1, but that only free plugins will be available initially. Developers can make plugins that will be paid plugins available for free now as well, but they will require purchase once Craft CMS 3 is in GA release.

The full rollout of the plugin store with paid plugins, Commerce 2, and the General Availability release of Craft 3 will happen on April 4th, 2018. Check out the What We Announced at Dot All 2017 article for details.

Speaking of plugins, Craft 3 comes with no Rich Text field by default. You’ll need to install the Redactor plugin first (don’t worry, your existing content is still there). This is because P&T will be offering a CKEditor Rich Text plugin as well, in the near future.

Link Template Changes

The good news is that in terms of actual changes to your Twig templates, there aren’t that many. Pixel & Tonic has done a great job outlining the changes in Twig 2 as well as the changes in Craft Template Tags that you’ll need to be aware of.

The vast majority of the changes are merely deprecation errors. That means that Pixel & Tonic plans to phase them out when Craft 4 comes along, but they’ll still work for now.

You can check on any deprecation errors inside of Craft 3 by going to Utilities → Deprecation Errors.

Craft 3 Cms Deprecation Errors

Craft 3 CMS Deprecation Errors

The other really interesting thing is that in Craft 3, the entire craft.app application instance is available to your Twig templates.

What that means in real terms is that you can do anything with the Craft 3 APIs via Twig that you can via PHP. So many small plugins that were needed to expose some needed functionality may no longer be necessary at all.

Phpstorm Craft Auto Completion

Twig inspection hint

One absolutely amazing thing you can do if you’re using PhpStorm is get full auto-completion of the entire craft. APIs in your Twig templates, too! To do make the magic happen, install the Symfony plugin, then Go to Preferences → Languages & Frameworks → PHP → Symfony and check Enable Plugin for this Project.

Then all you need to do is put this inspection hint at the top of your Twig templates:

{# @var craft \craft\web\twig\variables\CraftVariable #}

…and just like that, you get the same magic auto-completion of in your Twig templates that you have in your PHP code. And since the entire Craft application is available in our Twig templates now, this makes writing Twig code that uses the Craft app APIs so much nicer.

Link Wrapping Up!

This is undoubtably the first of several articles I’ll be writing on Craft 3. But hopefully it has given you an idea of the lay of the land for Craft 3 development.

Go forth and make cool stuff!

${ category } · ${ blog.postDate }

${ blog.title }

#${ tag.title }