Laravel Tutorial for Beginners

Laravel is an open-source web MVC framework for PHP. Laravel is a robust framework that provides easy development of PHP web applications with features like a modular packaging system with a dedicated dependency manager, access to relational databases, and other utilities for application deployment and maintenance.

Laravel Tutorial for Beginners

What is Laravel?

Laravel is an open-source web MVC framework for PHP. Laravel is a robust framework that provides easy development of PHP web applications with features like a modular packaging system with a dedicated dependency manager, access to relational databases, and other utilities for application deployment and maintenance.

Laravel was created by Taylor Otwell. Since its initial release in June 2011 (version 1), it has steadily grown more and more popular in the PHP-framework sector of the web development industry. A lot of this popularity can be attributed to the many developer-first-minded features that it comes with stock.

Why Laravel?

Circa 2000, most PHP codes was procedural and could be found in the form of "scripts" that would have a tangled mess of spaghetti code. Even the simplest pages had no separation of concerns, and thus it was fairly easy for an application to quickly grow into a maintenance nightmare. The world needed something better...Enter PHP version 5 and a variety of PHP frameworks attempting to bring some much-needed resolution and better solutions to various web application concerns.

Since then we've seen many frameworks released that would pave the way for the popular frameworks existing and being employed today. Today, the top three would (in our opinion) be Zend Framework, Symfony and of course Laravel. Although each of these frameworks was founded on similar principles and are geared toward solving (basically) the same common problems, their key differences lie is their implementations. They each have their own quirks about how to go about solving problems. When you look at the code produced by each of them, you will see that there is a pretty solid line separating them from each other. In our humble opinion, Laravel framework is the best. 

How to Download and Install Laravel with Composer

NOTE It is assumed that you already have a copy of PHP installed on your local system.

Composer is both a package and dependency manager. To install it, open up a terminal and cd into a new directory. Run this command:

curl -Ss | php

The results of this command will look like this:

Note For more extensive instructions on setting up Laravel, refer to the Laravel documentation here.

You will see it downloading and compiling the composer.phar script, which is what we use to install Laravel. Although there are numerous ways to set up a new Laravel application, we will do it via the Laravel composer script. To install this script, run:

composer global require laravel/installer

Which will look something like this:

This will download and install all the framework files themselves as well as all dependencies that it requires. The packages will be saved inside the vendor directory. Once it is downloaded and installed, its as easy as issuing the following command:

laravel new uploadApp

You will see something like the following output:

Composer is installating all the packages that Laravel needs in order to run. It may take a few minutes so be patient. After it is finished, run an ls -al command to take a look at what was installed.

Here is a brief breakdown of the directories in a common Laravel application:

  • app/ : This is the source folder where our application code lives. All controllers, policies, and models are inside this folder
  • bootstrap/ : Holds the application's startup script and a few class map files
  • config/ : Holds the app's configuration files. These are usually not modified directly but instead, rely on the values set up in the .env (environment) file at the root of the app
  • database/ : Houses the database files including migrations, seeds and test factories
  • public/ : Publicly accessible folder holding compiled assets and of course an index.php file
  • resources/ : Contains front-end assets such as javascript files, language files, CSS/SASS files and all templates used in the application (called blade templates)
  • routes/ : All routes in the application are inside here. There are a few different "scopes" of routes but the one we will be focusing on is the web.php file
  • storage/ : All temporary cache files used by the application, session files, compiled view scripts and log files
  • tests/ : Contains test files for the application such as unit tests and functional tests.
  • vendor/ : All dependency packages installed with composer

Now then, let's build the rest of the app and run it with a special artisan command (to save ourselves the hassle of installing and configuring a web server like Apache or nginx). The .env file contains all the configuration values that the files in the /config directory use to configure the application. Inside it, you will notice that the configuration value for various parameters used by the internals of the application.

Application design: A quick run-down of our requirements

In this online Laravel tutorial, we will be building a very simple application that will do only two things:

  1. handle file uploads from a web form
  2. displaying the previously uploaded files on a different page.

For this project, our application will be write-only, meaning that the user can only write files and view the list of files that they have uploaded. This application is extremely basic but should serve as good practice for you to start building your Laravel skills and knowledge on. Note that for the sake of brevity, I have excluded any database modeling, migrations and authentication but, in a real-world application, these are additional things you will want to consider.

