Laravel Handbook
Laravel Handbook
Laravel Handbook
Preface
The Laravel Handbook
Conclusion
1
Preface
The Laravel Handbook follows the 80/20 rule: learn in 20% of the time the
80% of a topic.
Enjoy!
2
The Laravel Handbook
0. Table of contents
0. Table of contents
1. Introduction to Laravel
2. Getting started
3. Blade
4. Dynamic routes
5. Adding a database
6. How to use migrations to create and modify the database schema
7. Using forms to accept user input and store it into the database
8. Adding a better layout
9. Adding the form at the bottom of the list
10. Allow users to delete dogs from the list
11. Adding authentication using Laravel Breeze
12. Only authenticated users can add items to the database
13. Push the app code to GitHub
14. Deployment
15. Dynamic routes
16. Non-web routes
17. Creating commands
18. Where to go from here
The goal of this handbook is to get you up and running with Laravel, starting
from zero knowledge.
I will only teach you the basics, and once you’re done with this you’ll have the
knowledge you need to dive deeper.
1. Introduction to Laravel
3
Laravel is one of those legendary frameworks that everyone using it loves.
I would say Laravel, together with WordPress, is the “PHP killer app”.
PHP is often diregarded by developers, but it has some unique features that
make it a great language for Web Development and Laravel figured out how
to take advantage of the best features of PHP.
This is not a “new framework of the month” kind of thing. Laravel has been
around since 2011, well before modern frontend tools like React and Vue.js
existed.
It stood the test of time. And it evolved over the years to a serious and
complete solution for building Web Applications, which comes out of the box
complete with everything you need.
Things like Next.js or Remix appear very primitive in some aspects, while in
some other aspects they seem more modern.
And I think as Web Developers we must know in which scenario one tool is
more optimal than others. So we can make the best technical choice
depending on the requirements.
4
In this handbook I am going to give a introduction to Laravel to get you up
and running.
2. Getting started
To get started with Laravel, you need to set up your PHP environment on
your computer.
Before going on, remove any older PHP installations you might have done in
the past. How exactly depends on how you installed PHP on your machine.
Hopefully you haven’t any and we can go on.
Once installed you should be able to run the php -v command to get the
version of PHP installed (same for composer -v ):
5
Now you can go into folder on your computer that you reserve for
development. I have a dev folder in my home directory, for example.
In there, run:
cd first
php artisan serve
Open your browser and you’ll see the default welcome screen of a Laravel
app:
6
If you have troubles reaching this stage, the official documentation has great
guides for macOS, Linux and Windows.
7
While you’re here I recommend you install the extensions
8
For example in this portion of the file you can see we set the app name, the
debug flag, the URL, settings related to logging, to the database connection,
email sending and much more.
One very useful folder is config . Here’s for example the config/app.php
file:
9
Each file in the folder contain a lot of configuration options you can set, very
well documented.
What’s the difference between config files and the .env file? Environment
variables in .env can be changed depending on the deployment, for
example locally in development you can have debug enabled, while on the
production server you don’t want that.
Some options in config files, like the ones you see above, make use of the
env() Laravel helper function to get the environment variable.
While options stored directly in the config folder hardcoded are “one for all
environments”.
10
Open the routes folder and you’ll 4 files. Open web.php :
This is the code that displays the sample home page of the Laravel
application:
11
We made a request to the / relative URL ( http://127.0.0.1:8000/ ), which
means the “home page”.
This URL is handled in the routes/web.php file, which contains the router
dedicated to handling HTTP requests coming from the browser.
In this file, as shown in the screenshot, we tell Laravel to return the welcome
view when someone visits the / URL using the GET HTTP method (the one
used when you open the page in the browser):
Route::get('/', function () {
return view('welcome');
});
To do this we use the view() Laravel helper, which knows where to find the
welcome view because Laravel uses a set of conventions.
12
We have folders and files dedicated to holding specific, well-defined parts of
our applications.
You can clear all the content of this file, and type <h1>test</h1> into it. Save
(cmd-s or ctrl-s) and reload in the browser, the homepage content will switch
to displaying this string:
13
So now you know for sure that this file is responsible for what’s shown on
that URL!
In routes/web.php , add:
//...
Route::get('/test', function () {
return view('welcome');
});
This will render the welcome view also when the /test route is called:
14
You can show a different content by creating a new view in resources/views
and using that view in the route, for example create a new view
resources/views/test.blade.php
resources/views/test.blade.php
15
<h1>new view!</h1>
routes/web.php
//...
Route::get('/test', function () {
return view('test');
});
Notice that any URL that does not have a specific entry in routes/web.php
16
You can customize this error page. Here’s how: create an errors folder in
resources/views , and in there create a 404.blade.php file. Add any content,
like
You didn’t have to do anything more than creating the file, because Laravel
has this set of conventions, so adding a file in the right place with the right
name will do something specific.
3. Blade
The view files that end with .blade.php and are Blade templates.
In its basic form it’s HTML. As you can see, those templates I used above
don’t have anything other than HTML.
17
But you can do lots of interesting stuff in Blade templates: insert data, add
conditionals, do loops, display something if the user is authenticated or not,
or show different information depending on the environment variables (e.g.
if it’s in production or development), and much more.
Here’s a 101 on Blade (for more I highly recommend the official Blade guide).
Route::get('/test', function () {
return view('test', ['name' => 'Flavio']);
});
The {{ }} syntax allows you to add any data to the template, escaped.
Inside it you can also run any PHP function you like, and Blade will display
the return value of that execution.
There’s also @elseif , @unless which let you do more complex conditional
structures.
18
We also have @switch to show different things based on the result of a
variable.
@php
$cats = array("Fluffy", "Mittens", "Whiskers", "Felix");
@endphp
@for
@foreach
@while
Like this:
<ul>
@foreach ($cats as $cat)
<li>{{ $cat }}</li>
@endforeach
</ul>
19
Inside a loop a very convenient $loop variable is always available to tell us
information about the loop, for example if it’s the first iteration or the last, if
it’s even or odd, how many iterations were done and how many are left.
This is just a basic intro. We’ll see more about Blade with components later.
4. Dynamic routes
We’ve seen how to create static routes with Laravel.
This will be especially useful with databases, but let’s do an example without
first.
Route::get('test/{name}', function($name) {
return view('test', ['name' => $name]);
});
@if (isset($name))
<h1>Hello {{$name}}</h1>
@else
<h1>Test</h1>
@endif
Now if you navigate with your browser to the /test/flavio route, “flavio” is
the $name parameter in the route, which is passed to the view, so you can
print it in the Blade template:
20
Change the route parameter, the name in the HTML changes:
5. Adding a database
We’re using Laravel in a very basic form, without any database.
After we’ve configured the database, I’ll show you how to use forms to accept
user input and store data in the database, and how to visualize this data.
I’ll also show you how you can use data from the database with dynamic
routes.
21
Open the .env file, and instead of the default configuration
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
add
DB_CONNECTION=sqlite
From the terminal, stop the Laravel server and run this command to create a
new migration, which is what we will use to create the database table(s) we
need to use:
22
This command created the 2023_05_11_080724_initial_table_creation.php
file (the date and time will of course change for you) in the
database/migrations folder.
Notice there are other migrations, which are added by the Laravel framework
itself for it’s authentication system.
Let’s create a dogs table with 3 columns, an id ,a name string and the
timestamp utility columns ( created_at and updated_at , as we’ll see).
23
Schema::create('dogs', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
And Laravel will apply the migrations that have not been applied yet, which
at this point means all the migrations you see in the migrations folder:
24
If you open the database/database.sqlite file using a database visualization
tool like TablePlus (free version, available for all operating systems) you will
see the newly created tables, including the one we defined:
25
php artisan migrate:rollback
and this rolls back the latest changes you did to the database.
What’s a model? A model is a class that allows us to interact with data stored
in the database.
26
This creates a model in app/Models/Dog.php :
The model has a corresponding table, which we do not mention, but it’s the
dogs table we created beforehand because of the naming convention dogs
27
We’ll show the user a form and they can add a dog name, and click “Add” and
the dog will be added to the database.
First we add the name field we added to the table to an array named
$fillable :
Like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
A model is a resource, and once you define a model you’ll later be able to
create a new resource, delete, update it.
Route::get('/newdog', function () {
return view('newdog');
});
28
Laravel adds a DogController.php file into the folder app/Http/Controllers/
For example we’ll create a form that sends a POST request to the /dogs
route.
The router will say “this controller is in charge” and will tell us which method
to use.
Inside the controller we write methods that perform actions, like adding data
to the database, or updating it.
We will start by adding a create method to the controller to handle the data
coming from the form, so we can store that to the database.
Before doing so, in routes/web.php we add the POST /dogs route handle
controller and we assign it the name dog.create
We also add a /dogs route which we call dogs . We now render the dogs
use App\Http\Controllers\DogController;
//...
Route::post(
'/dogs',
[DogController::class, 'create']
)->name('dog.create');
Route::get('/dogs', function () {
return view('dogs');
})->name('dogs');
29
In resources/views/ create a newdog.blade.php file, which contains a form
whose action attribute points to the dog.create route:
30
Now back to the app/Http/Controllers/DogController.php file.
Inside the class we import the Dog model, and we add the create method
which will first validate the form, then store the dog into the database.
31
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Dog;
return to_route('index');
}
}
You will be redirected to /dogs , after the new dog was saved to the database.
32
In the browser there’s an error now but don’t worry - it’s because we haven’t
added a dogs view yet.
33
In this view we’ll visualize the database data.
This data does not come from nowhere. It must be passed to the template.
Route::get('/dogs', function () {
return view('dogs');
})->name('dogs');
34
and we have to first retrieve the data from the model, and pass it to the view.
use App\Models\Dog;
Then in the route we call Dog::all(); to get all the dogs stored and we
assign them to a $dogs variable which we pass to the template:
Route::get('/dogs', function () {
$dogs = Dog::all();
return view('dogs', ['dogs' => $dogs]);
})->name('dogs');
35
8. Adding a better layout
Now that we got data working, let’s clean up the routes a bit, add a more
beautiful design.
36
Remove test.blade.php and welcome.blade.php .
37
<?php
use Illuminate\Support\Facades\Route;
use App\Models\Dog;
/*
|-------------------------------------------------------------------------
| Web Routes
|-------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
Route::get('/newdog', function () {
return view('newdog');
});
Route::post(
'/dogs',
[DogController::class, 'create']
)->name('dog.create');
Route::get('/', function () {
$dogs = Dog::all();
return view('dogs', ['dogs' => $dogs]);
})->name('index');
Ok!
38
In resources/views/dogs.blade.php we now have a super simple
The browser renders that because it tries its best to display something useful,
but let’s do things properly.
Here’s a start: we add the proper HTML structure and we wrap the dogs list
in an unordered list:
39
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>
Dogs
</h1>
<ul>
@foreach ($dogs as $dog)
<li>{{ $dog->name }}</li>
@endforeach
</ul>
</body>
</html>
The next thing we’ll do is configure Vite, so we can enable styling using
Tailwind CSS, a very useful library.
40
First go back to the terminal.
Run this:
(see my npx tutorial if you’re new to that, it’s installed automatically with
Node.js, as npm ).
@tailwind base;
@tailwind components;
@tailwind utilities;
41
Finally, back to the terminal, run npm run dev and keep it running while
developing the site, as php artisan serve (run both in 2 different terminal
windows).
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
@vite('resources/css/app.css')
If you refresh the page, you can see immediately that something changed. It’s
Tailwind adding some default normalization, so that’s a sign it’s working!
42
Now we can add classes to our HTML body to style the page a bit:
<body class="p-4">
<h1 class="font-bold border-b-gray-300 border-b pb-2 mb-3">
Dogs
</h1>
<ul>
@foreach ($dogs as $dog)
<li>{{ $dog->name }}</li>
@endforeach
</ul>
</body>
43
Notice that changes are applied automatically when you save the file in VS
Code, without refreshing the page. Both changes in the Blade template, and
in the Tailwind CSS classes. That’s some “magic” provided by Vite and
Laravel in development mode.
Using the @include directive we can include a view within another view.
44
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
@vite('resources/css/app.css')
</head>
<body class="p-4">
<h1 class="font-bold border-b-gray-300 border-b pb-2 mb-3">
Dogs
</h1>
<ul>
@foreach ($dogs as $dog)
<li>{{ $dog->name }}</li>
@endforeach
</ul>
@include('newdog')
</body>
</html>
It works!
45
But now since we use Tailwind, the form looks different than the
“standalone” route to add a new dog:
46
Let’s style it a bit:
47
Now, we don’t want the form to have its own route any more, because we
have it on / .
In resources/views/dogs.blade.php change
@include('newdog')
to
@include('partials.form')
and in routes/web.php you can now delete the GET route that showed that
form on /newdog :
Route::get('/newdog', function () {
return view('newdog');
});
Here’s how.
48
<ul>
@foreach ($dogs as $dog)
<li class="flex mb-1">
<span class="flex-1">{{ $dog->name }}</span>
<form action="{{ route('dog.delete', $dog->id) }}"
method="POST">
@csrf
@method('DELETE')
<button type="submit" class="border
bg-gray-200 p-1 border-black">Delete</button>
</form>
</li>
@endforeach
</ul>
We use Flexbox to align the dog name and the delete button. Adding the
flex-1 class makes the text take all the space available, and “pushes” the
button to the far right.
Route::delete(
'/dog/{id}',
[DogController::class, 'delete']
)->name('dog.delete');
49
//...
return to_route('index');
}
}
This method uses the Dog model to find a dog with a specific id, which is
passed by the form, and deletes it calling the delete() method.
50
11. Adding authentication using
Laravel Breeze
We don’t want random people to come to the website and edit data.
51
To make things even easier, it provides Breeze, an application starter kit tool
that will create what we need in no time. Breeze scaffolds user registration,
login, password reset, profile page, dashboard… and even API authentication.
It’s great. For more advanced needs we also have JetStream, but Breeze is
easier to set up.
The first one was named first , so to continue the tradition we’ll call this
second project second :
cd second
Now run
and pick option 0, “blade”, and pick the default options for the other
questions artisan asks you:
52
Now you can run php artisan serve and go to http://127.0.0.1:8000/.
53
All the login functionality is working out of the box:
54
Laravel added a ton of resources to achieve this.
Easily days of work for a developer, and it’s battle-tested code which you
don’t want to write yourself, as it’s a quite important and needs to be well
tested for security issues.
55
I recommend you take a look at the file structure and compare it to the first
project. Lots of new stuff has been added, for example views:
But before we can go on, we have to set up the database for this project, doing
what we did in the first one. We go to the .env file and comment those
lines:
56
# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
and add
DB_CONNECTION=sqlite
Now run
In another terminal folder, run npm install followed by npm run dev ,
which is a long running process you’ll keep running alongside php artisan
serve ( ⚠ just make sure you’re running those in the second folder and not
the first project, I just spent 15 minutes trying to figure out why I had a
problem).
57
The Blade templates provided by Breeze use Tailwind CSS, and the setup of
Tailwind was done automatically when we ran php artisan breeze:install
58
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
@vite('resources/css/app.css')
</head>
<body class="p-4">
@if (Route::has('login'))
<div class="text-right">
@auth
<a href="{{ url('/dashboard') }}" class="">Dashboard</a>
@else
<a href="{{ route('login') }}" class="">Log in</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="ml-4">
Register</a>
@endif
@endauth
</div>
@endif
<div>
@auth
<p>Logged in</p>
@endauth
@guest
<p>Not logged in</p>
@endguest
</div>
</body>
</html>
59
@auth / @endauth and @guest / @endguest are two Blade directives that
allow you to show content (or not) depending on the logged in state.
60
Create an account and you will be shown a dashboard page at the
/dashboard route:
61
If you go back to the home, you will see the page in the logged in state:
62
12. Only authenticated users can
add items to the database
Now let’s re-implement what we did in the first project but this time we show
the dogs list when logged out, but we’ll only allow logged in users to modify
the data.
63
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('dogs');
}
};
We just modify the migration a little adding a name for the dog:
Save the file, go back to the terminal, run php artisan migrate
64
Now we scaffold the Dog model:
Go to routes/web.php .
use App\Models\Dog;
Route::get('/', function () {
return view('welcome');
});
and change it to this to retrieve the dogs list and pass it to the view, which we
label index :
Route::get('/', function () {
$dogs = Dog::all();
return view('welcome', ['dogs' => $dogs]);
})->name('index');
65
<h1 class="pb-2 mb-3 font-bold border-b border-b-gray-300">
Dogs
</h1>
<div>
@foreach ($dogs as $dog)
<li class="flex mb-1">
<span class="flex-1">{{ $dog->name }}</span>
</li>
@endforeach
@auth
<p>Logged in</p>
@endauth
@guest
<p>Not logged in</p>
@endguest
</div>
If you refresh the home you’ll see nothing changed because we don’t have any
dog in the list.
Instead of
66
@foreach ($dogs as $dog)
<li class="flex mb-1">
<span class="flex-1">{{ $dog->name }}</span>
</li>
@endforeach
use this:
We don’t have dogs in the table yet, but you can open the database using
TablePlus and insert data using this SQL query:
67
Now when we’re logged in I want to display the form to add a new dog, and
the delete button for each dog in the list.
First, inside the Dog model class we add the name to an array named
$fillable :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
68
php artisan make:controller DogController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
Add use App\Models\Dog; at the top, and add those 2 methods to the class,
create and delete , as we did before, but this time both first check that the
user is logged in:
69
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use App\Models\Dog;
return to_route('index');
}
}
Ok now we need a route to add a a new dog, and one to delete a dog. In
routes/web.php , add:
70
use App\Http\Controllers\DogController;
//...
Route::post(
'/dogs',
[DogController::class, 'create']
)->name('dog.create');
Route::delete(
'/dog/{id}',
[DogController::class, 'delete']
)->name('dog.delete');
71
Try clicking one “delete” button, the corresponding row should disappear.
72
Now let’s add the form to add a new dog. Before we used a partial, to see how
you can use partials, but now let’s just add it to the welcome template:
@auth
<form method="post" action="{{ route('dog.create') }}">
@csrf
<h3 class="pb-2 mt-4 mb-3 font-bold border-b border-b-gray-300">
Add a new dog</h3>
<div class="flex">
<div class="flex-1">
<label>Name</label>
<input type="text" name="name" id="name"
class="p-1 border border-gray-200 ">
</div>
<input type="submit" name="send" value="Submit"
class="p-1 bg-gray-200 border border-black
cursor-pointer">
</div>
</form>
@endauth
73
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
@vite('resources/css/app.css')
</head>
<body class="p-4">
@if (Route::has('login'))
<div class="text-right">
@auth
<a href="{{ url('/dashboard') }}" class="">Dashboard</a>
@else
<a href="{{ route('login') }}" class="">Log in</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="ml-4">
Register</a>
@endif
@endauth
</div>
@endif
<ul>
@forelse ($dogs as $dog)
<li class="flex mb-1">
<span class="flex-1">{{ $dog->name }}</span>
@auth
<form action="{{ route('dog.delete', $dog->id) }}"
method="POST">
@csrf
@method('DELETE')
<button type="submit"
class="p-1 bg-gray-200 border border-black">
Delete</button>
</form>
@endauth
</li>
74
@empty
<p>No dogs yet</p>
@endforelse
</ul>
@auth
<form method="post" action="{{ route('dog.create') }}">
@csrf
<h3 class="pb-2 mt-4 mb-3 font-bold border-b
border-b-gray-300">Add a new dog</h3>
<div class="flex">
<div class="flex-1">
<label>Name</label>
<input type="text" name="name" id="name"
class="p-1 border border-gray-200 ">
</div>
<input type="submit" name="send" value="Submit"
class="p-1 bg-gray-200 border border-black
cursor-pointer">
</div>
</form>
@endauth
</body>
</html>
75
Try it, it should work!
If you don’t have a GitHub account yet, and you have no idea what is Git,
check out
https://flaviocopes.com/git/
https://flaviocopes.com/github/
I want you to create a Git repository, push the repository to GitHub, so that
you have the code up there, ready to be deployed:
76
14. Deployment
77
It’s all fun and all, but now we want to deploy the application on a real server,
on the Internet, so people can use it.
Probably the best one is using Laravel Forge, the official deployment
platform, combined with DigitalOcean.
When it comes to servers, and unless you like managing servers and you’re
actually an expert, I am a fan of investing some money and saving time
instead.
Forge in particular is official, made by the core team of Laravel, lots and lots
of people use it (they claim over 500,000 sites are powered by Forge), and we
can trust that to work as expected.
Forge does not provide a server to you. But it’s a service that connects to
DigitalOcean and other VPS - virtual private server - providers like Hetzner,
AWS, Vultr and more and it creates a server for you on that platform.
You could directly use a VPS, of course. Follow a tutorial, set everything up,
invest hours into basically doing what Forge can do with a few simple steps.
It’s a matter of convenience.
And in the long run, Forge can upgrade PHP for example with a simple click.
If that’s left to you to manage, it’s more complicated.
Anyway, pick your poison. Spend time and effort, or spend some money and
focus on your app.
How much money? Not much, $12/month. And it has a free trial.
78
Once you’re in, click “Connect to GitHub” to connect Forge to GitHub so it
can pull your code:
79
80
Now it’s time to connect to a server provider.
I pick DigitalOcean.
81
If you’re unsure, DigitalOcean gives you free credits, so you can try it out.
82
and finally I copy the code to Forge.
83
Here’s where you need to create the subscription. I picked the Hobby plan for
$12/m, with a free trial of 5 days:
84
Here you can change the type of server you want to create. Pick “App Server”
as it contains all you’re going to need.
Pick a region near you, and pick a modest server size, so you can save on
server costs until someone actually uses your app (you can always upgrade
the server later via the DigitalOcean panel)
85
I picked Postgres because I like that more, but it’s just a preference.
86
It will take some minutes, after which you’ll have your server up and running.
A server perfectly configured to run Laravel, already set up with the Nginx
server, database, and much more.
Once it’s done, here is the control panel of your server. On the left, there’s a
menu that gives you access to specific menus.
87
For example you have access to server logs through “Logs”:
88
You can see the scheduled jobs in “Scheduler”:
89
…and lots more.
You can restart the entire server, or specific services, throught the Restart
drop down menu:
90
which is very handy, and you can deploy new sites on this server.
There is a default one already set up, and if you copy and paste the public IP
address of the server in your browser, you’ll see it working:
91
Now let’s deploy the application on this site.
Ideally what you want to do is, you create a new site with a domain /
subdomain assigned.
But it’s starting to become complicated for this handbook, so we’ll just use
the default site which works on the IP address instead.
Click the default site in the dashboard and you’ll see the site panel:
92
We have the site in GitHub, so click “Git Repository”:
93
Now type the name of the repository you want to deploy prefixed with the
GitHub account name, in my case flaviocopes/second , select the branch
(usually main ) and click Install Repository.
94
Mmmm! We don’t see more details because now the site is in a production
environment, and we don’t show detailed logs to users.
To figure out the problem let’s go back to the panel, open Logs and you’ll see
the error is related to connecting to the database.
95
If you look closely in the GitHub repository you will see the .env file was
not pushed to GitHub, and this is correct because you don’t want to store the
environment variables in Git.
In the Forge site config click the Environment tab, this is where you will
edit your environment variables:
96
Comment the DB_* fields and add
DB_CONNECTION=sqlite
97
If you go to the deployments menu you can inspect the deployment output,
which is handy:
98
If the build fails, you’ll get an alert and also an email, pretty nice.
The build seems to work fine but if you reload the browser we have another
error now. Something about Vite.
Now we have to run npm run build , after running npm install .
We need to update our Deploy Script from the App tab, adding this at the
end:
npm install
npm run build
99
Then click Update and Deploy Now.
Now it works!
100
Also try registering in, it will work as expected and we’ll be able to add and
edit data:
We could spend more time on this topic, but there’s so much more to explore.
We’ve seen how to create a Web Application, as simple as it could be, just a
form that stores a field into a database, but complete with ready-made
authentication provided by the Breeze starter kit.
We’ve seen basic routing, and models, views and controllers interact to store
and retrieve data through the Eloquent ORM.
101
Route::get('/dogs', function () {
return view('dogs');
})->name('dogs');
Now suppose you want to create a page for each single dog, maybe you’ll fill
that with a description, an image, whatever.
You can’t create a static route for each dog in the database, because you don’t
know the name of the dog.
Imagine you have 2 dogs Max and Daisy, this would display a “dog” view
(which we don’t have yet) on the /dogs/max and /dogs/daisy :
Route::get('/dogs/max', function () {
return view('dog');
})
Route::get('/dogs/daisy', function () {
return view('dog');
})
Route::get('/dogs/{slug}', function () {
return view('dog');
})
Now we can pass the slug value to the callback function (the function that’s
called when the route is hit), and inside the function we can pass it to the
view:
102
Route::get('/dogs/{slug}', function ($slug) {
return view('dog', ['slug' => $slug]);
})
But we want to retrieve the actual dog data. We have the slug, which we can
imagine it’s stored in the database when we add the dog.
use App\Models\Dog;
103
php artisan serve
104
And to see how to use a command in particular, run php artisan <command> -
h :
105
You can create your own commands, too.
Run
106
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*/
public function handle()
{
//
}
}
$signature defines how the command will be called, in this case you can run
it using
In the handle() method you’ll write the code that runs when the command
is executed.
107
public function handle()
{
//
}
The simplest code could be printing something to the console, for example:
Commands are great to perform one-off tasks, maintenance, and much more.
Inside a command you have access to all the goodies provided by Laravel,
including your own code, classes, and more.
You can also call other commands. And commands can be ran by any part of
your Laravel app.
You can also schedule commands using schedules. The server can be
configured to run Laravel’s schedules, and then any schedule configured in
Laravel will be executed as needed.
108
18. Where to go from here
We've reached the end of the handbook!
Definitely not a complete guide. But I think that now you can go start
building an app using Laravel.
109
Conclusion
Thanks a lot for reading this book.
110