کوتاه کننده لینک با PHP/MYSQL/JS

کوتاه کننده لینک با PHP/MYSQL/JS

کوتاه کننده لینک با پی اچ پی ، مای اس کیو ال و جاوا اسکریپت – ساخت یک انتقال دهنده لینک نیازمند این است که راه حلی را داشته باشیم که بتوانیم یک رشته طولانی را به یک رشته کوتاه تبدیل کنیم .

در این آموزش یک URL Shortener نیمه حرفه ای را خواهیم ساخت که از کیفیت خوبی برخوردار خواهد بود و از تکنولوژی Ajax پشتیبانی می کند .

از این رو با در این آموزش با تابع های کاربردی مثل :

  • crc32 : این تابع رشته را گرفته و یک عدد 10 رقمی به ما برمی گرداند .
  • base_convert : می توانیم داده های عددی را به مبناهای مختلفی تبدیل کنیم .
  • filter_var : با کمک این تابع می توانیم ورودی های مختلفی مثل ایمیل ، url و … را اعتبارسنجی کنیم .


فایل index.php

خط 18 : از اونجایی که فرم ajax خواهد بود زمانی که آدرس وارد شد و کاربر ENTER زد نمی خواهیم هدایت بشیم بنابراین با onSubmit مقدار false برمی گردانیم کــــه ریدایرکت نشیم .
خط 19 : pattern را برای ورودی http و https تنظیم می کنیم که با یکی از این 2 شروع شود .

<?php
require_once "functions.php";
require_once "func.actions.php";
if(!empty($_GET['u']))require_once "redirect.php";
?>
<!DOCTYPE html>
<html lang="fa">
<head>
    <meta charset="UTF-8">
    <title>Rapidcode.iR - سورس کد</title>
    <link rel="stylesheet" href="static/css/main.css">
</head>

<body>
    <div class="container">
        <a id="introduce" href="https://rapidcode.ir" target="_blank">رپید کد • کتابخانه مجازی برنامه نویسان</a>

        <form onSubmit="return false;">
            <input autofocus pattern="https:\/\/.*|http:\/\/.*" type="url" name="url-inp" id="url-inp"
                placeholder="لینک مورد نظر برای کوتاه شدن"><br><br>
            <input type="button" id="submit" value="کوتاه کن">
        </form>

        <?php if(isset($GLOBALS['is_url_correct']) && !$GLOBALS['is_url_correct']) echo generate_html_message("آدرس مورد نظر در پایگاه داده یافت نشد ." , "warning") ?>
        <?php if(!empty($GLOBALS['info_msg'])) echo $GLOBALS['info_msg'] ?>

        <div class="short-link-wrapper">
            <button id="copy-short-link" data-clipboard-target="#short-link-copy">
                <img src="static/img/clippy.svg" alt="copy text">
            </button>
            <input id="short-link-copy" type="url" readonly placeholder="short link goes here (;" dir="ltr">
        </div>
    </div>

    <script src=static/js/lib/clipboard.min.js> </script>
    <script src="static/js/app.js"></script>
</body>
</html>


فایل contants.php برای ثابت ها

<?php

define("HOST" , "localhost");
define("USERNAME" , "root");
define("PASSWORD" , "");
define("DB" , "link_db");
define("CURRENT_TIME" , date("Y/m/d H:i:s"));

?>


فایل functions.php برای توابع دیتابیس و تابع های کاربردی

<?php

require_once "constants.php";
$table = "link_tbl";

function validate_url(string $url)
{   
    $url_list = parse_url($url);
    $host = $url_list['host'];
    $path = $url_list['path'];
    $url = str_ireplace($path , urlencode($path) , $url);
    $url = str_ireplace($host . "%2f" , $host . "/" , $url);
    $url = filter_var($url, FILTER_VALIDATE_URL);
    return $url;
}

function show_json_message($array_data)
{
    return json_encode($array_data);
}

function generate_url_token($url)
{
    $crc32_number = crc32($url);
    $encoded_url = base_convert($crc32_number, 10, 36);
    $encoded_url_list = str_split($encoded_url, 1);
    $encoded_url = "";

    for ($i = 0; $i < sizeof($encoded_url_list); $i++) {
        $current_index = $encoded_url_list[$i];
        $letter = is_numeric($current_index) ? $current_index : strtoupper($current_index);
        $encoded_url .= $letter;
    }

    return $encoded_url;
}

function generate_html_message($message = "", $type = "notice")
{
    return "<div class=\"msg {$type}\"><p>{$message}</p></div>";
}

function remove_end_slash($url)
{
    $url = strrev($url);
    $url = str_split($url, 1);

    if ($url[0] == "/") unset($url[0]);

    $url = join($url);
    $url = strrev($url);

    return $url;
}

