Build Shortener URL with Laravel 9 — Model & View Implementation — Part 2

Agri Kridanto
13 min readJan 15, 2023

--

Hello World,

In this tutorial, we will continue our series on building a web Shortener URL while learning Laravel 9. In the previous post, we explained the Environment Development of our Project, the MVC architectural pattern, and the project structure on the Laravel-based Web that we are building.

In this blog post, We will focus on implementing the Model-View-Controller (MVC) pattern in our project. I would put Controller implementation in the next post.

  1. Model
    We will delve into the subject of databases and model.

A. Database Design

This website has simple functionality, so the database built here is also simple. As we mentioned before, we will use is MySQL as our database in this project. If you are using Laragon, it comes pre-installed with MySQL as we previously discussed in our last post.

The primary purpose of this web application is to provide shortened versions of URLs. We will create a unique shortened URL for each user request and store it in our database. Additionally, we will keep track of the number of times each shortened URL is accessed, as well as the last accessed timestamp. Below is the table design that we will use to accomplish this functionality

database design for shortener url

The above table design has the following columns:

id: Primary Key column of this table. has a big integer data type and is auto-increment
long_url: has a string data type, which will be used to store the URL submitted by the user.
short_url: has a string data type, used as a shortening URL.
counter: has data type integer, which will be used to count the number of times this URL has been accessed via this short URL.
last_visit: has a timestamp data type, which states the last time the link was accessed via this short URL.
created_at, updated_at, deleted_at: have a timestamp data type, which states when the row was created, updated, and deleted.

B. Database Setup and Configuration

FYI, Laravel is a database-agnostic framework, so it means that it allows for the use of various databases, including SQLite, MySQL, Postgres, and MS SQL. Laravel provide Eloquent as an Object-Relational Mapper (ORM) to simplify interactions with the database. We will create a MySQL database, which comes pre-installed with Laragon. To do this, open the Laragon application and press the ‘Database’ button to create the MySQL database that we will use in this project.

access DB Client , Heidi SQL, from Laragon main menu
Create MySQL database from Laragon’s Heidi SQL

Input the desired name for the database, for example “db_pendekin”. Once entered, the database will be created. Next, we need to change the .env file in our laravel project so that it can connect to the database we created. Open the .env file in our project and change the DB settings as follows :

DB_CONNECTION=pendekin
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_pendekin
DB_USERNAME=root
DB_PASSWORD=

The settings specified above are for configuring the database that we will be using in this project. We have named the connection “pendekin”, and are using the MySQL database, on the IP address of 127.0.0.1 (which is our localhost/pc) and can be accessed via port 3306. The database name is the one we previously created, in this case, “db_pendekin”. Also, we provide the username and password to access the database. Since it’s still localhost, it does not pose a security risk to include this information in this post.

The database configuration used can be found in config>>database.php . I made slight modification on lines 18 and lines 38 to 55 for easier explanation.

config/database.php

The code indicates that we are utilizing the ‘pendekin’ connection as specified in the ‘DB_CONNECTION’ variable within the .env file. If the ‘DB_CONNECTION’ variable is not found in the .env file, then the second option will be used, which is ‘mysql’.

This ‘pendekin’ configuration located “connections” array (Line 38 in config>>database.php). In the configuration files, it also references variables from the .env file. If the variable is defined in .env, it will use that value. Otherwise, it will take the second option/parameter.

It’s is important to note, unlike the .env file that should not be submitted to the repository. The config>>database.php file typically stored in the repository. Therefore, it’s considered best practice to store the credentials in the .env file. For a more detailed explanation, you can refer to the Laravel documentation at this link .

C. Model & Migration

After we know the database design that we will create, we can use Migration in Laravel. This migration feature is provided by Laravel to generate database schemas through Laravel directly. This simplifies the process of set up or alter tables, as it can be done through the use of code rather than use a separate database client. Additionally, the code used in this process can be easily adapted to work with different databases such as Postgres or SQLite.

Let’s try, open Laragon’s terminal and type the following command:


php artisan make:model ShortedLink -m
generated files by executing that commands

The command above is an Artisan Command to generate Schema migrations and Models for the shorted_link table. There are 2 files generated by executing the command.

If you want to create migrations and models separately, you can use the artisan commands make:migration and make:model.

Migration

The migration files are stored in the database>>migrations folder. Here is the code for our migration and I think it’s quite easy to understand the code.

migration code for ‘shorted_links’ table

