無脂肪縮短連結 (F3)

無脂肪縮短連結 (F3)

在 13 歲的時候縮短連結並不丟臉,對吧? 初學者,而且不僅僅是初學者,應該在學習一些新框架的同時嘗試編寫自己的 Link Tamer。 這就是我所做的。 我能說什麼 - 第五個引導程序,一個低脂肪框架和一個靈魂。

這裡 演示, 和這裡 。 對於像我這樣的讀者😉

框架,對嗎?

當然不是 Laravel 之類的 - 今天我們就用 65 KB 湊合 無脂框架。 如果你熟悉 Python Flask,你會感覺這已經在某個地方完成了:

#роутинг во Фласке
@app.route('/')
def hello_world():
    return 'Hello, World!'
//роутинг в Обезжиренном
$f3->route('GET /',
    function() {
        echo 'Hello, world!';
    }
);

好吧,算了。 下載 來自異地的 .zip,將其解壓縮到一個資料夾中,該資料夾同時在您最喜歡的程式碼編輯器中開啟。 清除 的index.php 並從中刪除所有內容 /ui.

這裡的一切都非常簡單 - 在資料夾中 ui 我們擁有所有視圖,或者簡單地說,升級後的 HTML 模板,當使用者造訪特定 URL 時,我們將向他們顯示這些模板。

這是我們「應用程式」的骨架:

<?php
//Файл: index.php

// Kickstart the framework
$f3=require('lib/base.php');
$f3->set('DEBUG', 1);
if ((float)PCRE_VERSION<8.0)
    trigger_error('PCRE version is out of date');
$f3->config('config.ini');

//ВЕСЬ ОСТАЛЬНОЙ КОД БУДЕМ ПИСАТЬ ЗДЕСЬ

$f3->run();

這就是您開始時需要知道的全部內容。 讓我們開始編碼吧!

[為了開發我使用了本地 XAMPP 在 Windows 和 VS Code 上, 文章寫於Noushen]

主頁

讓我們從主頁開始。 符合邏輯,對吧?

//Файл: index.php

$f3->route('GET /',
    function($f3) { //чтобы использовать функции F3 передаем его в роут
                $view = new View; // создаем вьюшку
        echo $view->render('home.htm'); //рендерим шаблон
    }
);

現在您需要編寫這個模板。 為了簡單起見,我使用了 引導程式 v5 alpfa。

不要忘記在資料夾中建立所有模板 使用者介面, 否則他們 不會 對框架可見

<!-- Файл: ui/home.htm -->

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="<?php echo $ENCODING; ?>" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Пишем (код), сокращаем (ссылки)!</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
    </head>
    <body class="text-center bg-dark text-light"> <!-- темная тема ;) -->

        <!-- менюшка -->
        <nav class="m-2">
            <ul class="nav nav-pills justify-content-center">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">Главная</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Статья на Хабре</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="https://nikonovs.ru">Создатель</a>
                </li>
            </ul>
        </nav>

        <div class="container">
        <h1>Короткие ссылки уже здесь.</h1>

        <!-- Будем отправлять данные POST-запросом на /newLink -->
        <form class="mt-5 mb-3" action="/zh-TW/newLink/" method="POST">
            <div class="row justify-content-center">
                <div class="col-auto">
                <label for="inputLink" class="col-form-label">Введи ссылку:</label>
                </div>
                <div class="col-auto">
                <input required placeholder="https://" type="url" name="link" id="inputLink" class="form-control mb-1" aria-describedby="inputLink">
                </div>
                <div class="col-auto">
                <button type="submit" class="btn btn-outline-primary">Сократить!</button>
                </div>
            </div>
        </form>

        <!-- немного -->
        <p class="text-left m-auto mb-5" style="max-width: 30rem;">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Omnis illum molestiae hic fugiat molestias nemo, architecto beatae repellat ullam exercitationem non ab, necessitatibus maxime quod iure ipsa quam quos! Reprehenderit. Lorem ipsum dolor, sit amet consectetur adipisicing elit. Necessitatibus eos sapiente voluptates veniam sequi delectus totam tenetur praesentium obcaecati. Repudiandae quisquam, ipsa ullam corrupti molestiae minima optio nihil est modi?</p>

        <footer class="m-2">Сделано с <img width="20" height="20" src="https://image.flaticon.com/icons/svg/833/833472.svg" alt="любовью">, <a href="https://v5.getbootstrap.com/">пятым Bootstrap'ом</a>    и <a href="https://fatfreeframework.com/">без жира</a></footer>
        </div>
    </body>
