Laravel Application Development Blueprints

4 (1 reviews total)
By Arda Kılıçdağı , Halil İbrahim Yılmaz
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Building a URL Shortener Website

About this book

Laravel is a clean and classy framework for PHP web development. It helps you to create wonderful applications using simple, expressive syntax. Development should be a creative and enjoyable experience, not something that is painful, and Laravel makes it enjoyable for the users. Laravel's directory structure is designed to be familiar to users of other popular PHP frameworks. Web applications of any shape or size can easily be created using this structure similar to the way that they would be created in other frameworks. With the recently released 4th Version, Laravel became even better in numerous ways. Within this book, we will help you learn about both the old and new features of Laravel while developing various applications.

Laravel Application Development Blueprints covers how to develop 10 different applications step-by-step using Laravel 4. You will also learn about both basic and advanced usage of Laravel’s built-in methods, which will come in handy for your project. Also, you will learn how to extend the current libraries with the built-in methods and include third-party libraries.

This book looks at the Laravel PHP framework and breaks down the ingrained prejudice that coding with PHP causes due to spaghetti code. It will take you through a number of clear, practical applications that will help you to take advantage of the Laravel PHP framework and PHP OOP programming whilst avoiding spaghetti code.

You'll also learn about creating secure web applications using different methods such as file uploading and processing, making RESTful AJAX requests, and form processing. If you want to take advantage of the Laravel PHP framework's validate, file processing, and RESTful controllers in various types of projects, then this is the book for you.
Everything you need to know to code fast and secure applications with the Laravel PHP framework will be discussed in this book.

Publication date:
November 2013
Publisher
Packt
Pages
260
ISBN
9781783282111

 

Chapter 1. Building a URL Shortener Website

Throughout the book, we will be using the Laravel PHP framework to build different types of web projects.

In this chapter, we'll see how to build a URL Shortener website with the basics of Laravel framework. The covered topics include:

  • Creating a database and migrating our URL Shortener's table

  • Creating our form

  • Creating our Link model

  • Saving data to the database

  • Getting individual URL from the database and redirecting

 

Creating a database and migrating our URL shortener's table


Migrations are like version control for your application's database. They permit a team (or yourself) to modify the database schema, and provide up-to-date information on the current schema state. To create and migrate your URL Shortener's database, perform the following steps:

  1. First of all, we have to create a database, and define the connection information to Laravel. To do this, we open the database.php file under app/config, and then fill the required credentials. Laravel supports MySQL, SQLite, PostgreSQL, and SQLSRV (Microsoft SQL Server) by default. For this tutorial, we will be using MySQL.

  2. We will have to create a MySQL database. To do this, open your MySQL console (or phpMyAdmin), and write down the following query:

    CREATE DATABASE urls
    
  3. The previous command will generate a new MySQL database named urls for us. After having successfully generated the database, we will be defining the database credentials. To do this, open your database.php file under app/config. In that file, you will see multiple arrays being returned with database definitions.

  4. The default key defines what database driver to be used, and each database driver key holds individual credentials. We just need to fill the one that we will be using. In our case, I've made sure that the default key's value is mysql. To set the connection credentials, we will be filling the value of the mysql key with our database name, username, and password. In our case, since we have a database named urls, with the username as root and without a password, our mysql connection settings in the database.php file will be as follows:

    'mysql' => array(
      'driver' => 'mysql',
      'host' => 'localhost',
      'database' => 'database',
      'username' => 'root',
      'password' => '',
      'charset' => 'utf8',
      'collation' => 'utf8_unicode_ci',
      'prefix' => '',
    ),

    Tip

    You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

  5. Now, we will be using the Artisan CLI to create migrations. Artisan is a command-line interface specially made for Laravel. It provides numerous helpful commands to help us in development. We'll be using the following migrate:make command to create a migration on Artisan:

    php artisan migrate:make create_links_table --table=links --create
    

    The command has two parts:

    • The first is migrate:make create_links_table. This part of the command creates a migration file which is named something like 2013_05_01_194506_create_links_table.php. We'll examine the file further.

    • The second part of the command is --table=links --create.

      • The --table=links option points to the database name.

      • The --create option is for creating the table on the database server to which we've given the --table=links option.

  6. As you can see, unlike Laravel 3, when you run the previous command, it will create both the migrations table and our migration. You can access the migration file under app/database/migrations, having the following code:

    <?php
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    class CreateLinksTable extends Migration {
      /**
      * Run the migrations.
      *
      * @return void
      */
      public function up()
      {
        Schema::create('links', function(Blueprint $table)
        {
          $table->increments('id');
        });
      }
      /**
      * Reverse the migrations.
      *
      * @return void
      */
      public function down()
      {
        Schema::drop('links');
      }
    }
  7. Let's inspect the sample migration file. There are two public functions which are declared as up() and down(). When you execute the following migrate command, the contents of the up() function will be executed:

    php artsian migrate
    

    This command will execute all of the migrations and create the links table in our case.

    Note

    If you receive a class not found error when running the migration file, try running the composer update command.

  8. We can also roll back to the last migration, like it was never executed in the first place. We can do this by using the following command:

    php artisan migrate:rollback
    
  9. In some cases, we may also want to roll back all migrations we have created. This can be done with the following command:

    php artisan migrate:reset
    
  10. While in the development stages, we may forget to add/remove some fields, or even forget to create some tables, and we may want to roll back everything and remigrate them all. This can be done using the following command:

    php artisan migrate:refresh
    
  11. Now, let's add our fields. We've created two additional fields called url and hash. The url field will hold the actual URL, to which the URL present in the hash field will be redirected. The hash field will hold the shortened version of the URL that is present in the url field. The final content of the migration file is as shown in the following code:

    <?php
    use Illuminate\Database\Migrations\Migration;
    class CreateLinksTable extends Migration {
      /**
      * Run the migrations.
      *
      * @return void
      */
      public function up()
      {
        Schema::create('links', function(Blueprint $table)
        {
          $table->increments('id');
          $table->text('url');
          $table->string('hash',400);
        });
      }
      /**
      * Reverse the migrations.
      *
      * @return void
      */
      public function down()
      {
        Schema::drop('links');
      }
    }
 