Here is a list of components that we will need in order to make the application work as expected:

  • A route that will allow the outside world (internet) to use the application as well as specify the endpoint that will point to where the logic for saving the uploaded file is located
  • A controller that handles the request to response flow
  • A template that will be used to display a list of previously uploaded files and the actual upload form itself
  • A request that the controller will use to validate the data passed in from the web form

What is a Route?

A route in Laravel is basically an endpoint specified by a URI that acts as a "pointer" to some piece of functionality offered by the application. Most commonly, a route simply points to a method on a controller and also dictates which HTTP methods are able to hit that URI. A route doesn't always mean controller method, either; it could just pass execution of the application to a defined Closure or anonymous function as well.

Why use Route?

Routes are stored inside files under the /routes folder inside the project's root directory. By default, there are a few different files corresponding to the different "sides" of the application ("sides" comes from the hexagonal architecture methodology). They include:

  • web.php The public facing "browser"-based routes. These are the most common and is what gets hit by the web browser. They run through the web middleware group and also contain facilities for csrf protection (which helps defend against form-based malicious attacks and hacks) and generally contain a degree of "state" (by this I mean they utilize sessions)
  • api.php Routes that correspond to an API group and thus have the API middleware enabled by default. These routes are stateless and have no sessions or cross-request memory (one request does not share data or memory with any other request--each one is self-encapsulated).
  • console.php These routes correspond to custom artisan commands that you've created for your app
  • channels.php Registers routes for event broadcasting

