Chapter 2. Setting Up a Laravel Development Environment

Part of PHP’s success has been because it’s hard to find a web server that can’t serve PHP. However, modern PHP tools have stricter requirements than those of the past. The best way to develop for Laravel is to ensure a consistent local and remote server environment for your code, and thankfully, the Laravel ecosystem has a few tools for this.

System Requirements

Everything we’ll cover in this chapter is possible with Windows machines, but you’ll need dozens of pages of custom instructions and caveats. I’ll leave those instructions and caveats to actual Windows users, so the examples here and in the rest of the book will focus on Unix/Linux/macOS developers.

Whether you choose to serve your website by installing PHP and other tools on your local machine, serve your development environment from a virtual machine via Vagrant or Docker, or rely on a tool like MAMP/WAMP/XAMPP, your development environment will need to have all of the following installed in order to serve Laravel sites:

  • PHP >= 7.1.3 for Laravel versions 5.6 and 5.7, PHP >= 7.0.0 for version 5.5, PHP >= 5.6.4 for version 5.4, PHP between 5.6.4 and 7.1.* for version 5.3 and PHP >= 5.5.9 for versions 5.2 and 5.1

  • OpenSSL PHP extension

  • PDO PHP extension

  • Mbstring PHP extension

  • Tokenizer PHP extension

  • XML PHP Extension (Laravel 5.3 and higher)

  • Ctype PHP Extension (Laravel 5.6 and higher)

  • JSON PHP Extension (Laravel 5.6 and higher)

Composer

Whatever machine you’re developing on will need to have Composer installed globally. If you’re not familiar with Composer, it’s a tool that’s at the foundation of most modern PHP development. Composer is a dependency manager for PHP, much like NPM for Node or RubyGems for Ruby. But like NPM, Composer is also the foundation of much of our testing, local script loading, installation scripts, and much more. You’ll need Composer to install Laravel, update Laravel, and bring in external dependencies.

Local Development Environments

For many projects, hosting your development environment using a simpler tool set will be enough. If you already have MAMP or WAMP or XAMPP installed on your system, that will likely be fine to run Laravel. You can also just run Laravel with PHP’s built-in web server, assuming your system PHP is the right version.

All you really need to get started is the ability to run PHP. Everything past that is up to you.

However, Laravel offers two tools for local development, Valet and Homestead, and we’ll cover both briefly. If you’re unsure of which to use, I’d recommend using Valet and just becoming briefly familiar with Homestead; however, both tools are valuable and worth understanding.

Laravel Valet

If you want to use PHP’s built-in web server, your simplest option is to serve every site from a localhost URL. If you run php -S localhost:8000 -t public from your Laravel site’s root folder, PHP’s built-in web server will serve your site at http://localhost:8000/. You can also run php artisan serve once you have your application set up to easily spin up an equivalent server.

But if you’re interested in tying each of your sites to a specific development domain, you’ll need to get comfortable with your operating system’s hosts file and use a tool like dnsmasq. Let’s instead try something simpler.

If you’re a Mac user (there are also unofficial forks for Windows and Linux), Laravel Valet takes away the need to connect your domains to your application folders. Valet installs dnsmasq and a series of PHP scripts that make it possible to type laravel new myapp && open myapp.test and for it to just work. You’ll need to install a few tools using Homebrew, which the documentation will walk you through, but the steps from initial installation to serving your apps are few and simple.

Install Valet (see the docs for the latest installation instructions), and point it at one or more directories where your sites will live. I ran valet park from my ~/Sites directory, which is where I put all of my under-development apps. Now, you can just add .test to the end of the directory name and visit it in your browser.

Valet makes it easy to serve all folders in a given folder as “FOLDERNAME.test” using valet park, to serve just a single folder using valet link, to open the Valet-served domain for a folder using valet open, to serve the Valet site with HTTPS using valet secure, and to open an ngrok tunnel so you can share your site with others with valet share.

Laravel Homestead

Homestead is another tool you might want to use to set up your local development environment. It’s a configuration tool that sits on top of Vagrant (which is a tool for managing for virtual machines) and provides a pre-configured virtual machine image that is perfectly set up for Laravel development, and mirrors the most common production environment that many Laravel sites run on. Homestead is also likely the best local development environment for developers running Windows machines.

The Homestead docs are robust and kept constantly up-to-date, so I’ll just refer you to them if you want to learn how it works and how to get it set up.

Vessel

It’s not an official Laravel project, but Chris Fidao of Servers for Hackers and Shipping Docker created a simple tool for creating Docker environments for Laravel development called Vessel. Take a look at the Vessel documentation to learn more.

Creating a New Laravel Project

There are two ways to create a new Laravel project, but both are run from the command line. The first option is to globally install the Laravel installer tool (using Composer); the second is to use Composer’s create-project feature.

