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

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, you might want to kick the tires. Here is how to set up a Craft CMS 3 project

Craft Cms 3 Rc 1

Now that Craft CMS 3 has been released, you’re like­ly eager to give it a go. This arti­cle is some­thing you might want to read first, to give you a roadmap for set­ting up your project.

This arti­cle will dis­cuss set­ting up a new Craft 3 project so you can exper­i­ment with it. It will not cov­er updat­ing an exist­ing Craft 2.x project to Craft 3; expect that to come in a future article.

Release Candidate Features Frozen

This makes it an excel­lent time to start get­ting famil­iar with it, whether you’re a fron­tend devel­op­er, a plu­g­in devel­op­er, or both. With the fea­ture set frozen, you’re work­ing against a known quantity.

I won’t rehash what is new in Craft 3; if you’re inter­est­ed in that, check out the Craft 3 Beta Exec­u­tive Sum­ma­ry article.

The canon­i­cal ref­er­ence will always be the Craft CMS doc­u­men­ta­tion for Serv­er Require­ments, Instal­la­tion, Con­fig­u­ra­tion, and Direc­to­ry Struc­ture. But there are a few tips, tricks, and hints I’d like to add to the sub­ject as well.

So, let’s dive in!

Link Should I Use Craft 3 in Production?

N.B. Since Craft CMS 3 was released on April 4th 2018, the answer is: def­i­nite­ly yes, you should be using Craft CMS 3.x in pro­duc­tion. The bal­ance of this sec­tion is left in for his­tor­i­cal reasons.

One of the most com­mon­ly asked ques­tions with the release of Craft CMS 3 RC1 is:

Should I Use Craft 3 in Production?

The answer is it depends. I per­son­al­ly am using Craft 3 RC1 in pro­duc­tion for a client site, as well as a for a new project of my own.

The biggest draw­back is that your favorite plu­g­in may not be port­ed yet, but Craft is flex­i­ble enough that you can gen­er­al­ly do with­out many plu­g­ins if you have to. There are also quite a few Craft 3 plu­g­ins avail­able 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 rea­son­able to start using it now as well. The speed and infra­struc­ture improve­ments 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 com­pared to Craft 2.x, and all for the bet­ter in my opinion.

Changes Craft 2 To Craft 3

Some of these changes will take some get­ting used to:

  • Craft 3 now uses Com­pos­er for instal­la­tion & updat­ing of Craft and any plu­g­ins you might have
  • The default direc­to­ry struc­ture has some changes; but these are just sug­ges­tions. You can use what­ev­er you like
  • Plu­g­ins writ­ten for Craft 2.x will not work with Craft 3, they will need to be updat­ed by developers
  • Craft 3 now uses a php­dotenv .env file by default for han­dling envi­ron­men­tal-spe­cif­ic things like pass­words, data­base names, etc.
  • There are some minor tem­plate changes for you to make; most are just dep­re­ca­tions, 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 Com­pos­er for things like instal­la­tion and updates of both Craft CMS itself, and any plu­g­ins you may be using.

  • Com­pos­er is a tool that allows for the instal­la­tion of PHP pack­ages, much like npm and yarn for JavaScript
  • Pack​ag​ist​.org is a web­site that’s a pub­lic list­ing of Com­pos­er pack­ages, sim­i­lar to npmjs​.com for JavaScript

If you don’t have Com­pos­er installed on your local dev set­up yet, here are instruc­tions on how to Install Com­pos­er.

Pix­el & Ton­ic has men­tioned that they plan to allow a non-Com­pos­er instal­la­tion path, but as devel­op­ers it actu­al­ly makes our lives much eas­i­er to embrace Composer.

So if you aren’t famil­iar with Com­pos­er, invest­ing some time to learn it now will pay div­i­dends 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