Creating our form


Now let's make our first form view.

  1. Save the following code as form.blade.php under app/views. The file's extension is blade.php because we will be benefiting from Laravel 4's built-in template engine called Blade . There may be some methods you don't understand in the form yet, but don't worry. We will cover everything regarding this form in this chapter.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>URL Shortener</title>
        <link rel="stylesheet" href="/assets/css/styles.css" />
      </head>
      <body>
        <div id="container">
          <h2>Uber-Shortener</h2>
          {{Form::open(array('url'=>'/','method'=>'post'))}}
    
          {{Form::text('link',Input::old('link'),array('placeholder'=>'Insert your URL here and press enter!'))}}
          {{Form::close()}}
        </div>
      </body>
    </html>
  2. Now save the following codes as styles.css under public/assets/css:

    div#container{padding-top:100px;
      text-align:center;
      width:75%;
      margin:auto;
      border-radius:4px}
    div#container h2{font-family:Arial,sans-serif;
      font-size:28px;
      color:#555}
    div#container h3{font-family:Arial,sans-serif;
      font-size:28px}
    div#container h3.error{color:#a00}
    div#container h3.success{color:#0a0}
    div#container input{display:block;
      width:90%;
      float:left;
      font-size:24px;
      border-radius:5px}
    div#error,div#success{border-radius:3px;
      display:block;
      width:90%;
      padding:10px}
    div#error{background:#ff8080;
      border:1px solid red}
    div#success{background:#80ff80;
      border:1px solid #0f0}

    This code will produce you a form that looks like the following screenshot:

    As you can see, we have used a CSS file to tidy up the form a bit, but the actual part of the form is at the bottom of the View file, inside div with the ID of the container.

  3. We have used the Laravel's built-in Form class to generate a form, and we have used the old() method of the Input library. Now let's dig the code:

    • Form::open(): It creates a <form> opening tag. Within the first provided parameter, you can define how the form is sent, and where it is going to be sent. It can be a controller's action, a direct URL, or a named route.

    • Form::text(): It creates an <input> tag with type as text. The first parameter is the name of the input, the second parameter is the value of the input, and within the array given in the third parameter, you can define assets and other attributes of the <input> tag.

    • Input::old(): It will return the old input from a form, after the form is returned with the inputs. The first parameter is the name of the old input submitted. In our case, if the form is returned after submission (for example, if the form validation fails), the text field will be filled with our old input and we can reuse it for later requests.

    • Form::close(): It closes the <form> tag.

 

Creating our Link model


To benefit from Laravel's ORM class called Eloquent, we need to define a model. Save the following code as Link.php under app/models:

<?php
class Link extends Eloquent {
  protected $table = 'links';
  protected $fillable = array('url','hash');
  public $timestamps = false;
}