You can learn about both options in greater detail on the Installation documentation page, but I’d recommend the Laravel installer tool.

Installing Laravel with the Laravel Installer Tool

If you have Composer installed globally, installing the Laravel installer tool is as simple as running the following command:

composer global require "laravel/installer"

Once you have the Laravel installer tool installed, spinning up a new Laravel project is simple. Just run this command from your command line:

laravel new projectName

This will create a new subdirectory of your current directory named projectName and install a bare Laravel project in it.

Installing Laravel with Composer’s create-project Feature

Composer also offers a feature called create-project for creating new projects with a particular skeleton. To use this tool to create a new Laravel project, issue the following command:

composer create-project laravel/laravel projectName

Just like the installer tool, this will create a subdirectory of your current directory named projectName that contains a skeleton Laravel install, ready for you to develop.

Lambo: Super-powered “Laravel New”

Because I often take the same series of steps after creating a new Laravel project, I made a simple script called Lambo that automates those steps every time I create a new project.

Lambo runs laravel new, and then commits your code to Git, sets up your .env credentials with reasonable defaults, opens the project in a browser, and (optionally) opens it in your editor and takes a few other helpful build steps.

You can install Lambo using Composer’s global require:

composer global require tightenco/lambo

And you can use it just like laravel new:

cd Sites
lambo my-new-project

Laravel’s Directory Structure

When you open up a directory that contains a skeleton Laravel application, you’ll see the following files and directories:

app/
bootstrap/
config/
database/
public/
resources/
routes/
storage/
tests/
vendor/
.editorconfig
.env
.env.example
.gitattributes
.gitignore
artisan
composer.json
composer.lock
package.json
phpunit.xml
readme.md
server.php
webpack.mix.js
Note

In projects created prior to Laravel 5.4, you’ll likely see a gulpfile.js instead of webpack.mix.js; this shows the project is running Laravel Elixir instead of Laravel Mix.

Let’s walk through them one by one to get familiar.

The Folders

The root directory contains the following folders by default:

  • app is where the bulk of your actual application will go. Models, controllers, commands, and your PHP domain code all go in here.

  • bootstrap contains the files that the Laravel framework uses to boot every time it runs.

  • config is where all the configuration files live.

  • database is where database migrations, seeds, and factories live.

  • public is the directory the server points to when it’s serving the website. This contains index.php, which is the front controller that kicks off the bootstrapping process and routes all requests appropriately. It’s also where any public-facing files like images, stylesheets, scripts, or downloads go.

  • resources is where files that are needed for other scripts live. Views, language files, and (optionally) Sass/Less/source CSS and source JavaScript files live here.

  • routes is where all of the route definitions live, both for HTTP routes and “console routes,” or Artisan commands.

  • storage is where caches, logs, and compiled system files live.

  • tests is where unit and integration tests live.

  • vendor is where Composer installs its dependencies. It’s Git-ignored (marked to be excluded from your version control system), as Composer is expected to run as a part of your deploy process on any remote servers.

The Loose Files

The root directory also contains the following files:

  • .editorconfig gives your IDE/text editor instructions about Laravel’s coding standars (e.g. the size of indents, the charset, and whether to trim trailing whitespace). You’ll see in this in all versions of Laravel but only in projects created more recently.

  • .env and .env.example are the files that dictate the environment variables (variables that are expected to be different in each environment and are therefore not committed to version control). .env.example is a template that each environment should duplicate to create its own .env file, which is Git-ignored.

  • .gitignore and .gitattributes are Git configuration files.

  • artisan is the file that allows you to run Artisan commands (see Chapter 8) from the command line.

  • composer.json and composer.lock are the configuration files for Composer; composer.json is user-editable and composer.lock is not. These files share some basic information about this project and also define its PHP dependencies.

  • package.json is like composer.json but for frontend assets and dependencies of the build system; it instructs NPM on which JavaScript-based dependencies to pull in.

  • phpunit.xml is a configuration file for PHPUnit, the tool Laravel uses for testing out of the box.

  • readme.md is a Markdown file giving a basic introduction to Laravel. You won’t see this file if you use the Laravel installer.

  • server.php is a backup server that tries to allow less-capable servers to still preview the Laravel application.

  • webpack.mix.js or gulpfile.js is the (optional) configuration file for Mix (webpack.mix.js) or Elixir (gulpfile.js). These files are for giving your build system directions on how to compile and process your frontend assets.

Configuration

The core settings of your Laravel application—database connection, queue and mail settings, etc.—live in files in the config folder. Each of these files returns a PHP array, and each value in the array will be accessible by a config key that is comprised of the filename and all descendant keys, separated by dots (.)

So, if you create a file at config/services.php that looks like this:

<?php
return [
    'sparkpost' => [
        'secret' => 'abcdefg',
    ],
];