Let’s break this down:

  • composer is just the glob­al­ly installed Com­pos­er command
  • create-project tells Com­pos­er that we want to cre­ate a new project from an exist­ing tem­plate (more on this later)
  • craftcms/craft is the pack​ag​ist​.org pack­age we want to use as a tem­plate when cre­at­ing our project
  • PATH is the rel­a­tive or absolute path to where we want our project cre­at­ed; nor­mal­ly it’d be some­thing like craft3 or ~/webdev/sites/mysitename or what have you

So out of my Home­stead VM that I use for local devel­op­ment, the com­mand I’d run is:

vagrant@homestead ~/sites $ composer create-project craftcms/craft crafttest

A whole bunch of text will fly by, but let’s talk about what’s actu­al­ly hap­pen­ing. Com­pos­er is going out to pack​ag​ist​.org to look for a pack­age named craftcms/craft and then it’s essen­tial­ly git cloneing that repos­i­to­ry, but with­out actu­al­ly pulling down the .git data.

We’re cre­at­ing a new project, after all, so we want to use the pack­age as a tem­plate to get the files in it as a start­ing point.

Have a look at the actu­al craftcms/​craft repos­i­to­ry on GitHub​.com, and you’ll see that there isn’t a whole lot to it, real­ly. It’s just some Craft con­fig­u­ra­tion files, composer.json, etc. So it’s just a bare bones project that gets made for us as a start­ing point.

Then it will run a composer install to install any of the Com­pos­er pack­ages that craftcms/craft claims as depen­den­cies, much like npm install or yarn does for npm packages. 

The crit­i­cal thing to under­stand here is that the craftcms/craft pack­age is just scaf­fold­ing that Pix­el & Ton­ic set up with what they think is a nice start­ing point for your new Craft 3 project. This actu­al­ly could be any pack​ag​ist​.org pack­age that is of "type": "project"!

For instance, I have set up a pack­age nystudio107/craft that allows me to set up Craft 3 with the direc­to­ry struc­ture and depen­den­cies that I want, and I can start a new Craft 3 project with my scaf­fold­ing by doing:

vagrant@homestead ~/sites $ composer create-project nystudio107/craft crafttest

The nystudio107/​craft project pack­age does every­thing the Pix­el & Ton­ic craftcms/​craft project pack­age does, and then installs a num­ber of tools and scaf­fold­ing that I use, and has been described in arti­cles in this blog. So it makes a great start­ing point.

Not only is this pret­ty use­ful should you want to set up your own scaf­fold­ing, it’s a key point to under­stand 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"
  },
  "require": {
    "craftcms/cms": "^3.0.0",
    "vlucas/phpdotenv": "^2.4.0"
  },
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
    }
  },
  "config": {
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
    }
  },
  "scripts": {
    "post-create-project-cmd": [
      "@php -r \"copy('.env.example', '.env');\"",
      "@php -r \"unlink('composer.json');\"",
      "@php -r \"unlink('LICENSE.md');\"",
      "@php -r \"unlink('README.md');\"",
      "@php -r \"rename('composer.json.default', 'composer.json');\"",
      "@composer dump-autoload -o",
      "@php craft setup/welcome"
    ]
  }
}

So this is pret­ty inter­est­ing! The craftcms/craft project pack­age lists craftcms/cms as a depen­den­cy. It can get a lit­tle con­fus­ing, so remember:

  • craftcms/craft is the starter project scaf­fold­ing pack­age for your Craft 3 projects
  • craftcms/cms is the actu­al Craft 3 pack­age that con­tains all of the code that col­lec­tive­ly makes up Craft CMS

So Craft itself is just anoth­er Com­pos­er pack­age that gets pulled in. It works the same way for any plu­g­ins 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 pro­vides a nice GUI for doing all of this as well, but it’s use­ful to under­stand how things work under the hood.

If you want to do a deep-dive on Com­pos­er, I’d sug­gest check­ing out the arti­cles Com­pos­er Sta­bil­i­ty Flags & Com­pos­er Autoload Fea­tures (there are sev­er­al parts to this arti­cle, make sure to read them all!).

