In this guide we are going to create URL shortener. Wi will use Laravel 8 and VueJS. So for first of all make sure you have following requirements fulfilled.
composer require laravel/ui // For creating login and register pages with VueJS setup. php artisan ui vue --auth npm install npm install vue-loader@^15.9.7 --save-dev --legacy-peer-deps npm update vue-loader // For compiling npm run dev or npm run watch
After this now create a project
Once you have a new project change "welcome.blade.php". file to "urlshortener.blade.php".
this file code looks like this
@extends('layouts.app') @section('styles') @endsection @section('content') <div id="app" class="wrapper_url_shortener"> <url-shortener authorized-user="{auth()->user()->id ?? null}"></url-shortener> </div> @endsection
Here we used a vuejs component so create a component with name "UrlShortener.vue". and this file code looks like this.
<template> <div class="container"> <div class="row"> <div class="col-md-12"> <div class="shortner"> <div class="section-heading text-center"> <h1>URL Shortener</h1> <br> <div class="py-2" align="center"> <div class="pageIntroDescription border border-info p-3 mb-0"> Professinal Url Shortener, Free and Advanced... </div> </div> <br> <div v-if="AuthorizedUser"> <form action="" class="form"> <div class="input-group"> <input type="text" id="p1" placeholder="Put Url here" v-model="url" class="form-control addUrlInput"> </div> <br> <div> <button class="btn btn-dark" v-on:click.prevent='shortenUrl'> Process Url </button> </div> </form> <br> <p v-if="!urlNotFound" class="alert alert-danger"> Url is not Valid </p> <div class="copyLink mb-5"> <span id="output_url"></span> <span id="clipBoard" v-on:click.prevent="copyContent"> {copyTextString} </span> </div> </div> <div v-else> <h5> You are required to register with us</h5> <hr> To shorten your urls <hr> <a href="/register"> <small> Register Here </small> </a> or <a href="/login"> <small> Login Here </small> </a> </div> </div> </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Component mounted.') }, props:['AuthorizedUser'], data(){ return { url:null, urlNotFound: true, copyTextString: 'Copy Text To Clipboard', response:null, } }, methods:{ shortenUrl(){ let self = this; let newUrl = self.url; let newArray = newUrl.split('//'); let counter = 0; let resultNewUrl = Math.round((Math.pow(36,8) - Math.random() * Math.pow(36, 8))).toString(36).slice(1); for(let i = 0; i < newArray.length; i++){ if(newArray[i] == 'http:' || newArray[i] == 'https:'){ counter++; } if(counter == 0){ let newArrayOne = newUrl.split('.'); if(newArrayOne[i] == 'www'){ counter++; } let newArrayTwo = newUrl.indexOf('.com'); if(newArrayTwo >= 0){ counter++; } } if(counter ==0){ self.urlNotFound = false; }else{ let currentUrl = window.location.href+'u/'+resultNewUrl; axios.post('/url/shorten',{ url: newUrl, shortlink: currentUrl }).then(function(response){ self.response = response.data; $('.copyLink').fadeIn(500); $('.copyLink').siblings('.form').find("#p1").val(self.response); //self.url = self.response; console.log(self.response); }); } } }, copyContent(){ $("#p1").select(); this.copyTextString = 'Url Coppied Successfully'; document.execCommand("copy"); this.url = this.response; } } } </script> <style scoped> .copyLink{ display:none; } #clipBoard{ display:block; margin-top: 28px; background-color: #03cbf8; color:#fff; font-weight: 900; font-size:17px; } #clipBoard:hover{ background-color:#333; } #clipBoard:visited, #clipBoard:active, #clipBoard:focus{ background-color:green; color:#333; } </style>
Mainly we get user url and check if it is valid in function "shortenUrl". and then we store url. We also have a function "copyContent" to allow user copy generated url just by clicking on button.
Our "routes" are defined in "web.php"
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\UrlShortenerController; Route::get('/', function () { return view('urlshortener'); }); Auth::routes(); Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home'); // redirect to original url. Route::get('/u/{any}', [UrlShortenerController::class, 'handle']); // Store shorten url. Route::post('/url/shorten', [UrlShortenerController::class, 'store']);
Also register you component in "app.js"
Vue.component('example-component', require('./components/ExampleComponent.vue').default); Vue.component('url-shortener', require('./components/UrlShortener.vue').default); // Here we are registering component const app = new Vue({ el: '#app', });
the layout file must have jquery included
<!doctype html> <html lang="{ str_replace('_', '-', app()->getLocale()) }"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{ csrf_token() }"> <title>{ config('app.name', 'Laravel') }</title> <!-- Scripts --> <script src="{ asset('js/app.js') }" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet"> <!-- Styles --> <link href="{ asset('css/app.css') }" rel="stylesheet"> @yield('styles') </head> <body> <div id="app"> <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm"> <div class="container"> <a class="navbar-brand" href="{ url('/') }"> { config('app.name', 'Laravel') } </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{ __('Toggle navigation') }"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <!-- Left Side Of Navbar --> <ul class="navbar-nav me-auto"> </ul> <!-- Right Side Of Navbar --> <ul class="navbar-nav ms-auto"> <!-- Authentication Links --> @guest @if (Route::has('login')) <li class="nav-item"> <a class="nav-link" href="{ route('login') }">{ __('Login') }</a> </li> @endif @if (Route::has('register')) <li class="nav-item"> <a class="nav-link" href="{ route('register') }">{ __('Register') }</a> </li> @endif @else <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> { Auth::user()->name } </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{ route('logout') }" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> { __('Logout') } </a> <form id="logout-form" action="{ route('logout') }" method="POST" class="d-none"> @csrf </form> </div> </li> @endguest </ul> </div> </div> </nav> <main class="py-4"> @yield('content') </main> </div> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script> </body> </html>