Professional Documents
Culture Documents
The Laravel Survival Guide
The Laravel Survival Guide
2. Routing ........................................................................................ 18
Routing overview ......................................................................... 18
Routing in Laravel ....................................................................... 19
Quick Routing example ............................................................... 21
Route Closures vs Route Controller Actions ................................ 22
Route Parameters ........................................................................ 23
3. Models .......................................................................................... 25
What Are Models? ........................................................................ 25
Eloquent: The Laravel ORM ......................................................... 26
6. Views ............................................................................................ 44
Understanding Views ................................................................... 44
7. Blade ............................................................................................ 48
Blade Templating ........................................................................ 48
8. Controllers ................................................................................... 52
Understanding Controllers ........................................................... 52
By mastering the basics of Laravel, you can save yourself, and possibly
others, from becoming a mindless zombie developer.
Don't let the inner zombie thrive; keep close the Laravel survival guide.
6
7
1. Getting Started
Let's do this!
If you are a Mac user it will be scary easy to setup a local development
environment on your machine. Laravel now offers a native application
called Herd. Simply download the application here, install it, and you're
ready to start building.
8
the application at https://herd.laravel.com, install, and you're ready to
start building.
https://www.mamp.info/en/
http://www.wampserver.com/en/
https://www.apachefriends.org/
If you are on an Ubuntu machine you can use Xampp, or you may
choose to install all the applications individually. You can learn more
about how to do that from this article here.
Once these services are in place on your machine, you're all set! At the
end of the day there is no right or wrong way to setup a local dev
environment. Find a way that works best for you and you'll be on the
road to creating some killer web applications in no time!
9
Composer & The Laravel Installer
Composer
10
{
"toppings" : [
"pepperoni", "ham", "bacon", "beef", "sausage"
]
}
Voilà! Instead of the default pepperoni pizza, we now have our meat-
lovers pizza!
Replace project-name with the desired name for your new project. This
command will create a directory with the given name and install a fresh
Laravel application inside it.
11
Installing the Laravel Installer
To use the Laravel installer, open up a command prompt and type the
following command:
When you run this command you'll encounter several prompts; choose
No starter kit, PHPUnit, and No respectively. Also, when asked about
the database, opt for MySQL.
12
_ _
| | | |
| | __ _ _ __ __ ___ _____| |
| | / _` | '__/ _` \ \ / / _ \ |
| |___| (_| | | | (_| |\ V / __/ |
|______\__,_|_| \__,_| \_/ \___|_|
Note: If you're using Laravel Herd, your new Laravel apps will use the
.test domain. For instance, https://folder_name.test will present the
welcome page.
13
Congrats! You're now ready to start building amazing applications. The
ease of Laravel ensures you can resurrect a new project in mere
moments.
Before we dive into the code let's briefly get acquainted with Laravel's
folder structure.
In a new laravel project you will have the following code structure:
1. app
2. bootstrap
3. config
4. database
5. public
14
6. resources
7. routes
8. storage
9. tests
10. vendor
We will not go into full detail with all the files; however, it's important to
have a brief understanding of each folder.
App
This is the directory that has all our application logic. In this folder, we
will put all our models, controllers, services, and many other classes.
Bootstrap
Config
This file will contain many of our global configurations for our
application.
Database
This folder contains our database files such as migrations and seeds.
Public
Resources
We will put our view files in this folder. The views are the pages that a
user sees.
15
Routes
Storage
Laravel uses this folder to store sessions, caches, and logs in this folder.
Test
This folder contains files that we use to test the logic of our application.
Vendor
This is the folder that contains our dependencies. When you add new
libraries (toppings) to your app, this is the folder that will contain those
libraries.
Great job! You're going to love working with Laravel. Next, let's get our
hands dirty and dig into some code.
16
17
2. Routing
Routing overview
You can think of a route as being similar to a road. For instance, "We
drove down the road (route) to get to the graveyard." A route defines
how you get from one location to another. When you type a website
URL like site.com/graveyard, you are telling the browser that the
graveyard is the route you want to take. The application then says, "Ok,
you want to go to the 'graveyard'? This is the output I have for the
graveyard route."
<?php
Route::get('graveyard', function(){
echo 'Welcome to the graveyard!';
});
Here, the route for our graveyard page is defined. The application,
when prompted to 'get' the 'graveyard' pathway, will execute the
function, showcasing the message 'Welcome to the graveyard!'.
18
Routing in Laravel
<?php
Route::post('/zombie', function () {
echo "We want to create a new zombie";
});
Route::get('/zombie', function () {
echo 'We want to read or view a zombie';
});
Route::put('/zombie', function () {
echo "We want to update an existing zombie";
});
Route::delete('/zombie', function () {
echo "We want to destroy a zombie";
});
Most often we will use the GET method, but there is also a route we can
use to capture any method:
19
<?php
Route::any('/zombie', function () {
echo "Any request from this zombie route";
});
Great!
So, how do we initiate our routes from a browser? For most cases, we'd
use the GET request. Typing in site.com/zombie directs us to the GET
function. But how about POSTing data?
For PUT and DELETE methods, a hidden input specifies the intended
method:
20
<!-- PUT METHOD -->
<form method="POST" action="/zombie">
...
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="' . csrf_token()
. '">
<input type="submit">
</form>
These forms send data to the PUT and DELETE routes respectively.
Imagine you're faced with the task of killing (deleting) a rogue zombie!
21
<?php
use Illuminate\Http\Request;
And just like that, the troublesome zombie with ID 2 is no more! Note
the inclusion of the Request class from Laravel, which captures request
data. You'll have to remember to declare the namespace when you
want to make use of the request object.
Heads up! This example won't be fully operational yet since our
database and models are still in the making. We'll tackle that soon.
We've been using route closures. Next, let's discuss the difference
between route closures and route controllers.
Route::get('/zombie', function(){
echo 'Greetings from the Zombie Page!';
});
22
We'll explore Controllers further soon. Keep these distinctions in mind;
they'll become clearer.
Route Parameters
Route::get('/zombie/{id}', function($id){
echo "You've encountered a zombie with ID: " . $id;
});
Should our models and database be in place, this will retrieve and
display a specific zombie's details:
Route::get('/zombie/{id}', function($id){
$zombie = Zombie::find($id);
echo 'Name: ' . $zombie->name . '<br />';
echo 'Strength: ' . $zombie->strength . '<br />';
echo 'Health: ' . $zombie->health . '<br />';
});
23
24
3. Models
Zombie Developers often use complicated queries that can lead to bad
and infectious code. As a Laravel developer we must keep our queries
strong & healthy.
use Illuminate\Database\Eloquent\Model;
This code informs Laravel that the Zombie class corresponds to the
zombies table in your database. A hypothetical zombies table might
resemble:
zombies table
25
| Field | Type | Length |
|-------------|-----------|--------|
| id | INT | 11 |
| name | VARCHAR | 50 |
| strength | VARCHAR | 20 |
| health | INT | 3 |
| updated_at | TIMESTAMP | |
| created_at | TIMESTAMP | |
With the aforementioned table in place, we can now interact with the
database using Eloquent.
26
<?php
use App\Models\Zombie;
Route::get('/zombie/{id}', function($id){
$zombie = Zombie::find($id);
echo 'Name: ' . $zombie->name . '<br />';
echo 'Strength: ' . $zombie->strength . '<br />';
echo 'Health: ' . $zombie->health . '<br />';
});
Previously, our application couldn't locate the Zombie class, but with
the model in place, we can access it without a hitch.
27
<?php
Route::get('/admin/zombies/create', function(){
});
<?php
Route::post('/admin/zombies/create', function () {
// create a new zombie
});
28
<?php
use App\Models\Zombie;
use Illuminate\Http\Request;
Route::post('/admin/zombies/create', function(Request
$request){
29
<?php
use App\Zombie;
use Illuminate\Http\Request;
Route::post('/admin/zombies/create', function(Request
$request){
use Illuminate\Database\Eloquent\Model;
30
effortlessly created.
31
32
4. Model Relationships
Model Relationships
Relationships bind data across tables. Imagine you manage a blog with
'posts' and 'comments' tables.
weapons table
Note the 'zombie_id' column above. It refers to the 'id' column in the
Zombies table. This connection, known as a Foreign Key, occurs when
one table's row distinctly identifies another table's row. This Foreign
Key solidifies the link between the Weapons and Zombies tables.
33
Above, you see that we've included an "Axe" for the zombie with ID 2
and a "Shot Gun" for the zombie with ID 1.
use Illuminate\Database\Eloquent\Model;
To display our zombie's details, including their weapon, we can use this
code:
34
<?php
Route::get('/zombie/{id}', function($id){
$zombie = Zombie::find($id);
echo 'Name: ' . $zombie->name . '<br />';
echo 'Strength: ' . $zombie->strength . '<br />';
echo 'Health: ' . $zombie->health . '<br />';
$weapon = Weapon::where('zombie_id',
$zombie->id)->first();
echo 'Weapon: ' . $weapon->name . '<br />';
});
use Illuminate\Database\Eloquent\Model;
Having updated our Zombie Model, let's rework our previous code:
35
<?php
Route::get('/zombie/{id}', function($id){
$zombie = Zombie::find($id);
echo 'Name: ' . $zombie->name . '<br />';
echo 'Strength: ' . $zombie->strength . '<br />';
echo 'Health: ' . $zombie->health . '<br />';
echo 'Weapon: ' . $zombie->weapon->name . '<br />';
});
36
Lastly, if we possess a weapon's ID and wish to identify its zombie
owner, we can:
use Illuminate\Database\Eloquent\Model;
Route::get('/weapon/{id}', function($id){
$weapon = Weapon::find($id);
echo "This " . $weapon->name . " belongs to " .
$weapon->zombie->name;
});
37
Laravel's relationship features make data interactions both intuitive and
delightful.
38
39
5. Mutators and Accessors
Recall the zombies table from our previous chapters. Suppose we aim
for a consistent presentation of zombie names, ensuring each name is
capitalized. This is where Accessors come to our rescue.
The name of the function must be the name of the column. We must also
include the Attributes namespace in our model.
40
use Illuminate\Database\Eloquent\Casts\Attribute;
Here's how our complete Zombie Model would appear with both the
Mutator and Accessor:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
41
Mutators and Accessors are another testament to Laravel's versatility,
making developers' tasks simpler and more intuitive.
42
43
6. Views
In this chapter, we're going to talk about using views. Leveraging the
powerful features of Laravel will help us gain a clear VIEW of what we
want to build (sorry for the cheesy pun).
Understanding Views
At their core, views are the HTML and layout elements that construct a
page. Simply put, it's what users see when they access a page.
Route::get('graveyard', function(){
echo 'Welcome to the graveyard!';
});
To replicate the above functionality with a view, we'd modify our code
to:
Route::get('graveyard', function(){
return view('graveyard');
});
44
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<p>Welcome to the graveyard!</p>
</body>
</html>
The outcome aligns with the initial view. But, by using the view, we're
incorporating valid HTML, adhering to best practices in code structure
and data presentation.
Imagine wanting to retrieve all the zombies from our database and
presenting them in our view. The process is very simple. The route
would appear as:
Route::get('zombies', function(){
$data = ['zombies' => Zombie::all()];
return view('zombies', $data);
});
This would forward all our zombies to a view titled zombies.php located
in the resources/views/ folder. We can modify that file and loop
through our zombies like so:
45
<html>
<head>
<title>Zombies</title>
</head>
<body>
<ul>
<?php foreach($zombies as $zombie): ?>
<li><?php echo $zombie->name; ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>
To funnel data into your views, simply pack the variables into an array
and relay it as the second parameter within the view function.
46
47
7. Blade
Using Blade Templating in your app will make your views look super
clean and easily readable. Blade templating is optional to use, but after
you get the hang of it, you'll find yourself wanting to use it all the time.
Blade Templating
<ul>
<?php foreach($zombies as $zombie): ?>
<li><?php echo $zombie->name; ?></li>
<?php endforeach; ?>
</ul>
<ul>
@foreach($zombies as $zombie)
<li>{{ $zombie->name }}</li>
@endforeach
</ul>
48
As demonstrated, rather than traditionally enclosing a foreach loop
within PHP tags, the @ symbol offers a cleaner alternative. Also, the {{
}} syntax auto-renders its content.
@if($var)
The statement is true. The variable is equal to {{ $var }}
@else
The statement is false. The variable is equal to {{ $var
}}
@endif
49
Having grasped the essence of Views in a Laravel application, our next
pit stop is Controllers—the epicenter of our app's functionality.
50
51
8. Controllers
Understanding Controllers
Models retrieve and store data in our database, Views are responsible
for what the user sees in the browser, and Controllers dictate how
data flows between Models and Views. You'll find the controllers for
your application in the app\Http\Controllers directory.
Route::get('/zombie', function(){
echo 'Welcome to the Zombie Page!';
});
52
Let's craft a new file within app\Http\Controllers named
ZombieController.php and populate it with:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
namespace App\Http\Controllers;
In most controllers we also specify the Request class which will allow us
53
to capture requests from our route (more on this later). The use
keyword specifies the namespace for the Request class.
use Illuminate\Http\Request;
Great! We can map any route to any controller method. This will help
keep our route file clean, and it will put the logic in our controller files.
In the next chapter, we will cover Controllers in a little more depth. You
will see the process of execution from the route to the controller and
then to the view. Let's continue and learn more about how these pieces
come together.
54
55
9. Piecing It Together
A zombie developer might write all logic and views in a single file, but a
Laravel developer segments their app using routes, models, views, and
controllers, resulting in a cleaner, more flexible, and better-organized
application.
Piecing It Together
use App\Http\Controllers\ZombieController;
56
Here, we'll create a zombie controller at:
<?php
namespace App\Http\Controllers;
use App\Models\Zombie;
use Illuminate\Http\Request;
3. Fetch the zombies from our zombie model via our controller
Within our Zombie Controller, we extract all zombies from the Zombie
model, structuring it as such:
It's important to note that our app might not recognize Zombie::all()
out of context. Remember our zombie model lives within the
App\Models namespace instead of the App\Http\Controllers
namespace. So, we must make sure to specify where our Zombie class
57
is located.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Models\Zombie as Zombie;
Passing our zombie data to the view is pretty simple. Within show(), we
invoke a view file, and pass the zombie data:
The first argument is a string with the view we want to load (located at
resources/views/zombies.blade.php) and the second argument is an
array of data that we wish to pass to our view.
58
Our view file at resources/views/zombies.blade.php will display our
zombie data, like so:
<html>
<head>
<title>Zombies</title>
</head>
<body>
<ul>
@foreach($zombies as $zombie)
<li>{{ $zombie->name }}</li>
@endforeach
</ul>
</body>
</html>
Above, a simple foreach loop cycles through each zombie, listing their
names. Notably, we are using blade syntax that we covered previously.
Voilà! This section provides an overview of how each piece will work
from your route, model, controller, and view.
Isn't it fascinating?
59
60
10. Artisan
Most would opt for a shotgun for its efficiency. Similarly, when building
an app, wouldn't you want a tool that speeds up and eases the process?
Introducing Artisan
Recall from the first chapter where we used the artisan command to
initiate a local server. Specifically, we executed the php artisan serve
command in our Laravel project to start a local dev server.
61
$ php artisan make:controller ZombieController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
62
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
And just like that we've created our model class that can interact with
our zombies table in our database.
Pro Tip: If you wish for this Model to sync with a different database
table, add a protected variable named $table. For instance,
protected $table = 'zombie_folks'; ensures this model
communicates with the zombie_folks table.
Though we've only touched upon the basics with commands like php
artisan make:controller and php artisan make:model, numerous
other artisan commands await your exploration.
63
Next up, we'll dive into middleware—an efficient mechanism for
executing code between page requests.
64
11. Middleware
Unlike zombie developers who lack the ability to process between page
requests, Laravel developers harness Middleware to enhance their
app's security and flexibility.
Understanding Middleware
Route::get('arsenal', function(){
$is_zombie = rand(0, 1);
if($is_zombie){
return redirect('/home');
}
In the above code, zombie users are redirected to the homepage. For
65
another route, we could employ similar logic:
Route::get('armory', function(){
$is_zombie = rand(0, 1);
if($is_zombie){
return redirect('/home');
}
However, duplicating this code for every new route can become
tedious. Instead, a Middleware can be crafted to handle this
functionality. Using Laravel's Artisan, generate a new middleware file:
66
<?php
namespace App\Http\Middleware;
use Closure;
class isNotZombie
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
if($is_zombie){
return redirect('/home');
}
The final phase is registering our middleware in the app. This involves
naming our middleware class and appending it to the Kernel located in
app/Http/Kernel.php:
67
protected $routeMiddleware = [
// ... (existing middlewares)
'zombie' => \App\Http\Middleware\isNotZombie::class,
];
Web Middleware
protected $middlewareGroups = [
'web' => [
// ... (list of middleware classes)
],
'api' => [
// ...
],
];
68
Nesting and Using Multiple Middleware
Route-Specific Middleware
Route::get('arsenal', function () {
//
})->middleware(['zombie']);
Controller Middleware
namespace App\Http\Controllers;
69
enjoyment in coding. As we transition to the topic of Authentication,
we'll explore another middleware example that helps safeguard routes,
ensuring access only for authenticated users.
70
71
12. Authentication
Laravel Breeze offers a minimal yet adequate starting point for building
72
a Laravel application with authentication.
3. Database Configuration:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my-first-authentication
DB_USERNAME=root
DB_PASSWORD=your_password_here
4. Exploring Authentication:
With Breeze installed, you now have routes and views for registration,
login, password reset, and more. Visit your app's URL, and you'll
encounter neatly crafted login and registration pages, ready for action!
73
5. Crafting a User Profile:
The beauty of Laravel lies in its simplicity and elegance. Let's create a
user profile display.
Generate a controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
Route::get('profile',
'UserController@profile')->middleware('auth');
74
<!DOCTYPE html>
<html>
<head>
<title>{{ $user->name }}'s Profile</title>
</head>
<body>
<p>Welcome, {{ $user->name }}!</p>
<p>Email: {{ $user->email }}</p>
<a href="{{ route('dashboard') }}">Back to Dashboard</a>
</body>
</html>
6. Wrapping Up:
75
76
13. Requests
Requests allow our app to receive messages from the client. If these are
not handled well or efficiently it can lead to a deteriorating user
experience and could have significant vulnerabilities.
Requests
This server side language can accept requests from the client (web
browser) such as submitting a form or even requesting a route URL.
When a user types in a URL in their browser, the browser will then
contact or send a request to the server. So, when data is sent from the
browser to the server it is called a Request.
<?php
use Illuminate\Http\Request;
So, whenever we want to use the Request Class we need to make sure
to specify that we want to use the Illuminate\Http\Request
77
namespace, then we can simply pass the (Request $request) object as
a parameter.
$uri = $request->path();
if ($request->is('zombie/*')) {
// we have hit the zombie/{id} route
}
If we wanted to fetch the full URL instead we could simply get it like
this:
$url = $request->url();
Request Method
78
Now, let's say we wanted to figure out what kind of request our
application is recieving.
$method = $request->method();
if ($request->isMethod('post')) {
// we have a post method
}
This is the request method that we have used in the previous chapters.
This is where we get input data submitted by a form:
$zombie_name = $request->name;
We could also get all the input data as an array by doing the following:
$input = $request->all();
79
input value:
if ($request->has('name')) {
// 'name' is present in the request data
}
$cookie = $request->cookie('name');
We could also use the Request class to retrieve uploaded files like so:
$file = $request->file('photo');
if ($request->hasFile('photo') &&
$request->file('photo')->isValid()) {
// We have a valid file
}
There are a few more request types that are provided by the Laravel
Request class. Be sure to checkout the full documentation
(https://laravel.com/docs/requests) to learn more.
We just learned a few of the awesome things that the Request class
offers and we know how our app can accept requests, but what can it
do after it gets a request? Well, it can also send a response. Let's learn
80
about Responses in the next chapter.
81
14. Responses
Responses
In the previous chapter, we talked about requests and how our Laravel
app can accept them. In this chapter we are going to cover responses.
use Illuminate\Support\Facades\Route;
Route::get('/apocalypse', function () {
return 'End of the World!';
});
In the example above our laravel app recieves a GET request to the
/apocalypse route and it returns a string as the response. This is the
simplest form of a response.
So, when we return a response that contains HTML our Laravel app is
essentially returning an HTML document that gets displayed in the
users browser.
82
In the previous chapter we talked about how your app can retrieve a
cookie, now lets see how we can set a cookie by attaching it to a
response. Remember a cookie is stored on the client side (browser), so
when our app sends a response it will need to attach a cookie to be set
by the browser.
use Illuminate\Support\Facades\Route;
Route::get('/set_cookie', function(){
return response()->view('apocalypse')->cookie('name',
'value', 60); // 60 minutes
});
JSON responses
use Illuminate\Support\Facades\Route;
Route::get('/json-response', function(){
$data = [
'name' => 'Johnny Bullet Holes',
'strength' => 'strong'
];
return response()->json($data);
});
By running the route above, we get a nice JSON output as the response.
83
use Illuminate\Support\Facades\Route;
Route::get('/redirect-me', function(){
return redirect()->route('zombie.show', ['id' => 1]);
});
Route::redirect('/redirect-me', '/zombie/1');
View response
The most common response your app will send is an HTML response
from one of your application views.
When you return a view in your Laravel app, it is essentially the same
thing as returning an HTML response. Here is a quick example from a
few chapters back:
use App\Models\Zombie;
84
use Illuminate\Support\Facades\Route;
Route::get('/header_response', function () {
return response("With Custom Headers")
->header('X-Custom-Header', 'CustomHeaderValue')
->header('X-Another-Custom-Header',
'AnotherCustomHeaderValue');
});
Download Responses
use Illuminate\Support\Facades\Storage;
Route::get('/download', function () {
return response()->download(Storage::path('file.jpg'),
'user_friendly_name.jpg');
});
The example above will download a file from your storage directory and
send it as a response.
85
86
15. Migrations
Exporting and importing SQL files are dead, anyone who performs these
actions have zombie like tendencies.
Migrations
Say you are working on a team and someone adds a new row to the
database, they'll have to send you over an updated database schema
which you will have to import and make sure there are no conflicts!
Well, thanks to migrations, MySQL dumps will be a thing of the past and
sharing your updated schemas with teammates will be super simple. By
using migrations, you can create files in your app that store the
database structure.
zombies
87
Field Type Length
strength VARCHAR 20
health INT 3
created_at TIMESTAMP
updated_at TIMESTAMP
After running the following command, you will see a new file that has
been created inside your project located in the database\migrations
folder, and it probably looks something like:
Let's open up our new zombie migration file and you should see
something similar to the following:
88
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
}
Notice that there are 2 methods available in our new migration class.
Let's add some code to the up() method that looks like the following:
89
public function up()
{
Schema::create('zombies', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('strength');
$table->tinyInteger('health');
$table->timestamps();
});
}
All our migrations will then be run and we should see a few tables inside
our database including the zombies table.
And we run:
It will run our down() method and we will no longer see our zombies
table in our database.
Migration Status
90
You can check which migrations have been run and which are pending
by using:
If you want to roll back all of your migrations and then run them all from
the start (useful during development):
Production Precautions
91
Remember: Always backup your production database before running
migrations!
Migration Squashing
In the latest versions of Laravel, if you have a project that has been
running for a long time, you might end up with many migration files.
Laravel offers a way to squash them into a single SQL file, making it
faster to migrate:
The first command generates a schema dump, and the second one
squashes the migrations.
Hopefully, you can see the power of migrations. We could easily share a
GitHub repo with another user and they could pull our code down and
create a new database. Then they can run the migrations and they will
have the most up-to-date database schema.
There are many other types of functionality you can run in your up and
down methods, be sure to checkout the full documentation on
migrations at Laravel's documentation to learn more.
Fantastic!
92
93
16. Seeds
A zombie developer imports data into their database with an SQL data
dump, whereas a Laravel developer uses Seeds to input default data
into their application.
If you were to build an app that does not have any data, it would look
pretty useless. Luckily we can leverage seeds, which allow us to add
default data into our database schemas. So, when we hand over our
app to another developer we can always make sure there is a little bit
of seed data to work with.
Laravel allows us to add test data into our application. This is referred
to as seeding the database. In the previous chapter we talked about
migrations and in this chapter we will talk about seeds which is the
data stored in our database.
If we have our database migration for our zombies table we could hand
over our application to another developer and they can run php
artisan migrate and be up and running with the zombies table. Well,
what if we also wanted to include our zombie data in the database?
94
$ php artisan make:seeder ZombieSeeder
<?php
use Illuminate\Database\Seeder;
The function that will run when we want to seed the database is the
run() method, and this is where we will put our code. To seed our
zombie database with our two zombies we would add this to our run
method:
95
public function run()
{
$zombies = [
['name' => 'Johnny Bullet Holes', 'strength' =>
'Strong', 'health' => 70],
['name' => 'Ted Manwalking', 'strength' => 'Weak',
'health' => 90]
];
DB::table('zombies')->insert($zombies);
}
With Laravel's factories, you can also generate large amounts of test
data using random values. This can be especially handy when testing
features that require varied data sets.
Now we can use version control for our data, so when a new developer
pulls a fresh copy of our app on their computer they will also have the
data from our database.
Gone are the days of passing around an SQL file and now are the days
96
of creating migrations and seeds.
This is just another example of how Laravel makes our lives easier. Let's
move on to learning about the built-in security that Laravel provides.
97
98
17. Security
We want to make sure that no one can hack into our application, and
luckily Laravel has been built to prevent some of the most common
ways that users hack into systems.
Security
Don't worry if you don't know much about any of these protections.
We'll explain them below:
SQL Injection
$weapon_name = $_POST['weapon_name'];
$query = 'INSERT INTO weapons VALUES ('1', $weapon_name);
The user could easily enter in a value to the weapon name to Inject SQL
into our query. So, they could potentially run a query and drop a table
or a database.
99
Check out this XKCD.com comic:
Now whenever someone visits that page, they will be alerted with this
annoying popup. You can see that this could be dangerous because the
user could even redirect that page to another page.
{{ $user_comment }}
100
Cross-site Request Forgery
Finally, there is another attack called Cross Site Request Forgery that
Laravel can prevent against. This occurs someone modifies a
POST/PUT/DELETE request being sent to your server.
When you submit a form you can include a hidden input type with a
name of _token and the value of csrf_token() and Laravel will handle
the rest. The form will look similar to the following:
So, now you can sleep peacefully knowing that your site is safe against
any CSRF attacks.
101
patched in newer releases.
Security isn't just a feature—it's a priority. And with Laravel, you're not
just coding, you're crafting securely. Dive deeper and continue building
your masterpiece with peace of mind.
102
103
18. Testing
Say that you are given a few grenades during the zombie apocalypse
and the person giving you these grenades says, "I think they should
work, they've been stored away for many years". Wouldn't you rather
have them say, "These are our finest top of the line, tested to blow the
roof off of anything grenades"
Yeah, of course you would feel better throwing the grenade into a
swarm full of zombies that you know are tested to work. That's why
testing is so important. We want to guarantee that our app works in any
situation.
Testing
I'm sure we've all done some testing to some extent. If we open our
application, look at data, or even click a few links then we have tested
our application. The only problem with manual testing is that it can be
very time consuming.
Imagine for every line of code you change you have to go back and run
through your whole application to make sure it's all functioning
correctly. That would be absurd, right? Only a zombie would mindlessly
perform these repetitive tasks over and over again.
104
manually test when Laravel offers tools for automated testing?
Let's go over an easy example of how testing can help us out. Let's say
that we have a page with a simple link called 'Invetory of Weapons' that
would bring us to a page that says 'Weapons.'
<html>
<head>
<title>Artillery</title>
</head>
<body>
<a href="/weapons">Inventory of Weapons</a>
</body>
</html>
Route::get('artillery', function(){
return view('artillery');
});
Route::get('weapons', function(){
return view('weapons');
});
And each of these will load the view. Now, we want to guarantee that
anytime we visit the artillery page we see 'Inventory of Weapons' and
when we click on the link, we then end up on the weapons page.
105
For simplicity sake we will just assume that when you land on the
weapons page (located at resources\views\weapons.blade.php) that
it has the text 'Weapons' on the page, like so:
<html>
<head>
<title>Weapons</title>
</head>
<body>
<h1>Weapons</h1>
</body>
</html>
After running the artisan command above, we will end up with the
following code inside of a new file created at
tests\Feature\ArtilleryTest.php:
106
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
$response->assertStatus(200);
}
}
So, by default, we are given a test example. This test example is just
hard-coded to be true. So, let's run this test by typing in the following
command:
OK (1 test, 1 assertion)
Which means that we have run 1 test and 1 assertion and everything
was fine.
107
Why don't we go ahead and add a new method to our ArtilleryTest class
that looks like the following:
Notice that each function must be prepended with test. Let's run our
test again:
And we will see a green success message, with the following text:
OK (2 tests, 2 assertions)
Try changing up the text in our test. Say for instance that the link in the
artillery.blade.php file said 'Inventory of Kittens' instead of 'Inventory of
Weapons'. If we run the test again, we will see a red error message
saying that our tests have failed.
You can think of this as a game if you like. When we see green we are
currently winning! But if we see red that means we have a problem and
we need to figure out what needs to be fixed to pass our test.
108
Besides what we've already mentioned, some additional tips for testing
are:
Test Coverage: Aim for high test coverage but remember, it's not
just about quantity. Quality matters. Some critical parts of your
application might require thorough testing while others might not.
This was a very simple example just to give you a quick idea of how
tests can work, but there are many more things that you can test
besides text on the screen. Be sure to read up more about Laravel tests
on the documentation page. We'll also provide some awesome
resources you'll want to check out in the next chapter.
109
110
19. Wrapping Up
Wrapping Up
Whoa! We made it! You just learned the basics of Laravel, and shortly
you'll be on your way to building the latest and greatest app!
There are so many more fun things to learn about Laravel that we have
not included in this book, so be sure to head over to the Laravel
documentation and give it a read.
Resources
Laravel has quickly become one of the most popular PHP frameworks
available today. It should be no doubt that there are plenty of resources
out there to further your Laravel knowledge.
Here are some resources that will help you on your way to advancing
your Laravel skills:
111
https://laravel-news.com/ (Latest news on Laravel)
http://devdojo.com/ (Video resource with Dev & Laravel
Screencasts)
Words of Encouragement
Having fellow developers around you can help you grow and increase
your skills; however, there may also be other developers who will tell
you the way you are doing things are wrong and that you should be
doing things this way or that way.
These kinds of people can distract or discourage you from time to time.
A New Reality
112
Being a web developer is an excellent and exciting career choice. The
demand for web developers is at an all time high.
Most people will agree that building and creating something is very
satisfying, and as web developers we get to do just that! We get to take
an idea and make it come to life!
113