Also extreme­ly use­ful for under­stand­ing Composer/​Packagist semver nam­ing is the Pack­ag­ist Semver Check­er.

Link Craft 3 Initial Setup

Okay, so after we’ve cre­at­ed a Craft 3 project, now we need to do a lit­tle bit of work set­ting it up.

Craft 3 Cms Setup Instructions

At the tail end of the instal­la­tion, you’ll see a mes­sage 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/crafttest/craft setup

The secu­ri­ty key that it gen­er­ates is just a ran­dom string of char­ac­ters (like a pass­word) that’s unique on a per-project basis. For mul­ti-envi­ron­ment setups, you’ll want to be using the same secu­ri­ty key in each environment.

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

If you run the com­mand ~/sites/crafttest/craft setup (or what­ev­er it out­puts for your project), it’ll set up your .env file for you:

vagrant@homestead ~/sites $ ~/sites/crafttest/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: crafttest
Database table prefix:
Testing database credentials... success!
Saving database credentials to your .env file...
done

Your (emp­ty) data­base needs to have been cre­at­ed 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 essen­tial­ly just a com­mand line equiv­a­lent of the famil­iar set­up wizard:

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

Username: [admin]
Email: andrew@nystudio107.com
Password:
Confirm:
Site name: crafttest
Site URL: http://crafttest.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 php­dotenv .env file in your project root that has your cre­den­tials in it:

vagrant@homestead ~/sites $ cat crafttest/.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="crafttest"

# 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"

Remem­ber, this file is nev­er checked into git, so we’ll need a man­u­al­ly cre­at­ed .env file for each envi­ron­ment we deploy Craft to, includ­ing our staging and live pro­duc­tion servers.

The con­stants in the .env file are parsed, and set as PHP Envi­ron­ment vari­ables 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 devel­op­ment, for live pro­duc­tion I’d rec­om­mend mov­ing the envi­ron­men­tal vari­ables to your web­serv­er con­fig, or using some­thing like Craft 3 Mul­ti-Envi­ron­ment as described in the Mul­ti-Envi­ron­ment Con­fig 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 lit­tle sur­vey of what we actu­al­ly have installed.

Craft 3 Cms Directory Structure

Here’s what our fresh­ly installed project direc­to­ry looks like:

vagrant@homestead ~/sites/crafttest $ 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/ direc­to­ry here at all any­more, which is some­thing we were used to see­ing in Craft 2.x. Every direc­to­ry that was inside of the craft/ direc­to­ry 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 anoth­er Com­pos­er depen­den­cy 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 infor­ma­tion for our project, includ­ing the PHP pack­age depen­den­cies and their min­i­mum semver ver­sions
  • composer.lock has infor­ma­tion on what PHP pack­ages & their ver­sions are actu­al­ly installed (they may be new­er than our min­i­mum versions)
  • config/ is what used to be craft/config/, and has all of the famil­iar Craft CMS con­fig files
  • craft is a com­mand line tool that is exact­ly anal­o­gous to the web-fac­ing index.php. It’s what you use to run Craft 3 via the com­mand line (more on this below)
  • .env is our php­dotenv .env file that has our envi­ron­ment-spe­cif­ic things like data­base pass­words, etc. stored
  • .gitignore tells git what file pat­terns to ignore com­plete­ly, and nev­er check into git
  • storage/ is what used to be craft/storage/ and is where tem­po­rary run­time files, logs, etc. are kept, just like in Craft 2.x
  • templates/ is what used to be craft/templates/ and is where your Twig tem­plates are stored
  • vendor/ is where all of the PHP pack­age depen­den­cies that your project uses (includ­ing Craft itself) are stored
  • web/ is what used to be the public/, which con­tains our index.php, .htac­cess, etc. files, and is where the web serv­er root should be pointed

It’s impor­tant to note that Craft doesn’t real­ly care what you use as a direc­to­ry struc­ture, this is just what Pix­el & Ton­ic is pro­vid­ing you as a base set­up. If you don’t like the change from public/ to web/, that’s fine. Just rename it!