— Line 16, we will create a table named ‘shorted_links’.
— Line 17, we will generate auto increment for this table.
— In line 19, we define the short_url field, with a data type of varchar up to 15 characters. Please adjust to your needs.
— Line 20 will generate a counter column with an integer data type that has a default value of 0.
— Line 21 will generate the column last_visit which has the data type timestamp and is nullable, which is not mandatory/ required when we create a row in this table.
— Line 22 will generate 3 timestamp columns, namely: created_at, updated_at,.
— Line 23 will generate column deleted_at with timestamp data type

Next, we need to execute this migration to create tables in the database via the following command:

php artisan migrate
php artisan migrate

As illustrated in the image above, five tables have been created. The additional four tables are pre-built in Laravel and have not been used in this tutorial for the sake of simplicity. If you open the Heidi SQL application, you will see those five tables. You can view the ‘shorted_links’ like the image below. If you wish to learn more about using migrations, you can refer to the official Laravel documentation at this link.

table generated from migration

— Models

Remember the Model in the MVC concept? Yes, Models are used to interact with databases. According to the tutorial above, we already have one model generated via the Laravel Artisan Command above. These models can be accessed in the App>>Models>>ShortedLink.php .

The file interacts directly with the ‘shorted_links’ table. By examining the file names generated by the commands, we can identify the naming conventions used by the framework. The Model class created follows the convention of using singular nouns and CamelCase, while the table generated through migration uses a plural noun and snake_case. When using English, it is recommended to follow these conventions as it aligns with Laravel’s naming conventions.

Let’s take a look at the ShortedLink.php file, in the code, it doesn’t say which table is related. If we follow the Laravel naming conventions above then there’s no problem. But if we don’t, we need to write it explicitly (Line 14).

Next, we also need to determine which fields we can fill in through the Model. Because by default, Model does not allow fields to be filled in directly, we need to specify which fields we can fill in, via the $fillable or $guarded property. If we use $fillable, it means that we need to explicitly specify which fields we can fill in. On the other hand, if we use $guarded, we need to fill in any columns that cannot be filled in by the user, for example, the id column as the Primary Key (PK) in this table.

In the code below, we write that the fields ‘long_url’, ‘short_url’, ‘counter’, ‘last_visit’ can be filled (Line 16). We also use SoftDeletes to flag deleted rows (Line 7 and Line 12). The following is the code for the ShortedLink.php model.

ShortedLink Model

To test the interaction with the database, we can use Tinker and Eloquent ORM. Tinker is a command line interface (CLI) in Laravel that we can use to execute code with the PHP programming language. This tool is very practical, we can use them to check code statements in the PHP language more briefly.

Meanwhile, Eloquent is an Object Relational Mapper that we use to access the database we have defined. By using Eloquent, we can use the same code, even though the database used is different. The code used is very intuitive and easy to understand. Okay, we will demonstrate inserting data using a model through Tinker in the terminal.

php artisan tinker

Use the following code to insert new data into the shorted_links table.

$url = App\Models\ShortedLink::create(['long_url'=>'blog.1ln.xyz','short_url' => 'blogini']);

The above code uses the Eloquent ORM to insert a row to database. We can see that by default Eloquent also fills in the created_at and updated_at columns. Let’s try updating the row using Eloquent as follows. We do a select query and then do an update. Is it easy to understand the syntax, isn’t it ?

Updating data using Model through Tinker CLI

We can also update with one line code / chaining code as follows.


$links = App\Models\ShortedLink::where('short_url','mylink')->update(['counter' => 4]);

Next, let’s try a delete query, like the terminal screenshot below. The deleted_at column will be filled if we use the delete command. We can use the following code to delete via Models with Eloquent ORM. (Remember, we are using SoftDeletes on the Model we have created).

Deleting data using Model through Tinker CLI

Next, let’s try the following code, to get row data where the column long_url has the extension “.xyz”.

Select data using Model through Tinker CLI

The code is equivalent to the following SQL query:

select * from shorted_links where long_url like '%.xyz'

There are still many Eloquent features that are very useful and can make it easier for us to develop applications with the Laravel Framework. For more details, you can access Laravel Official docs in this link

2. Views

In Views, we’ll focus on the view side of our web page. Of course, later it will also interact with the Route and Controller. But in this session, we will focus more on making the appearance first.

For its appearance, we will make it simple. On the main page, we will provide an input form and a button to generate short links according to the main functionality of the application being built. Okay, it’s easier for us to take an example of landing page template as provided by Start Bootstrap on this link.

I think the template fits our needs and mobile-friendly. Okay, let’s just download via that link, and extract files and move to public folder. So the structure of the folder should look like the image below.