The key file to be concerned with at this time is the browser-specific one, web.php . There is already one route defined by default, which is the one you hit right when navigating to the web root of your application (web root is in the public directory). We are going to need three different routes for our upload application to function:

  • /upload This will be the URI of the main page displaying our web form for uploading files.
  • /process This will be where the form located at the /upload URI posts its form-submitted data to (the form's "action")
  • /list This will list all files uploaded to the site

note The /list endpoint may not be needed if we wished to put all the logic for displaying the upload form and the list of files on a single page, however, we kept them separate for now to add a little more matter to the subject at hand.

//inside routes/web.php
Route::get('/upload', 'UploadController@upload')->name('upload');
Route::get('/download, 'UploadController@download)->name(‘download');
Route::post('/process', 'UploadController@process')->name('process');
Route::get('/list', 'UploadController@list')->name('list');

In this Laravel framework tutorial, for each desired route, we will list it explicitly in the routes file web.php using one of the available HTTP-specific request methods (get(), post(), put() , delete(), patch() or options() ). For a breakdown of each of these, check this out. What these methods do is specify which HTTP verbs are allowed to access that given route. If you need a route to be able to accept more than one HTTP verb (which could be the case if you are using a single page to both displays the initial data and post submitted form data), you could use the Route::any() method.

The second argument to both the Route::get() and Route::post() method (and any of the other HTTP-verb-related methods on the Route facade), is the name of a specific Controller and method housed inside that controller that gets executed upon hitting the route's endpoint with the allowed HTTP request (GET, POST, PATCH, etc.) We are using the UploadController for all three routes and have specified them in the following fashion:

The last method we call on each route is its name() function, which accepts a single string as an argument and is used to more-or-less "tag" a particular route with an easy to remember the name (in our cases, upload, process, and list). I realize it doesn't seem so great of a feature to give each route its own name when the URL is named the exact same, but it really comes in handy when you have a specific route like /users/profile/dashboard/config, which would be easier to remember as profile-admin or user-config.

A note on Facades :

  • Facades provide a "static" interface to classes that are available in the application's service container."
  • They provide a terse, memorable syntax that allows you to use Laravel's features without remembering long class names that must be injected or configured manually.

The above route definitions in this Laravel framework tutorial, we use the Route facade instead of manually instantiating a new Illuminate/Routing/Router object and calling the corresponding methods on that object. It's just a shortcut that saves typing. Facades are used heavily throughout the Laravel framework--you can and should get more familiar with them. The docs for Facades can be found here.

What is a Controller?

A controller is the "C" in the "MVC" (Model-View-Controller) architecture, which is what Laravel is based on. A controller's job can be boiled down to this simple definition: It receives the request from the client and returns a response to the client. This is the bare-bones definition and is also the minimum requirements of any given controller. What it does in between those two things is generally considered as the "action" of the controller (or the "route's implementation"). It acts as the second point of entry to the application (the first being the request) to the client, who sends the request payload (which we will get to next) to the application, expecting some type of response (in the form of a success page, redirect, error page, or any other kind of HTTP response).

A controller does (basically) the same thing as a route definition with an anonymous function set as the "action" when that route is hit. The difference is that a controller holds up well to the separation of concerns while a route is defined inline to the actual url definition, which basically means we are coupling the route's assigned URI with the route's implementation, or the code that executes when that route is hit.

For example, the following two pieces of code will achieve the same thing:

Example #1: Route's definition & implementation inside a single method call (in the web.php routes file)

//inside routes/web.php

Here is what our /upload page looks like:

This is a very typical example of a blade file containing an HTML form and javascript/jQuery for adding asynchronous functionality (so the page doesn't refresh). There is a basic

tag with no method attribute (which I'll explain in just a sec) and with a curious action attribute with the value {{route('file.upload')}}. In blade, this is what is known as a directive. A directive is just a fancy name for function--they are functions specific to blade templates that perform different operations that are common to constructing web pages and web applications. For a better understanding of all the cool shit that blade can do, check out the docs here. In the case above, we are using the route directive to generate a URL for our form submission.

Remember that we defined our routes earlier in the application inside the web.php file, specifying an easy to remember the name for each of them. The {{route()}} directive accepts a name of a route, looks it up inside the internally cached routes list, and generates a full URL based on the definition of that route in the web.php file. For this first case, we are specifying that we want the form to send its submitted data to the /process URL of our application, which is defined as a POST route.

The next weird thing you may have noticed is the @csrf tag right below the opening form tag. In blade, this tag generates a _token parameter on the form, which gets checked inside the application before the form data is allowed to be processed. This ensures that the data inside the form is of a valid origin and prevents cross-site-request-forgery attacks. For more info on this, see the docs.

After this we define our form as normal, however, do note that the names of our form parameters, userFile and fileName are the exact same as defined inside our request object. If we forgot to include an input for a given parameter that was defined in the request object (or misspelled it), the request would fail and an error would be returned, preventing the original form request from ever hitting the controller method located at UploadController@process .

Go ahead and try it out and submit a few files to the application using this form. Afterward, navigate to the /list page to see the contents of the upload folder, with the files you uploaded listed in a table:

The Bigger Picture

Let's take a step back and look at what we've done in this Laravel tutorial.

This diagram depicts the application as it stands right now (high-level details excluded) :

You should recall that the request object we constructed at the beginning of this Laravel tutorial should have the same parameters defined in its rules method as is on the form in the blade template (if not re-read the section "Creating the Validation Logic"). The user enters the form in a web page that is rendered via a blade template engine (this process is of course on auto-pilot so we don't have to even think about it) and submits the form. The template's jQuery code at the bottom stops the default submission (which would automatically redirect to a separate page), creates an ajax request, loads the request with the form data and uploaded the file, and sends the whole thing into the first layer of our application: the request.

The request object gets populated by associating the parameters inside the rules() method with the submitted form parameters, then validates the data according to each specified rule. If all the rules are satisfied, the request gets passed along to whatever controller method that corresponds to the values defined in the route file web.php. In this case, it is the process() method of the UploadController that does the work. Once we hit the controller, we already know that the request passed validation so we don't have to re-test if the filename given is, in fact, a string or the userFile parameter actually holds some type of file... We can continue as normal.

The controller method then grabs the validated parameters out of the request object, generates a full filename by concatenating the passed in fileName parameter with the userFile 's original extension, stores the file inside a directory in our application, then returns a simple JSON-encoded response verifying that the request was successful. The response is received by the jQuery logic, which does a few more UI-related tasks such as displaying the success (or error) message for 5 seconds then hiding it as well as clearing out the previous form entries...this is so the user knows for sure that the request was successful and can upload another file, if they wish.

Also, take note in the diagram above just where the line is drawn between the client and the server. This concept is absolutely critical for you to understand and will help you solve problems and issues you may have in the future when juggling, for example, multiple asynchronous requests that can occur at any given time. The separation is right at the boundary of the request object. The request object itself can be thought of as the "gateway" to the rest of the application... It does the initial validation and registration of form values passed in from the web browser. If they are deemed valid, then it continues to the controller. Everything before that is on the front end (the "client" literally means "on the user's computer"). The response is returned from the app back into the client side, where our jQuery code patiently listens for its arrival and does a few simple UI tasks once it receives it.

What's Your Reaction?