The craft com­mand line tool is actu­al­ly what we used ear­li­er to set up the .env file, and option­al­ly install Craft. Just think of it as a way to run Craft from the com­mand line. It inher­its a num­ber of tools from Yii2 Con­sole Com­mands, and Pix­el & Ton­ic has added a num­ber of Craft-spe­cif­ic things to it as well.

For instance, you can use ./craft install/plugin my-plugin-handle to install plu­g­ins from the com­mand line. Cool!

Link Deploying Craft CMS

The change in how Com­pos­er is used for Craft 3 dis­cussed ear­li­er leads direct­ly to how we should be updat­ing, test­ing, and deploy­ing Craft 3.

For Craft 2.x, we just checked all of craft/ (includ­ing the vendor/ sub-direc­to­ry) into git, updat­ed & test­ed it in local dev, and then deployed it to staging/live pro­duc­tion via our deploy­ment tool of choice, such as Lar­avel Forge, Buddy.works, Lar­avel Envoy­er, Deploy­Bot, etc.

Deploying Craft 3 Cms

There are a few impor­tant bits from Com­pos­er that we need to under­stand first, to see how this needs to change for Craft 3:

  • composer.json has all of the infor­ma­tion about our project, and what PHP pack­age depen­den­cies it requires as min­i­mum semver ver­sions
  • composer.lock has infor­ma­tion on what PHP pack­age depen­den­cies are actu­al­ly installed (we might have new­er ver­sions than what our min­i­mum ver­sions require)
  • vendor/ is a direc­to­ry that has all of the actu­al PHP pack­ages installed (includ­ing Craft CMS itself!)
  • .gitignore tells git what file pat­terns to ignore when track­ing changes in git

Here’s the default .gitignore file pro­vid­ed by the craftcms/​craft package:

/.env
/.idea
/vendor
.DS_Store

The impli­ca­tions are that we’re nev­er check­ing our .env files into git (because putting sen­si­tive things like pass­words into ver­sion con­trol is a bad idea), but we’re also ignor­ing the entire /vendor directory.

So if we’re not check­ing any of our PHP pack­ages in the /vendor direc­to­ry into git (this includes Craft CMS itself, remem­ber!), how do we update and deploy things?

By embracing Composer, that’s how!

We’ll take advan­tage of how Com­pos­er works:

  • In local dev, we’ll update every­thing via composer update (or we can update just spe­cif­ic pack­ages via composer update packagevendor/package)
  • The above step can also be done via the AdminCP UI by click­ing on Update, either for Craft CMS itself, or any of its plu­g­ins. Under the hood, it ends up run­ning Com­pos­er just as described above
  • This caus­es Com­pos­er to down­load & install the updat­ed package(s), and then it writes out what’s installed to the composer.lock file
  • Then we test every­thing in local dev just as we used to, to make sure it’s ready for prime time
  • Since we ignore all of the /vendor direc­to­ry, the only thing that will be changed as far as git is con­cerned is the composer.lock file that lists what ver­sions of what pack­ages are actu­al­ly installed

Then on the serv­er-side deploy­ment of things, we’ll run the fol­low­ing from our project direc­to­ry on the server:

composer install --no-interaction --prefer-dist --optimize-autoloader

What composer install does is look at what­ev­er is in the composer.lock file, and if it’s new­er than what it sees installed local­ly, it updates & installs it! You can see the full options avail­able to com­pos­er install here.

The neat thing about doing it this way is we have less cruft checked into our git repos, and we can also dis­crete­ly update only spe­cif­ic things.

Maybe we only want to update a spe­cif­ic plu­g­in, we can do that by updat­ing only that plu­g­in via composer update pluginvendor/plugin from local dev. Since that’s the only change that gets writ­ten out to the composer.lock file, that’s the only thing that gets updat­ed when our serv­er runs composer install

Nice.