add UI template to public folder

We need to make some modifications in the style.css file, related to the position (path) of the assets file that we have adjusted, which are located in public folder.

header.masthead
.call-to-action

After that, we copy and paste the index.html file into the resources>>view>>sb.blade.php . The .blade.php is an extension of the views file in Laravel. Remember the previous file that contains Laravel documentation? Yup, the filename is welcome.blade.php. Now, let’s go to routes/web.php and update the route as follows..

web.php

Ok, now we have 3 routes, each of them accessing a different view. Route /start_bootstrap to access the Start Bootstrap page we set up earlier.
I think we don’t need all the sections in the template earlier. I will only user 4 sections on the landing.blade.php page, which are:

Masthead, we use this as a form submit by the user to generate short links
Icons, we will use this to show the number of short links that we have generated and the number of visitors who visit short links through this website.
Image Showcases, this section is static, we write down the benefits of this website, like : Easy To Remember, Forever Free, and Always Accessible
Footer, in this section we will display the footer of this web, such as copyrights and links to our social media.

However, feel free to use other sections if you prefer. Let’s try to access the main page on this web, it should match with our expectations. On the main page, the Icons section will display variables that will be processed from Route to Views. Let’s begin by customizing our route first.

sending variable from routes to views

In the code above, we set up 2 variables, namely $shortlink_count and $visitor_count to be sent to views landing.blade.php using the compact function provided by Laravel. Don’t forget to write it using the string from the variable name. Next, we will change the side view landing.blade.php

In the code views, above, we will display the variables sent by the route namely {{$shortlink_count}} and {{$visitor_count}} . The directive {{ $variable }} is a Blade Directive which similar with php echo $variable. Now let’s try to use other Blade features so that the display is more modular by creating a skeleton from the page we created.

landing.blade.php

Let's create a file in resources>>view>>layouts.app.blade.php file. In that code, we create an HTML skeleton for our page.

app.blade.php

On line 19 we provide a place/section namely 'contents' to fill in content from this landing page.
On line 20, we add/attach a footer to this skeleton

Let’s try to create a file in resources>>views>>layouts>>footer.blade.php with the following code. The code matches the StartBootstrap template that we previously downloaded, but only in the footer section.

footer.blade.php

With the code above, our skeleton already has a footer. But we haven’t prepared the content yet. Let’s prepare it by creating the following file resources>>views>>layouts>>contents.blade.php It contains Mastheads (for URL input form), Icons (to display URL metrics and the number of visitors), and Image Showcase (For The Benefits use this short link).

contents.blade.php

After we refactor our views to make them more modular. Let’s modify landing.blade.php as follows.

resources>>views>>landing.blade.php

In the code above, we extend the template that we have provided in the resources>>layouts>>app.blade.php file so that this page will load the required styles and the footer we have prepared. At the app.blade.php file, we also provide a place for content with the syntax ‘@yield(‘content’)’. Meanwhile at the landing.blade.php file, we including the ‘contents.blade.php’ file that we previously created.

This will be very useful when we create complex websites, where consist of headers, footers, sidebars, etc. This is where blade templating and blade directives come in handy. More complete documentation about Blade can be accessed on the following page.

contents.blade.php

Next, let’s try to look at the form. Let’s edit the resources>>views>>layouts>>contents.blade.php file in the MastHead section. In that code, line 9, we add @csrf which is a Blade Directive to avoid Cross-Site Request Forgery. We should mainly use it when accessing routes with POST, PUT, PATCH, and DELETE methods in our Laravel web. But for simplicity, in the following example, our form still uses the GET method (line 7) and points to the route we defined earlier, namely ‘/laravel-welcome’.

Let’s try to access the page, and press the button. We will be redirected to the ‘laravel-welcome’ route. Look at the url in the web browser, something like this:

http:// pendekin.test/laravel-welcome?_token=RBEGQ3qbiH4OgSN1W5eDCihqdizdGEmY0RQXOfYu.

This _token variable is used in the CSRF protection above. More details about CSRF protection in Laravel can be read in the following documentation.

I think that’s enough for the tutorial about Models and Views. I hope it’s clear and useful for us. There are still forms but we will discuss them further together with the Controller considering they are very related.

If you feel this tutorial is helpful please share this post, clap, and follow me on Medium. Please don’t hesitate to ask in the comments if you have any questions or suggestions. See you guys on the next posts.

--

--

Agri Kridanto

I'm a software developer with skills in web & mobile development. Proficient in PHP, Javascript and Java. Also experienced in IoT & Machine Learning research