You will now have access to that config variable using config('services.sparkpost.secret').

Any configuration variables that should be distinct for each environment (and therefore not committed to source control) will instead live in your .env files. Let’s say you want to use a different Bugsnag API key for each environment. You’d set the config file to pull it from .env:

// config/services.php
<?php
return [
    'bugsnag' => [
        'api_key' => env('BUGSNAG_API_KEY'),
    ],
];

This env() helper function pulls a value from your .env file with that same key. So now, add that key to your .env (settings for this environment) and .env.example (template for all environments) files:

# In .env
BUGSNAG_API_KEY=oinfp9813410942
# In .env.example
BUGSNAG_API_KEY=

Your .env file already contains quite a few environment-specific variables needed by the framework, like which mail driver you’ll be using and what your basic database settings are.

Using env() outside of config files

Certain features in Laravel, including some caching and optimization features, aren’t available if you use env() calls anywhere outside of config files.

The best way to pull in environment variables is to set up config items for anything you want to be environment-specific. Have those config items read the environment variables, and then reference the config variables anywhere within your app:

// config/services.php
return [
    'bugsnag' => [
        'key' => env('BUGSNAG_API_KEY')
    ]
];

// in controller, or whatever
$bugsnag = new Bugsnag(config('services.bugsnag.key'));

The .env file

Let’s take a quick look at the default contents of the .env file. The exact keys will vary depending on which version of Laravel you’re using, but take a look at Example 2-1 to see what they look like in 5.7.

Example 2-1. The default environment variables in Laravel 5.7
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

I won’t go into all of them, because quite a few (Pusher, Redis, DB, Mail) are just groups of authentication information for various services. Here are two important environment variables you should know, though:

  • APP_KEY is a randomly-generated string that’s used to encrypt data. If this is ever empty, you may run into the error “No application encryption key has been specified”. If so, just run php artisan key:generate and Laravel will generate one for you.

  • APP_DEBUG is a boolean determining whether the users of this instance of your application should see debug errors. Great for local and staging; terrible for production.

The rest of the non-authentication settings (BROADCAST_DRIVER, QUEUE_CONNECTION, etc.) are given default values that work with as little reliance on external services as possible, which is perfect for when you’re getting started.

When you start your first Laravel app, the only change you’ll likely want to make on most projects is to the database configuration settings. Since I use Laravel Valet, I change DB_DATABASE to the name of my project, DB_USERNAME to root, and DB_PASSWORD to an empty string. And then, I go create a database with the same name as my project in my favorite MySQL client. Ready to go.

DB_DATABASE=myProject
DB_USERNAME=root
DB_PASSWORD=

Up and Running

You’re now up and running with a bare Laravel install. Run git init, commit the bare files with git add . and git commit, and you’re ready to start coding. That’s it! And if you’re using Valet, you can run the following commands and instantly see your site live in your browser:

laravel new myProject && cd myProject && valet open

Every time I start a new project, these are the steps I take:

laravel new myProject
cd myProject
git init
git add .
git commit -m "Initial commit"

I keep all of my sites in a ~/Sites folder, which I have set up as my primary Valet directory, so in this case I’d instantly have myProject.test accessible in my browser with no added work. I can edit .env and point it to a particular database, add that database in my MySQL app, and I’m ready to start coding. And remember, if you use Lambo, all of these steps are already taken for you.

Testing

In every chapter after this, the “Testing” section at the end of the chapter will show you how to write tests for the feature or features that were covered. Since this chapter doesn’t cover a testable feature, let’s talk tests quickly. (To learn more about writing and running tests in Laravel, head over to Chapter 12.)

Out of the box, Laravel brings in PHPUnit as a dependency and is configured to run the tests in any file in the tests directory whose name ends with Test.php (for example, tests/UserTest.php).

So, the simplest way to write tests is to create a file in the tests directory with a name that ends with Test.php. And the easiest way to run them is to run ./vendor/bin/phpunit from the command line (in the project root).

If any tests require database access, be sure to run your tests from the machine where your database is hosted—so if you’re hosting your database in Vagrant, make sure to ssh into your Vagrant box to run your tests from there. Again, you can learn about this and much more in Chapter 12.

Also, some of the testing sections will use testing syntax and features that you will not be familiar with yet if you’re just reading the book for the first time. If code in any of the testings section is confusing, just skip it and come back to it after you’ve had a chance to read the testing chapter.

TL;DR

Since Laravel is a PHP framework, it’s very simple to serve it locally. Laravel also provides two tools for managing your local development: a simpler tool called Valet that uses your local machine to provide your dependencies, and a preconfigured Vagrant setup named Homestead. Laravel relies on, and can be installed by, Composer, and comes out of the box with a series of folders and files that reflect both its conventions and its relationship with other open source tools.