The only down­side to this is that composer install can take a bit longer than a sim­ple git pull to exe­cute, so look­ing into atom­ic deploy­ments via Buddy.worksLar­avel Envoy­erDeploy­Bot, etc. might not be a bad idea.

Link Craft 3 Plugins

The bad news about plu­g­ins is that plu­g­in devel­op­ers will need to rewrite their plu­g­ins for Craft 3.

Craft 3 Cms Plugins

The good news is that Pix­el & Ton­ic has made a nice guide on Craft 3 Plu­g­in Devel­op­ment, and many plu­g­ins have already been port­ed. Check out the Craft 3 Plu­g­ins page to see what’s avail­able already.

Also, tools like plug​in​fac​to​ry​.io and arti­cles like So You Wan­na Make a Craft 3 Plu­g­in? are avail­able to help developers. 

The best thing you can do is check with your plu­g­in ven­dor to see how far along they are on port­ing their plu­g­ins to Craft 3.

Pix­el & Ton­ic has stat­ed that a beta ver­sion of the Plu­g­in Store (which is inte­grat­ed into the Craft 3 AdminCP) will ship with Craft 3 CMS RC 1, but that only free plu­g­ins will be avail­able ini­tial­ly. Devel­op­ers can make plu­g­ins that will be paid plu­g­ins avail­able for free now as well, but they will require pur­chase once Craft CMS 3 is in GA release.

The full roll­out of the plu­g­in store with paid plu­g­ins, Com­merce 2, and the Gen­er­al Avail­abil­i­ty release of Craft 3 will hap­pen on April 4th, 2018. Check out the What We Announced at Dot All 2017 arti­cle for details.

Speak­ing of plu­g­ins, Craft 3 comes with no Rich Text field by default. You’ll need to install the Redac­tor plu­g­in first (don’t wor­ry, your exist­ing con­tent is still there). This is because P&T will be offer­ing a CKEd­i­tor Rich Text plu­g­in as well, in the near future.

Link Template Changes

The good news is that in terms of actu­al changes to your Twig tem­plates, there aren’t that many. Pix­el & Ton­ic has done a great job out­lin­ing the changes in Twig 2 as well as the changes in Craft Tem­plate Tags that you’ll need to be aware of.

The vast major­i­ty of the changes are mere­ly dep­re­ca­tion errors. That means that Pix­el & Ton­ic plans to phase them out when Craft 4 comes along, but they’ll still work for now.

You can check on any dep­re­ca­tion errors inside of Craft 3 by going to Util­i­ties → Dep­re­ca­tion Errors.

Craft 3 Cms Deprecation Errors

Craft 3 CMS Dep­re­ca­tion Errors

The oth­er real­ly inter­est­ing thing is that in Craft 3, the entire craft.app appli­ca­tion instance is avail­able to your Twig templates. 

What that means in real terms is that you can do any­thing with the Craft 3 APIs via Twig that you can via PHP. So many small plu­g­ins that were need­ed to expose some need­ed func­tion­al­i­ty may no longer be nec­es­sary at all.

Phpstorm Craft Auto Completion

Twig inspec­tion hint

One absolute­ly amaz­ing thing you can do if you’re using Php­Storm is get full auto-com­ple­tion of the entire craft. APIs in your Twig tem­plates, too! To do make the mag­ic hap­pen, install the Sym­fony plu­g­in, then Go to Pref­er­ences → Lan­guages & Frame­works → PHP → Sym­fony and check Enable Plu­g­in for this Project.

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

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

…and just like that, you get the same mag­ic auto-com­ple­tion of in your Twig tem­plates that you have in your PHP code. And since the entire Craft appli­ca­tion is avail­able in our Twig tem­plates now, this makes writ­ing Twig code that uses the Craft app APIs so much nicer.

Link Wrapping Up!

This is undoubtably the first of sev­er­al arti­cles I’ll be writ­ing on Craft 3. But hope­ful­ly it has giv­en you an idea of the lay of the land for Craft 3 development.

Go forth and make cool stuff!