> Faqs > Cambiar URLs en texto plano a links HTML, mediante PHP

Cambiar URLs en texto plano a links HTML, mediante PHP

Espero me podais ayudar a entender como hacer esto:

Por ejemplo, si se pone un enlace como por ejemplo https://ejemplo.es en un textarea en un formulairo, ¿Cómo hago para que PHP detecte que es un enlace http: // y se pueda clicar?

Gracias de antemano

Respuestas

Por el texto de tu pregunta no me queda claro si deseas que la URL se pueda hacer clic al estar como texto dentro de un campo textarea. Este caso no podrías, ya que en un textarea solo se puede escribir y ver texto plano.

Pero lo que imagino que quieres es que, al cargar una cadena de texto que has escrito en un textarea y volcarla como contenido de una página, en HTML, que cualquier URL se vea como si fuera un enlace, cambiando tal URL en texto a una etiqueta <a> de enlace con su href.

Eso se puede hacer simplemente transformando la cadena que has cargado con el textarea. Haciendo un reemplazo de la cadena, en búsqueda de todas las URL, para colocar la etiqueta <a href="URL_ENCONTRADA"> completa.

En Internet encontramos varias soluciones a este tema. Puedes consultar esta de Stack Overflow, aunque me parece todavía más completa esta función publicada por un usuario en GitHub.

Por si retiran más adelante ese código de GitHub, copio y pego la solución aquí.

Los parámetros son:

  • $value: la cadena original
  • $protocols: los protocolos que tiene que buscar, en un array, por ejemplo ('http', 'mail'). Por el código que tiene la función, si colocas http te vale tanto para http como https.
  • $attributes: un array asociativo, con el nombre del atributo y el valor del atributo que se desea poner al enlace
public function linkify($value, $protocols = array('http', 'mail'), array $attributes = array())
{
    // Link attributes
    $attr = '';
    foreach ($attributes as $key => $val) {
        $attr .= ' ' . $key . '="' . htmlentities($val) . '"';
    }
    
    $links = array();
    
    // Extract existing links and tags
    $value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
    
    // Extract text links for each protocol
    foreach ((array)$protocols as $protocol) {
        switch ($protocol) {
            case 'http':
            case 'https':   $value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, "<a $attr href=\"$protocol://$link\">$link</a>") . '>'; }, $value); break;
            case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
            case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\">{$match[0]}</a>") . '>'; }, $value); break;
            default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
        }
    }
    
    // Insert all link
    return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}
Alfonso
289 11 19 16