The Eloquent model is quite easy to understand.

  • The variable $table is used to define the table name for the model, but it's not compulsory. Even if we don't define this variable, it would use the plural form of the model name as a database table name. For example, if the model name was post, it would look for the post's table as default. This way, you can use any model names for the tables.

  • The protected $fillable variable defines what columns can be (mass) created and updated. Laravel 4 blocks the mass-assignment of the values of all the columns with Eloquent by default. This way, for example, if you have a users table, and you are the only user/administrator, the mass-assignment protects your database from another user being added.

  • The public $timestamps variable checks whether the model should try setting the timestamps created_at and updated_at by default, while creating and updating the query respectively. Since we don't need these features for our chapter, we will disable this by setting the value to false.

We now need to define this view to show whether we can navigate to our virtual host's index page. You can do this either from the controllers defined in routes.php, or from routes.php directly. Since our application is small, defining them directly from routes.php should suffice. To define this, open the routes.php file under the app folder and add the following code:

Route::get('/', function()	
{
  return View::make('form');
});

Note

If you already have a section starting with Route::get('/', function(), you should replace that section with the previous code.

Laravel can listen get, post, put, and delete requests. Since our action is a get action (because we will be navigating through the browser without posting), our route type will be get, and because we want to show the view on the root page, our first parameter of the Route::get() method will be /, and we wrap a closure function as the second parameter to define what we want to do. In our case, we will be returning form.blade.php placed under app/views that we had generated before, so we just type return View::make('form'). This method returns the form.blade.php view from the views folder.

Note

If the view was in a subdirectory, it would be called subfolder.form.

 

Saving data to the database


Now we need to write a route that will have to listen to our post request. For this, we open our routes.php file under the app folder and add the following code:

Route::post('/',function(){
  //We first define the Form validation rule(s)
  $rules = array(
    'link' => 'required|url'
  );
  //Then we run the form validation
  $validation = Validator::make(Input::all(),$rules);
  //If validation fails, we return to the main page with an error info
  if($validation->fails()) {
    return Redirect::to('/')
    ->withInput()
    ->withErrors($validation);
  } else {
    //Now let's check if we already have the link in our database. If so, we get the first result
    $link = Link::where('url','=',Input::get('link'))
    ->first();
    //If we have the URL saved in our database already, we provide that information back to view.
    if($link) {
      return Redirect::to('/')
      ->withInput()
      ->with('link',$link->hash);
      //Else we create a new unique URL
    } else {
      //First we create a new unique Hash
      do {
        $newHash = Str::random(6);
      } while(Link::where('hash','=',$newHash)->count() > 0);

      //Now we create a new database record
      Link::create(array('url' => Input::get('link'),'hash' => $newHash
      ));

      //And then we return the new shortened URL info to our action
      return Redirect::to('/')
      ->withInput()
      ->with('link',$newHash);
    }
  }
});

Validating the users' input

Using the post action function that we've coded now, we will be validating the user's input with the Laravel's built-in Validation class. This class helps us prevent invalid inputs from getting into our database.

We first define a $rules array to set the rules for each field. In our case, we want the link to have a valid URL format. Then we can run the form validation using the Validator::make() method and assign it to the $validation variable. Let's understand the parameters of the Validator::make() method:

  • The first parameter of the Validator::make() method takes an array of inputs and values to be validated. In our case, the whole form has only one field called link, so we've put the Input::all() method, which returns all the inputs from the form.

  • The second parameter takes the validation rules to be checked. The stored $validation variable holds some information for us. For example, we can check whether the validation has failed or passed (using $validation->fails() and $validation->passes()). These two methods return Boolean results, so we can easily check if the validation has passed or failed. Also, the $validation variable holds a method messages(), which contains the information of a failed validation. And we can catch them using $validation->messages().

If the form validation fails, we redirect the user back to our index page (return Redirect::to('/')), which holds the URL shortener form, and we return some flash data back to the form. In Laravel, we do this by adding the withVariableName object to the redirected page. Using with is mandatory here, which will tell Laravel that we are returning something additional. We can do this for both redirecting and making views. If we are making views and showing some content to the end user, those withVariableName will be variables, and we can call them directly using $VariableName, but if we are redirecting to a page with the withVariableName object, VariableName will be a flash session data, and we can call it using the Session class (Session::get('VariableName')).

In our example, to return the errors, we used a special method withErrors($validation), instead of returning $validation->messages(). We could also return using that, but the $errors variable is always defined on views, so we can use our $validation variable as a parameter with withErrors() directly. The withInput() method is also a special method, which will return the results back to the form.

//If validation fails, we return to the main page with an error info
if($validation->fails()) {
  return Redirect::to('/')
  ->withInput()
  ->withErrors($validation);
}

If the user forgets one field in the form, and if the validation fails and shows the form again with error messages, using the withInput() method, the form can be filled with the old inputs again. To show these old inputs in Laravel, we use the old() method of the Input class. For example, Input::old('link') will return us the old input of the form field named link.

Returning the messages to the view

To return the error message back to the form, we can add the following HTML code into form.blade.php:

@if(Session::has('errors'))
<h3 class="error">{{$errors->first('link')}}</h3>
@endif

As you can already guess, Session::has('variableName') returns a Boolean value to check whether there is a variable name for the session. Then, with the first('formFieldName') method of Laravel's Validator class, we are returning the first error message of a form field. In our case, we are showing the first error message of our link form field.

 

Diving further into controller and processing the form


The else part of the validation checking part that is executed when the form validation is completed successfully in our example, holds the further processing of the link. In this section, we will perform the following steps:

  1. Checking whether the link is already in our database.

  2. If the link is already in our database, returning the shortened link.

  3. If the link is not present in our database, creating a new random string (the hash that will be in our URL) for the link.

  4. Creating a new record in our database with the provided values.

  5. Returning the shortened link back to the user.

Now, let's dig the code.

  1. Here's the first part of our code:

    // Now let's check if we already have the link in our database. If so, we get the first result
    $link = Link::where('url','=',Input::get('link'))
    ->first();

    First, we check if the URL is already present in our database using the where() method of Fluent Query Builder , and get the first result via the method first(), and assign it to the $link variable. You can use the Fluent query methods along with the Eloquent ORM easily. If this confuses you, don't worry, we will cover this further in the later chapters.

  2. This is the next part of our controller method's code:

    //If we have the URL saved in our database already, we provide that information back to view.
    if($link) {
      return Redirect::to('/')
      ->withInput()
      ->with('link',$link->hash);

    If we have the URL saved in our database, the $link variable will hold the object of our link's information taken from the database. So with a simple if() clause, we can check if there is a result. If there is a result returned, we can access it using $link->columnname.

    In our case, if the query has a result, we redirect the inputs and the link back to the form. As we've used here, the with() method can also be used with two parameters instead of using a camel case—withName('value') is exactly the same as with('name','value'). So, we can return the hash code with a flash data named link with('link',$link->hash). To show this, we can add the following code to our form:

    @if(Session::has('link'))
    <h3 class="success">
      {{Html::link(Session::get('link'),'Click here for your shortened URL')}}</h3>
    @endif

    The Html class helps us write HTML codes easily. The link() method requires the following two parameters:

    • The first parameter is link. If we provide a string directly (the hash string in our case), the class will identify it automatically and make an internal URL from our website.

    • The second parameter is the string that has the link.

    The optional third parameter has to be an array, holding attributes (such as class, ID, and target) as a two-dimensional array.

  3. The following is the next part of our code:

    //Else we create a new unique URL
    } else {
      //First we create a new unique Hash
      do {
        $newHash = Str::random(6);
      } while(Link::where('hash','=',$newHash)->count() > 0);

    If there is no result (the else clause of the variable), we are creating a six-character-long alphanumeric random string with the Str class's random() method and checking it each time to make sure that it is a unique string, using PHP's own do-while statement. For real world application, you can use an alternative method to shorten, for example, converting an entry in the ID column to base_62 and using it as a hash value. This way, the URL would be cleaner, and it's always a better practice.

  4. This is the next part of our code:

    //Now we create a new database record
    Link::create(array(
      'url' => Input::get('link'),
      'hash' => $newHash
    ));

    Once we have a unique hash, we can add the link and the hash values to the database with the create() method of the Laravel's Eloquent ORM. The only parameter should be a two-dimensional array, in which the keys of the array are holding the database column names, and the values of the array are holding the values to be inserted as a new row.

    In our case, the url column has to have the link field's value that came from the form. We can catch these values that came from the post request using Laravel's Input class's get() method. In our case, we can catch the value of the link form field that came from the post request (which we would catch using the spaghetti code $_POST['link']) using Input::get('link'), and return the hash value to the view as we did earlier.

  5. This is the final part of our code:

    //And then we return the new shortened URL info to our action return Redirect::to('/')
    ->withInput()
    ->with('link',$newHash);

    Now, at the output, we're redirected to oursite.dev/hashcode. There is a link stored in the variable $newHash; we need to catch this hash code and query our database, and if there is a record, we need to redirect to the actual URL.

 

Getting individual URL from the database and redirecting


Now, in the final part of our first chapter, we need to get the hash part from the generated URL, and if there is a value, we need to redirect it to the URL which is stored in our database. To do this, add the following code at the end of your routes.php file under the app folder:

Route::get('{hash}',function($hash) {
  //First we check if the hash is from a URL from our database
  $link = Link::where('hash','=',$hash)
  ->first();
  //If found, we redirect to the URL
  if($link) {
    return Redirect::to($link->url);
    //If not found, we redirect to index page with error message
  } else {
    return Redirect::to('/')
    ->with('message','Invalid Link');
  }
})->where('hash', '[0-9a-zA-Z]{6}');

In the previous code, unlike other route definitions, we added curly brackets around the name hash, which tells Laravel that it's a parameter; and with the where() method we defined how the name parameter will be. The first parameter is the name of the variable (which is hash in our case), and the second parameter is a regular expression that will filter the parameter. In our case, the regular expression filters an exact alphanumeric string that is six-characters long. This way, we can filter our URLs and secure them from start, and we won't have to check if the url parameter has something we don't want (for example, if alphabets are entered instead of numbers in the ID column). To get individual URL from the database and redirect, we perform the following steps:

  1. In the Route class, we first make a search query, as we did in the earlier section, and check if we have a link with the given hash from a URL in our database, and set it to a variable called $link.

    //First we check if the hash is from an URL from our database
    $link = Link::where('hash','=',$hash)
    ->first();
  2. If there is a result, we redirect the page to the url column of our database, which has the link to which the user should be redirected.

    //If found, we redirect to the link
    if($link) {
      return Redirect::to($link->url);
    }
  3. If there is no result, we redirect the user back to our index page using the $message variable, which holds the value Invalid Link.

    //If not found, we redirect to index page with error message
    } else {
      return Redirect::to('/')
      ->with('message','Invalid Link');
    }

    To show the Invalid Link message in the form, add the following code in your form.blade.php file placed under app/views:

    @if(Session::has('message'))
    <h3 class="error">{{Session::get('message')}}</h3>
    @endif
 

Summary


In this chapter, we have covered the basic usage of Laravel's routes, models, artisan commands, and database drivers by making a simple URL shortener website. Once you've followed this chapter, you can now create database tables with migrations, write simple forms with the Laravel Form Builder Class, validate these forms with the Validation class, and process these forms and insert new data to the table(s) with the Fluent Query Builder or Eloquent ORM. In the next chapter, we'll cover the advanced usage of these awesome features.

About the Authors

  • Arda Kılıçdağı

    Arda Kılıçdağı is a PHP, MySQL, and JavaScript programmer from Turkey. He has been developing applications in PHP since 2005. He has been administrating the Turkish national support website for the well-known open source content management script, PHP-Fusion. He's also one of the international developers and a member of the management team for PHP-Fusion, and he has an important role in the project's future. He has worked as a developer and has experience on projects such as Begendy (an exclusive private shopping website) and Futbolkurdu (a local soccer news website). He is experienced in using the Facebook API, Twitter API, and PayPal's Adaptive Payments API (which is used on crowdfunding websites such as KickStarter). He's also experienced in using JavaScript, and he's currently infusing his applications with JavaScript and jQuery, both on the frontend and backend. He has also developed applications using CodeIgniter and CakePHP for about four years, but these PHP frameworks didn't suit his needs completely. This is why he decided to use another framework for his projects, and that is when he met Laravel. Currently he is developing all his applications using Laravel. He's also obsessed with Unix/Linux and uses Linux on a daily basis. In addition, he is administrating the world's best-known microcomputer, Raspberry Pi's biggest Turkish community website.

    Browse publications by this author
  • Halil İbrahim Yılmaz

    Halil İbrahim Yılmaz is a Python and PHP programmer and an e-commerce consultant from Turkey. He has worked as a developer and a software coordinator in over a dozen ventures, including Begendy, Modeum, Futbolkurdu, Arkeoidea, and Uzmanlazim. He is experienced in using many APIs such as Google, YouTube, Facebook, Twitter, Grooveshark, and PayPal. After meeting his business partner, he co-founded 16 Pixel, a Bursa-based creative consultancy that specializes in web development and e-commerce. He loves learning functional programming languages (Erlang and Haskell), new JavaScript technologies (Node.js), and NoSQL database systems (Riak and MongoDB). When he is not working on client projects, he is often trying to code a web application with those technologies. He lives in a house full of Linux boxes in Bursa, Turkey.

    Browse publications by this author

Latest Reviews

(1 reviews total)
Good
Book Title
Access this book, plus 7,500 other titles for FREE
Access now