We'll be using Laravel 5.8. You can see the list of articles in this series here.
Run composer create-project --prefer-dist laravel/laravel address-book
to install.
Go ahead and setup your .env
file to suit your needs. Also create a .env.testing
file that will contain your test configurations (eg a test database).
Let's modify our JS setup as we'll be using VueJS to create our front-end views. Replace the contents of webpack.mix.js
with this:
let mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.extract(Object.keys(require('./package.json').dependencies || []))
.sass('resources/sass/app.scss', 'public/css')
.version();
Modify package.json
as shown below and run npm install
.
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.18",
"bootstrap": "^4.3.1",
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^4.0.15",
"popper.js": "^1.15.0",
"resolve-url-loader": "^2.3.1",
"sass": "^1.18.0",
"sass-loader": "^7.1.0",
"vue": "^2.6.10",
"vue-template-compiler": "^2.6.10",
"vue-trix": "^0.7.7"
}
}
Delete the tests/Unit
folder.
Install the event-sourcing library by typing composer require spatie/laravel-event-projector:^2.0.0
(requires >= PHP 7.3), and running php artisan vendor:publish --provider="Spatie\EventProjector\EventProjectorServiceProvider" --tag="migrations"
and php artisan vendor:publish --provider="Spatie\EventProjector\EventProjectorServiceProvider" --tag="config"
Also install Laravel Passport (which we'll use for API authentication) using composer require laravel/passport
.
Add the line below to the boot()
method of app/Providers/AppServiceProvider.php
to force all URLs to use the HTTPS scheme. Without that, you might run into issues where assets try to load over HTTP.
if (config('app.env') === 'production') \URL::forceScheme('https');
We'll need a common layout for our views. Let's create resources/views/layouts/app.blade.php
and paste the following template into it:
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Address Book') }}</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md navbar-light navbar-laravel">
<div class="container">
@guest
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name', 'Address Book') }}
</a>
@else
<a class="navbar-brand" href="{{ route('contacts') }}">
{{ config('app.name', 'Address Book') }}
</a>
@endguest
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Authentication Links -->
@guest
<li><a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a></li>
<li><a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a></li>
@else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ Auth::user()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
@csrf
</form>
</div>
</li>
@endguest
</ul>
</div>
</div>
</nav>
<main class="py-4">
@yield('content')
</main>
</div>
<script type="text/javascript" src="{{ asset('js/manifest.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/vendor.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/app.js') }}"></script>
</body>
</html>
We're done with the preparatory steps. In the next article, we'll be implementing user accounts.
You can explore the changes here.