function update_views($column, $short_url)
{

    $mysqli = new mysqli(HOST, USERNAME, PASSWORD, DB);
    $current_time = CURRENT_TIME;
    $row_updated = 0;

    $mysqli->set_charset("utf8");
    $stmt = $mysqli->stmt_init();
    $query = "UPDATE `{$GLOBALS['table']}` SET `views` = views + 1 , `date_last_view` = ? WHERE {$column} = ?";

    $stmt->prepare($query);
    $stmt->bind_param('ss', $current_time, $short_url);

    if ($stmt->execute()) {
        $row_updated = $stmt->affected_rows ? $stmt->insert_id : 0;
    }

    $stmt->close();
    $mysqli->close();

    return $row_updated;
}

function row_select($user_query, $column, $select = "*")
{

    $mysqli = new mysqli(HOST, USERNAME, PASSWORD, DB);
    $row = 0;

    $mysqli->set_charset("utf8");
    $stmt = $mysqli->stmt_init();
    $query = "SELECT {$select} FROM `{$GLOBALS['table']}` WHERE {$column}=?";

    $stmt->prepare($query);
    $stmt->bind_param("s", $user_query);

    if ($stmt->execute() && $res = $stmt->get_result()) {
        if ($stmt->affected_rows || $res->num_rows) {
            $row = $res->fetch_assoc();
        }
    }

    $stmt->close();
    $mysqli->close();

    return $row;
}

function row_insert($url)
{
    $mysqli = new mysqli(HOST, USERNAME, PASSWORD, DB);
    $views = 0;
    $token_url = generate_url_token($url);
    $inserted_id = 0;
    $current_time = CURRENT_TIME;

    $mysqli->set_charset("utf8");
    $stmt = $mysqli->stmt_init();

    $query = "INSERT INTO `{$GLOBALS['table']}` (link_original , link_short , date_submitted , date_last_view , views) VALUES (? , ? , ? , ? , ?)";

    $stmt->prepare($query);
    $stmt->bind_param('ssssi', $url, $token_url, $current_time, $current_time, $views);

    if ($stmt->execute()) {
        $inserted_id = $stmt->affected_rows ? $stmt->insert_id : 0;
    }

    $stmt->close();
    $mysqli->close();

    return $inserted_id;
}


فایل func.actions.php

این فایل شامل 3 تابع است که 3 عمل اصلی را هم انجام می دهد :

  1. تابع func_action_submit : برای زمانی که لینکی را ثبت می کنیم .
  2. تابع func_action_redirect : کاربر را با لینک کوتاه به لینک اصلی هدایت می کند .
  3. تابع func_action_redirect_info : اطلاعاتی از لینک کوتاه ثبت شده به ما می دهد شامل تاریخ ثبت لینک ، تاریخ آخرین ارجاع یا بازدید از لینک ، تعداد بازدید .
<?php

function func_action_submit($response_list, $user_url)
{
     $row = row_select($user_url, "link_original");
     if (empty($row)) {
          $row = row_insert($user_url);
          if (empty($row)) {
               $response_list['status'] = 0;
               $response_list['msg'] = "خطایی در هنگام ثبت داده در دیتابیس رخ داده .";
               die(show_json_message($response_list));
          } else {
               $response_list['status'] = 1;
               $response_list['msg'] = "آدرس مورد نظر با موفقیت ثبت گردید .";
               $response_list['data'] = json_encode(row_select($row, "id", "link_short"));
               die(show_json_message($response_list));
          }
     } else {
          $response_list['msg'] = "این آدرس از قبل ثبت شده";
          $response_list['data'] = json_encode(["link_short" => $row['link_short']]);
          die(show_json_message($response_list));
     }
}

function func_action_redirect($user_url)
{
     $url_data = row_select($user_url, "link_short", "link_original");
     $GLOBALS['is_url_correct'] = false;
     if (!empty($url_data)) {
          update_views("link_short", $user_url);

          header("Location: {$url_data['link_original']}");
          $GLOBALS['is_url_correct'] = true;
     }
}

function func_action_redirect_info($user_url)
{
     $url_data = row_select($user_url, "link_short", "*");
     $url_data['link_original'] = urldecode($url_data['link_original']);
     $GLOBALS['is_url_correct'] = false;
     if (!empty($url_data)) {
          $GLOBALS['info_msg'] = "<div style=\"direction: ltr;font-size:25px\" class=\"msg success\"><p>{$url_data['link_original']}</p></div><table id=\"statistics\"><tr><td>تاریخ ثبت لینک : </td><td>{$url_data['date_submitted']}</td></tr><tr><td>تاریخ آخرین ارجاع لینک : </td><td>{$url_data['date_last_view']}</td></tr><tr><td>تعداد ارجاع : </td><td>{$url_data['views']}</td></tr></table>";
          $GLOBALS['is_url_correct'] = true;
     }
}


فایل redirect.php

این تابع مشخص می کند که کاربر با لینک کوتاهی که وارد کرده است می خواهد به لینک اصلی هدایت شود یا آمار لینک را مشاهده کند .

<?php

