
No es vergonzoso acortar enlaces a los 13 años, ¿verdad? Tanto a un principiante como a cualquier persona le vendría bien intentar crear su propio Acortador de Enlaces mientras aprende algún nuevo framework. Eso es lo que he estado haciendo. ¿Qué puedo decir? Quinto Bootstrap, un framework ligero y un poco de alma.
Aquí , pero . Para lectores como yo 😉
Un framework, ¿no?
Por supuesto que no es Laravel ni cosas similares; hoy usaremos 65 kilobytes. . Si conoces Python Flask, tendrás la sensación de que esto ya ha existido en algún lugar:
#роутинг во Фласке
@app.route('/')
def hello_world():
return 'Hello, World!'
//роутинг в Обезжиренном
$f3->route('GET /',
function() {
echo 'Hello, world!';
}
);Está bien, olvida eso. Descarguemos , lo descomprimimos en la carpeta que se abrirá en tu Editor de Código Favorito. Limpia index.php y elimina todo de /ui.
Aquí todo es muy sencillo: en la carpeta ui tenemos todas las vistas, o en términos simples, plantillas HTML mejoradas que mostraremos al usuario cuando acceda a una URL determinada.
Esta es la estructura de nuestra "aplicación":
<?php
//Archivo: index.php
//Iniciar el framework
$f3=require('lib/base.php');
$f3->set('DEBUG', 1);
if ((float)PCRE_VERSION<8.0)
trigger_error('La versión de PCRE está desactualizada');
$f3->config('config.ini');
//TODO: AQUÍ ES DONDE ESCRIBIREMOS EL CÓDIGO RESTANTE
$f3->run();Y eso es todo lo que necesitas saber para empezar. ¡Vamos a programar!
[para desarrollo utilicé un servidor local en Windows y VS Code, ]
Página Principal
Comencemos con la página principal. Tiene sentido, ¿verdad?
//Файл: index.php
$f3->route('GET /',
function($f3) { //чтобы использовать функции F3 передаем его в роут
$view = new View; // создаем вьюшку
echo $view->render('home.htm'); //рендерим шаблон
}
);Ahora necesitamos escribir esa plantilla. Para simplificar, utilicé
No olvides crear todas las plantillas en la carpeta ui, de lo contrario, no serán visibles para el framework.
<!-- Файл: 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>Escribimos (código), acortamos (enlaces)!</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="#">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Artículo en Habré</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://nikonovs.ru">Creador</a>
</li>
</ul>
</nav>
<div class="container">
<h1>Los enlaces cortos ya están aquí.</h1>
<!-- Будем отправлять данные POST-запросом на /newLink -->
<form class="mt-5 mb-3" action="/es/newLink/" method="POST" data-trp-original-action="/newLink/">
<div class="row justify-content-center">
<div class="col-auto">
<label for="inputLink" class="col-form-label">Introduce el enlace:</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">¡Acortar!</button>
</div>
</div>
<input type="hidden" name="trp-form-language" value="es"/></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">Hecho con <img width="20" height="20" src="https://image.flaticon.com/icons/svg/833/833472.svg" alt="con amor">, <a href="https://v5.getbootstrap.com/">el quinto Bootstrap</a> y <a href="https://fatfreeframework.com/">sin grasa</a></footer>
</div>
</body>
</html>Y eso es todo, ya tenemos nuestra página principal funcionando. El formulario envía un enlace que necesita ser acortado mediante una solicitud POST.
Ahora viene lo más interesante (no).
Trabajo con la base de datos
Crearemos la base de datos — MySQL. Si tienes PhpMyAdmin instalado, crea una nueva base de datos "linker", y luego ejecuta este 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`);Tendremos 3 campos para cada enlace:
- Code — son 4 caracteres aleatorios después del dominio, que se usarán para el redireccionamiento, en el formato example.com/ABC1
- Link — El enlace original. Hits — el número de accesos al enlace acortado.
- Te contaré brevemente cómo funciona con la base de datos, sin rodeos.
Brevemente explicaré el principio de trabajo con bases de datos, sin rodeos.
set('result', $db->exec('SELECT * FROM wherever'));
// estarán disponibles en las plantillas como
// O se puede usar el SQL Mapper incorporado:
$row = new DBSQLMapper($db, 'links');
$row->load(array('link="https://habrahabr.ru"')); // ahora desde este objeto se tienen disponibles todas las columnas de la fila donde la link apunta a Habr:
$row_value = $row->somerow; // Así
// Por supuesto, se pueden cambiar los valores:
$row->link = 'https://habr.com';
$row->save(); // hay que guardar los cambios, ¿qué pensabas?
// más información sobre cómo trabajar con la base de datos está disponible aquí: https://a.nikonovs.ru/MPHR Recomiendo encarecidamente leerlo, al menos con la ayuda de un traductor incorporado en el navegador.
?>Comenzamos a acortar.
Procesando nuevo enlace
Creando nueva vista en index, que procesará la solicitud del formulario en la página principal.
Primero crearemos una nueva plantilla, pero muy parecida a la primera (home.htm) — "newLink.htm".
Ahí mostraremos el enlace acortado y la cantidad de clics en él (para volver a ver esta "estadística" es necesario acortar de nuevo el mismo enlace — la dirección seguirá siendo la misma).
Usaremos un truco con "pase de variables":
set('link', $shorted_link);
$view = new View;
echo $view->render('newLink.htm');
// ahora en la plantilla se puede usar:Aquí está el listado 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>Escribimos (código), acortamos (enlaces)!</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="/es/">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Artículo en Habré</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://nikonovs.ru">Creador</a>
</li>
</ul>
</nav>
<div class="container">
<h1>Los enlaces cortos ya están aquí.</h1>
<!-- Убираем из формы функционал формы и выводим переменные -->
<form class="mt-5 mb-3" action="">
<div class="row justify-content-center">
<div class="col-auto">
<label for="inputLink" class="col-form-label">Reducido:</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">Han hecho clic en este enlace: ``</p>
<input type="hidden" name="trp-form-language" value="es"/></form>
<a href="/es/" class="mt-3 mb-5 btn btn-primary btn-lg">VOLVER A LA PÁGINA PRINCIPAL</a>
<footer class="m-2">Hecho con <img width="20" height="20" src="https://image.flaticon.com/icons/svg/833/833472.svg" alt="con amor">, <a href="https://v5.getbootstrap.com/">el quinto Bootstrap</a> y <a href="https://fatfreeframework.com/">sin grasa</a></footer>
</div>
</body>
</html>Escribimos la ruta.
$f3->route('GET|POST /newLink', //vamos a procesar tanto POST como GET
function($f3) {
$db = new DBSQL( //Conexión a la base de datos nueva en cada ruta
'mysql:host=localhost;port=3306;dbname=linker',
'root',
''
);
//una maravillosa función para generar caracteres aleatorios:
$permitted_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
function generate_string($input, $strength = 4) {
$input_length = strlen($input);
$random_string = '';
for($i = 0; $i 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; //si el link se repite, mostramos el código antiguo
}
$short_link = 'https://'. $_SERVER['HTTP_HOST'] . '/' . $g_code; //construimos el link final
//los parámetros de $_POST se pueden obtener usando $f3->get('POST'), se soporta la notación de punto (corríjanme si lo llamo incorrectamente): se puede obtener el parámetro "link" así:
$link = $f3->get('POST.link');
if ( !empty($f3->get('POST')) ) { //Emitimos HTML sólo si el POST no está vacío.
$f3->set('link', $short_link);
$f3->set('hits', $check->hits);
$view = new View;
echo $view->render('newLink.htm');
} else { //de lo contrario - redirigir a la principal
$f3->$f3->reroute('/');
}
}
);¡Listo! En realidad, fue fácil.
Redirección
Solo queda lo siguiente:
- Obtener el parámetro de la URL
- Verificar su existencia en la base de datos
- Obtener el link correspondiente de la base de datos
- Redirigir al usuario
- ¡Beneficio!
Continuamos escribiendo código después de la última ruta.
$f3->route('GET \/@code', \/\/especificamos el parámetro después de "@", se almacenará en PARAMS
function($f3) {
\/\/definimos nuevamente $db
$db = new DBSQL(
'mysql:host=localhost;port=3306;dbname=linker',
'root',
''
);
$code = $f3->get('PARAMS.code'); \/\/obtenemos el parámetro
$link = new DBSQLMapper($db,'links');
\/\/si puede obtener el enlace de la base de datos - lo obtenemos, incrementamos el número de visitas y redirigimos
if ($link->load(array('code="'.$code.'"', 'link=?'))) {
$link->hits++;
$link->save();
$f3->reroute($link->link);
} else {
$f3->reroute('\/'); \/\/si no hay tal enlace - lo invitamos a la página principal
}
}
);Podría haber notado que en y en la ruta newLink, y en la ruta anterior se definirá lo mismo — pues puede coincidir con "newLink" (no puede, en el generador solo hay letras mayúsculas), pero dado que primero se define él, se ejecutará primero.
$f3→run()!
¡Gracias por leer!
Estaré encantado si escribe un comentario y corrige cualquier cosa que esté mal.
Y como tarea o prueba de la pereza del autor (mía), dejo una lista de lo que se puede hacer. ¡Es mejor aprender en la práctica!
- Esto es, por supuesto, poco probable, pero al generar $g_code puede repetirse, así que le propongo escribir una función que lo verifique.
- También se puede hacer una estadística adecuada y mostrarla por cada clic en /@code/stats
- Prohibir la creación de enlaces al propio servicio de acortamiento de enlaces, crear una lista de "recursos" protegidos de ser acortados
Recomiendo encarecidamente, incluso en un asunto tan pequeño, hacer la validación de entrada también del lado del servidor, con la visualización de errores correspondientes, no hay que confiar solo en agregar el atributo required y el tipo type="url" al campo de entrada
Sugiéralo en los comentarios…
Saludos)
Fuente: habr.com
