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. Learn more about Difference between Laravel and CodeIgniter In this Laravel tutorial for beginners, you will learn Laravel basics like :
What is Laravel?
Why Laravel?
How to Download and Install Laravel with Composer
Application design: A quick run-down of our requirements
What is a Route?
What is a Controller?
Generating the Request
Creating the Validation Logic
Modifying the Controller
The Blade Template
The Bigger Picture
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. If not, you can read how to install it here Composer is both a package and dependency manager. To install it, open up a terminal and cd into a new directory. Run this command: 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: 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: 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:
handle file uploads from a web form 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. 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) Example #2: Route’s definition is inside routes/web.php, but it’s implementation resides inside the /app/Http/Controllers/HelloWorldController class Although Laravel example #2 seems like a lot more work (which it’s not–just a little more code is all), look at the benefits we gain by putting our action logic for the given “hello-world” route inside of a controller instead of with the route’s definition as a callback function:
Our logic is cleanly separated into its own class (separation of concerns) Our controller is set up for extension later on if we needed to add additional capabilities to it…Say maybe we wanted to add a “goodbye-world” feature… In this case we would rename the controller to a more generic “HelloController” then define two separate methods, hello() and goodbye(). We would also need to define two separate routes that mapped the /hello and /goodbye URIs to their appropriate method on the controller. This is desirable compared to fattening up a routes file with each route’s implementation-defined as callback functions. Laravel has the built-in ability to cache all the route definitions in the application so that it speeds up the time it takes to find a given route (increases application performance); however, you will only be able to take advantage of that if all of your defined routes inside the application are configured using controller-specific mappings (see Example #2 above)
Let’s run this command that will generate a new controller for us. Essentially, what this command does is generates a stub for a controller named “UploadController” inside of the main controller directory at /app/Http/Controllers/UploadController.php.Feel free to open up that file and take a look. It’s very simple because it is only a stubbed out version of the controller, with the correct namespace path and the required classes that it extends from.
Generating the Request
Before we go forward in this PHP Laravel tutorial and make a few changes to the UploadController’s generated stub, I think it will make more sense to create the request class first. This is because the controller method that handles the request must type hint the request object in its signature, allowing it to automatically validate the incoming form data (as specified in the rules() method. More on that later…) For now, let’s use the artisan command again to generate our request stub: This command will generate a file called UploadFileRequest inside app/Http/Requests/UploadFileRequest. Open up the stub and take a peek… You will find it very simple, containing only two methods, authorize() and rules.
Creating the Validation Logic
Let’s modify the request stub to meet the needs of our application. Modify the file so that it looks like so: Not a whole lot of changes but notice that the authorize() method now returns true instead of false. This method decides whether or not to allow the request to go into the application. If it is set to false, it stops the request from entering the system (which would normally be a method on the controller). This would be a very handy place to put any authorization checks on the user or any other logic that may decide if the request can move forward to the controller. For now, we just return true here to allow anything and everything to use the request. The other method, rules() is where all the magic comes into play with regard to validation. The idea is simple: return an array containing a set of rules in the form of: There are many different validation constraints that are supported by Laravel right out of the box. For a full list of them, check out the online documentation here. For our upload application, there are going to be two fields that are passed in via POST request from a form on the front end. The fileName parameter must be included inside the form body (i.e. required) and is used as the filename we will store the file under in the storage (this is done in the controller–we will get to it a little later). We also specify that the file name must be a string by adding a pipe character (|) and the word ‘string’. Constraints are always delimited by pipes, allowing you to specify any additional criteria for the given field in a single line! What power! The second parameter, userFile , is the actual file that the user uploads from a form on a webpage. UserFile is also required and must be a file. Note: If we were expecting the uploaded file to be an image, then we would use the image constraint instead, which would limit the file types accepted to be one of the popular image types (jpeg, png, bmp, gif or svg). Since we want to allow the user to upload any type of file, we will just stick with the file validation constraint. That is about all there is to the request object. Its main job is to simply hold the acceptable set of criteria (constraints) that the form’s body parameters must satisfy in order to proceed deeper into the application. Another thing to note is that these two fields (userFile and filename) must also be specified inside the HTML code in the form of input fields (with the field name corresponding to the name inside the request object). You might be asking: sure this defines the characteristics of what a form request should contain, but where is the actual check of these constraints done? We will get into that next.
Modifying the Controller
Open up the app/Http/Controllers/UploadController and make the following changes to it: So it’s a fairly straightforward approach to saving the uploaded files to disk. Here is a breakdown of the upload() method above:
Type-hint the request class in the controller method that is doing the ‘meat and potatoes’ functionality so we can auto-validate the incoming data Grab the file out of the (now validated) request object inside the controller method (in this case we’ve named it upload() but it could have also been named to a more standardized name like store()). Grab the filename out of the request Generate the final filename that will be used to save the file under. The getClientOriginalExtension() method simply grabs the original extension of the uploaded file. Store the file to the local filesystem using its storeAs() method, passing in the named path inside the /storage directory as the 1st argument and the filename to save it under as the second. Return a JSON response indicating the request was successful
The Blade Template
The last major piece to this puzzle is the blade template, which will hold all HTML, CSS, and javascript for our simple application. Here is the code–We will explain it later. 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