if($_GET['u'] && !empty($_GET['info'])){
    func_action_redirect_info($_GET['u']);
}else if($_GET['u']){
    func_action_redirect($_GET['u']);
}

?>


فایل api.php

از اسمی که دارد برای endpoint استفاده می شود که درخواست های ajax به این فایل ختم می شود .

<?php

header("Content-Type: application/json");
require_once "functions.php";
require_once "func.actions.php";

$response_list = [
    "status" => 0,
    "msg" => "",
    "data" => []
];

$action_list = [
    "submit",
];

$user_url = @$_POST['inp-url'];
$action = @$_POST['action'];

if(empty($action) || !in_array($action , $action_list)){
    $response_list['msg'] = "پارامتر action معتبر نمی باشد .";
    die(show_json_message($response_list));
}

$user_url = remove_end_slash($user_url);

if(empty($user_url) || !validate_url($user_url)){
    $response_list['msg'] = "لینک معتبری وارد نشده است .";
    die(show_json_message($response_list));
}

$user_url = urldecode($user_url);
call_user_func("func_action_" . $action , $response_list , $user_url);

?>


همچنین از clipboard.js برای کپی کردن لینک ها در این پروژه استفاده کردیم که می تونید از اینجا کتابخانه را دانلود کنید .

فایل app.js

const clipboardJS = new ClipboardJS('#copy-short-link');

const submitDOM = document.getElementById("submit");
const urlInput = document.getElementById("url-inp");
const shortLinkWrapper = document.getElementsByClassName("short-link-wrapper")[0];


submitDOM.addEventListener("click", handlerSubmit);


function handlerSubmit() {
    if (!urlInput.checkValidity()) {
        alert("آدرس داده شده معتبر نمی باشد .");
        return false;
    }

    submitDOM.setAttribute("disabled", "disabled");
    submitDOM.value = "در حال دریافت لینک ...";

    funcPostRequest(function (xhr) {
        const response = xhr.currentTarget.response;
        let data = response.data;

        if(typeof data == "string") data = JSON.parse(data);

        
        window.alert(response.msg);
        if (data['link_short']) {
            shortLinkWrapper.classList.add("active");
            submitDOM.removeAttribute("disabled");
            submitDOM.value = "کوتاه کن";
            shortLinkWrapper.querySelector("#short-link-copy").value = location.origin + "?u="+ data['link_short'];
        }



    }, function () {
        alert("خطایی رخ داده برای جزئیات بیشتر تب console را باز کنید")
        console.warn("[XHR Error]");

        submitDOM.removeAttribute("disabled");
        submitDOM.value = "کوتاه کن";
    });

}


function funcPostRequest(cbOnload, cbOnerror) {
    const xhr = new XMLHttpRequest();
    xhr.responseType = "json";

    const params = new FormData;
    params.append("action", "submit");
    params.append("inp-url", urlInput.value);

    xhr.open("POST", location.origin + "/api.php");

    xhr.onload = cbOnload;
    xhr.onerror = cbOnerror;

    xhr.send(params);
}


فایل main.css

body{
    background-image: url(../img/sea.jpg);
    background-size: cover;
}

.active{
    display: block !important;
}

#url-inp{
    transition: 0.3s all;
    width: 40%;
    border: none;
    outline: none;
    padding: 10px;
    border-radius: 25px;
    text-align: center;
    font-weight: bold;
}

#url-inp:focus{
    width: 50%;
    border: 1px solid #000;
}

#submit{
    border: none;
    background-color: #2196f3;
    color: white;
    font-weight: bold;
    font-size: 25px;
    padding: 10px 50px;
    border-radius: 25px;
    cursor: pointer;
}

#submit:hover{
    background-color: #137dd3;
}

.msg{
    background-color: silver;
    color: #000;
    border-radius: 15px;
    display: inline-block;
    padding: 5px 35px;
    margin: 15px auto;
    font-weight: bold;
}

.msg.warning{
    background-color: #ffa500;
}

.msg.success{
    background-color: #3f51b5;
    color: white;
}

#statistics{
    font-weight: bold;
    background-color: rgb(255 255 255 / 79%);
    border-radius: 4px;
    width: 50%;
    margin: 0 25%;
}

#statistics td{
    padding: 12px;
}

.short-link-wrapper{
    display: none;
}

#short-link-copy{
    margin-top: 50px;
    font-size: 24px;
    background-color: #4caf50;
    border: 3px #fff solid;
    outline: none;
    color: white;
    padding: 3px 10px;
    border-radius: 15px;
}

.short-link-wrapper button{
    height: 25px;
}

.short-link-wrapper button img{
    width: 15px;
}


خروجی برنامه

دموی کوتاه کننده لینک با PHP , MYSQL , JAVSCRIPT


دانلود پروژه کوتاه کننده لینک
لینک کوتاه مقاله

ارسال نظر

جهت استفاده از کد حتما از تگ pre استفاده نمایید .

contact us