</html>

就這樣,我們的主頁已經可以運行了。 該表單會傳送帶有需要縮短的連結的 POST 請求。
現在來了有趣的部分(不是)。

使用資料庫

讓我們建立一個資料庫 - MySQL。 如果您安裝了 PhpMyAdmin,則建立一個新資料庫“鏈接」然後執行這個 SQL:

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `links` (
  `code` varchar(4) NOT NULL,
  `link` varchar(1000) NOT NULL,
  `hits` int(255) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `links`
  ADD UNIQUE KEY `code` (`code`);

我們將為每個連結設定 3 個欄位:

  1. 代碼是域名後的隨機 4 個字符,透過它進行重定向,例如 example.com/ABC1
  2. 關聯 - 未縮短 關聯。
  3. 點擊數 - 縮短連結的點擊次數。

我將簡要告訴您使用資料庫的原理,而不需要脂肪。

<?php
//сначала нужно подключиться к БД
$db = new DBSQL(
    'mysql:host=localhost;port=3306;dbname=linker',
    'root',
    ''
);

//Дальше есть два варианда работы с данными:

//Можно установить переменную в Фреймворк c помощью обычного SQL-запроса:
$f3->set('result', $db->exec('SELECT * FROM wherever')); 
//они будут доступны в шаблонах, как <?= $resul ? >

//А можно использовать встроенный SQL Mapper:
$row = new DBSQLMapper($db, 'links');

$row->load(array('link="https://habrahabr.ru"')); //теперь из этого объекта доступны все колонки строки, где ссылка на Хабр:
$row_value = $row->somerow; //Вот так

// Естесственно можно изменять значения:
$row->link = 'https://habr.com';
$row->save(); //изменения нужно сохранить, а что вы думали

// больше информации по работе с БД доступно здесь: https://a.nikonovs.ru/MPHR Настоятельно рекомендую прочитать, хотябы с помощью переводчика, встроенного в браузер.
?>

讓我們開始縮短。

處理新連結

在中建立一個新視圖 指數,它將處理來自主頁上表單的請求。

首先,讓我們建立一個新的,但與第一個 (home.htm) 模板非常相似的模板 - ”新連結.htm".
在那裡,我們將顯示已經縮短的連結及其點擊次數(要再次查看這些“統計資料”,您需要再次縮短相同的連結 - 地址將保持不變)。
為了產生輸出,我們將使用「變數傳遞」技巧:

<?php
//Файл: нет (пример)

//устанавливаем переменную в index'е и рендерим шаблон
$f3->set('link', $shorted_link);
$view = new View;
echo $view->render('newLink.htm');
//теперь в шаблоне можно использовать:
<?= $link ?>

這是清單 新連結.html:

<!-- Файл: newLink.htm -->

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="<?php echo $ENCODING; ?>" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Пишем (код), сокращаем (ссылки)!</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha1/css/bootstrap.min.css" integrity="sha384-r4NyP46KrjDleawBgD5tp8Y7UzmLA05oM1iAEQ17CSuDqnUK2+k9luXQOfXJCJ4I" crossorigin="anonymous">
    </head>
    <body class="text-center bg-dark text-light">
        <nav class="m-2">
            <ul class="nav nav-pills justify-content-center">
                <li class="nav-item">
                    <a class="nav-link" aria-current="page" href="/zh-TW/">Главная</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Статья на Хабре</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="https://nikonovs.ru">Создатель</a>
                </li>
            </ul>
        </nav>

        <div class="container">
        <h1>Короткие ссылки уже здесь.</h1>

        <!-- Убираем из формы функционал формы и выводим переменные -->
        <form class="mt-5 mb-3">
            <div class="row justify-content-center">
                <div class="col-auto">
                    <label for="inputLink" class="col-form-label">Сократили:</label>
                </div>
                <div class="col-auto">
                    <input disabled required type="url" name="link" id="inputLink" class="form-control disabled" aria-describedby="inputLink" value="<?= $link ?>">
                </div>
            </div>
            <p class="m-2 text-secondary">По этой ссылке перешли: `<?= $hits ?>`</p>
        </form>

        <a href="/zh-TW/" class="mt-3 mb-5 btn btn-primary btn-lg">ВЕРНУТЬСЯ НА ГЛАВНУЮ</a>

        <footer class="m-2">Сделано с <img width="20" height="20" src="https://image.flaticon.com/icons/svg/833/833472.svg" alt="любовью">, <a href="https://v5.getbootstrap.com/">пятым Bootstrap'ом</a>    и <a href="https://fatfreeframework.com/">без жира</a></footer>
        </div>
    </body>
</html>

我們自己寫路線。

$f3->route('GET|POST /newLink', //мы будем обрабатывать и POST и GET
    function($f3) {

            $db = new DBSQL( //Подключение к БД новое в каждом Роуте
                'mysql:host=localhost;port=3306;dbname=linker',
                'root',
                ''
            );

            //прекрасная функция генерации радомных символов:
            $permitted_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            function generate_string($input, $strength = 4) {
                $input_length = strlen($input);
                $random_string = '';
                for($i = 0; $i < $strength; $i++) {
                    $random_character = $input[mt_rand(0, $input_length - 1)];
                    $random_string .= $random_character;
                }

                return $random_string;
            }

            //проверка на повторение link - нам же не нужно чтобы каждый раз генерировались новые ссылки. link - уникальный.
            $check = new DBSQLMapper($db,'links');
            $check->load(array('link="'. $link .'"'));
            if ($check->dry()) {
                $g_code = generate_string($permitted_chars);
                $row = new DBSQLMapper($db,'links');
                $row->reset();
                $row->code = $g_code;
                $row->link = $link;
                $row->save();
            } else {
                $g_code = $check->code; //если link повторяется, то показываем старый код
            }

            $short_link = 'https://'. $_SERVER['HTTP_HOST'] . '/' . $g_code; //собираем конечную ссылку

            //параметры из $_POST можно получить с помощью $f3->get('POST'), поддерживается точечная нотация (поправьте, если неправильно называю): параметр "link" можно получить так: 
            $link = $f3->get('POST.link');

            if ( !empty($f3->get('POST')) ) { //Выдаем HTML, только если POST не пустой.

            $f3->set('link', $short_link);
            $f3->set('hits', $check->hits);
            $view = new View;
            echo $view->render('newLink.htm');

            } else { //иначе - редирект на главную
                $f3->$f3->reroute('/');
            }

        }
);

準備好! 其實很簡單。

重新導向

還剩下一點點要做:

  1. 從 URL 取得參數
  2. 檢查它在資料庫中的存在
  3. 從資料庫中取得對應的鏈接
  4. 重定向用戶
  5. 利潤!

上一條Route之後我們繼續寫程式碼。

$f3->route('GET /@code', //указываем параметр после "@", он попадет в PARAMS
    function($f3) {

        //снова определяем $db
        $db = new DBSQL(
            'mysql:host=localhost;port=3306;dbname=linker',
            'root',
            ''
        );

        $code = $f3->get('PARAMS.code'); //получаем параметр

        $link = new DBSQLMapper($db,'links'); 

        //если получается получить ссылку из БД - получаем, увеличиваем количество переходов и перенаправляем
        if ($link->load(array('code="'.$code.'"', 'link=?'))) {
            $link->hits++;
            $link->save();

            $f3->reroute($link->link);
        } else {
            $f3->reroute('/'); //а если такой ссылки нет - милости просим на главную
        }
    }
);

您可能已經註意到,在路線中 新鏈接, 並且在上面的路線中將定義相同的東西 - 畢竟 可能會匹配“newLink”(不能,生成器只包含大寫字母),但由於它是先定義的,所以會先執行。

$f3→運行()!

謝謝閱讀!
如果您寫下評論並糾正我(如果有問題),我會很高興。

作為家庭作業或作者(我)懶惰的證明,我留下了一份可以做什麼的清單。 最好邊做邊學!

  • 這當然不太可能,但是當生成時 $g_代碼 可能會再次發生,所以我建議你寫一個函數來檢查這一點。
  • 也可以進行正常統計並切換到後顯示 /@代碼/統計
  • 禁止建立指向鏈接縮短服務本身的鏈接,創建“受保護”免受縮短的資源列表
  • 我強烈建議,即使是這麼小的事情,你也可以在伺服器端進行輸入驗證,並顯示相應的錯誤,你不應該依賴於在輸入字段中添加 required 屬性和 type = “url”
    紅色同志

  • 在評論中提出建議...

    聯繫)

來源: www.habr.com

添加評論