
Сокращать ссылки в 13 лет не стыдно, верно?
Новичку, да и не только новичку, стоит попробовать написать свой Укротитель Ссылок, походу изучая какой-нибудь новый фреймворк. Чем я и занялся. Что сказать — пятый бутстрап, обезжиренный фреймворк и частичка души.
Вот демо, а вот код. Для таких читателей, как я 😉
Фреймворк, не так ли?
Конечно не Laravel и тому подобные — сегодня обойдёмся 65-ю килобайтами FatFreeFramework. Если Вы знакомы с Python Flask, то возникнет ощущение, что где-то это уже было:
#роутинг во Фласке @app.route('/') def hello_world(): return 'Hello, World!'
//роутинг в Обезжиренном $f3->route('GET /', function() { echo 'Hello, world!'; } );
Ладно, забудьте. Скачиваем .zip с офф.сайта, распаковываем в папку, которая в этот же миг открывается в вашем Любимом Редакторе Кода. Очистите index.php и удалите все из /ui.
Здесь все предельно просто — в папке ui у нас все Вьюшки, а если по простому — прокачанные ХТМЛ шаблоны, которые мы будем показывать пользователю при заходе на определенный 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, статья написана в Ноушене]
Homepage
Начнем с главной страницы. Логично, правда?
//Файл: index.php $f3->route('GET /', function($f3) { //чтобы использовать функции F3 передаем его в роут $view = new View; // создаем вьюшку echo $view->render('home.htm'); //рендерим шаблон } );
Теперь нужно этот самый шаблон написать. Для простоты я использовал бутстрап v5 alpfa.
Не забудьте создавать все шаблоны в папке ui, иначе они не будут видны фреймворку
<!-- Файл: 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="/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;">Довольно часто при общении в интернете люди пересылают друг другу ссылки. Иногда эти ссылки бывают длинными. Совсем иногда — очень длинными. Но почти всегда — слишком длинными. Для того чтобы избавиться от этой проблемы, был создан этот сайт. Да, я знаю, что таких тысячи, но этот же лучше! А дальше все просто: вставляете ссылку в поле для ввода, нажимаете "Сократить!" и получаете короткий, совсем короткий URL. © <a href="https://clck.ru">Кликер</a></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, то создайте новую БД "linker", а потом выполните этот 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 поля у каждой ссылки:
- Code — это рандомные 4 символа после домена, по которым будет происходить перенаправление, вида example.com/ABC1
- Link — Не сокращенная ссылка.
- Hits — количество переходов по сокращенной ссылке.
Кратко расскажу принцип работы с БД, без жира.
<?php //сначала нужно подключиться к БД $db = new DB\SQL( 'mysql:host=localhost;port=3306;dbname=linker', 'root', '' ); //Дальше есть два варианда работы с данными: //Можно установить переменную в Фреймворк c помощью обычного SQL-запроса: $f3->set('result', $db->exec('SELECT * FROM wherever')); //они будут доступны в шаблонах, как <?= $resul ? > //А можно использовать встроенный SQL Mapper: $row = new DB\SQL\Mapper($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 Настоятельно рекомендую прочитать, хотябы с помощью переводчика, встроенного в браузер. ?>
Приступаем к Укорачиванию.
Обработка новой ссылки
Создаем новую Вьюшку в index’e, которая будет обрабатывать запрос из формы на главной странице.
Сначала создадим новый, но очень похожий на первый (home.htm) шаблон — "newLink.htm".
Там мы будем выводить уже сокращенную ссылку и количество переходов по ней (чтобы снова увидеть эту "статистику" нужно снова сократить эту же ссылку — адрес останется тот же).
Для вывода воспользуемся трюком с "переходом переменных":
<?php //Файл: нет (пример) //устанавливаем переменную в index'е и рендерим шаблон $f3->set('link', $shorted_link); $view = new View; echo $view->render('newLink.htm'); //теперь в шаблоне можно использовать: <?= $link ?>
А вот и листинг newLink.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="/">Главная</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="/" 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 DB\SQL( //Подключение к БД новое в каждом Роуте '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 DB\SQL\Mapper($db,'links'); $check->load(array('link="'. $link .'"')); if ($check->dry()) { $g_code = generate_string($permitted_chars); $row = new DB\SQL\Mapper($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('/'); } } );
Готово! На самом деле, это было просто.
Перенаправление
Дело осталось за малым:
- Получить параметр из URL
- Проверить его наличие в БД
- Получить из БД соответствующую ссылку
- Перенаправить пользователя
- Profit!
Продолжаем писать код после прошлого Роута.
$f3->route('GET /@code', //указываем параметр после "@", он попадет в PARAMS function($f3) { //снова определяем $db $db = new DB\SQL( 'mysql:host=localhost;port=3306;dbname=linker', 'root', '' ); $code = $f3->get('PARAMS.code'); //получаем параметр $link = new DB\SQL\Mapper($db,'links'); //если получается получить ссылку из БД - получаем, увеличиваем количество переходов и перенаправляем if ($link->load(array('code="'.$code.'"', 'link=?'))) { $link->hits++; $link->save(); $f3->reroute($link->link); } else { $f3->reroute('/'); //а если такой ссылки нет - милости просим на главную } } );
Вы могли заметить, что в и в роуте newLink, и в роуте выше определятся одно и тоже — ведь code может совпасть с "newLink" (не может, в генераторе только буквы верхнего регистра), но так как сначала определен он, то он и выполнится первым.
$f3→run()!
Спасибо за прочтение!
Я буду рад, если Вы напишете комментарий, и поправите если что не так.
А в качестве домашнего задания или доказательства лени автора (меня), оставляю списочек, что можно сделать. Ведь лучше учиться на практике!
- Это конечно маловероятно, но при генерации $g_code может повториться, так что предлагаю вам написать функцию, которая будет это проверять.
- Еще можно сделать нормальную статистику и выводить ее по переходу на /@code/stats
- Запретить создавать ссылки на сам сервис сокращения ссылок, создать список "защищенных" от укорачивания ресурсов
-
Настоятельно рекомендую даже в таком маленьком деле делать валидацию ввода и на стороне сервера, с выводом соответствующих ошибок, не стоит полагаться на добавление аттрибута required и типа type=«url» к полю ввода
RedComrade -
Предлагайте в комментарии…
На связи)
ссылка на оригинал статьи https://habr.com/ru/post/515636/
Добавить комментарий