Gerardo, parte de este gran staff, nos hizo el favor de redactar este escrito ya que conoce muy bien dicho tema.
Solución:
Bueno, puedes usar parse_url
para conseguir el anfitrión:
$info = parse_url($url);
$host = $info['host'];
Luego, puede hacer algunas cosas elegantes para obtener solo el TLD y el Host
$host_names = explode(".", $host);
$bottom_host_name = $host_names[count($host_names)-2] . "." . $host_names[count($host_names)-1];
No es muy elegante, pero debería funcionar.
Si quieres una explicación, aquí va:
Primero tomamos todo entre el esquema (http://
, etc.), usando parse_url
capacidades de … bueno … analizar URL. 🙂
Luego tomamos el nombre de host y lo separamos en un array basado en donde caen los periodos, entonces test.world.hello.myname
se convertiría:
array("test", "world", "hello", "myname");
Después de eso, tomamos el número de elementos en el array (4).
Luego, le restamos 2 para obtener el penúltimo string (el nombre de host, o example
, en tu ejemplo)
Luego, le restamos 1 para obtener el último string (porque array keys empezar en 0), también conocido como TLD
Luego combinamos esas dos partes con un punto, y tienes tu nombre de host base.
No es posible obtener el nombre de dominio sin usar una lista de TLD para comparar, ya que existen muchos casos con completamente la misma estructura y longitud:
- www.db.de (subdominio) versus bbc.co.uk (dominio)
- big.uk.com (SLD) frente a www.uk.com (TLD)
La lista de sufijos públicos de Mozilla debería ser la mejor opción, ya que la utilizan todos los navegadores principales:
https://publicsuffix.org/list/public_suffix_list.dat
Siéntete libre de usar mi función:
function tld_list($cache_dir=null)
// we use "/tmp" if $cache_dir is not set
$cache_dir = isset($cache_dir) ? $cache_dir : sys_get_temp_dir();
$lock_dir = $cache_dir . '/public_suffix_list_lock/';
$list_dir = $cache_dir . '/public_suffix_list/';
// refresh list all 30 days
if (file_exists($list_dir) && @filemtime($list_dir) + 2592000 > time())
return $list_dir;
// use exclusive lock to avoid race conditions
if (!file_exists($lock_dir) && @mkdir($lock_dir))
// read from source
$list = @fopen('https://publicsuffix.org/list/public_suffix_list.dat', 'r');
if ($list)
// the list is older than 30 days so delete everything first
if (file_exists($list_dir))
foreach (glob($list_dir . '*') as $filename)
unlink($filename);
rmdir($list_dir);
// now set list directory with new timestamp
mkdir($list_dir);
// read line-by-line to avoid high memory usage
while ($line = fgets($list))
fclose($list);
@rmdir($lock_dir);
// repair locks (should never happen)
if (file_exists($lock_dir) && mt_rand(0, 100) == 0 && @filemtime($lock_dir) + 86400 < time())
@rmdir($lock_dir);
return $list_dir;
function get_domain($url=null)
Lo que hace especial:
- acepta todas las entradas como URL, nombres de host o dominios con o sin esquema
- la lista se descarga fila por fila para evitar un uso elevado de memoria
- crea un nuevo archivo por TLD en una carpeta de caché, por lo que
get_domain()
solo necesita revisarfile_exists()
si existe, no necesita incluir una base de datos enorme en cada solicitud como lo hace TLDExtract. - la lista se actualizará automáticamente cada 30 días
Prueba:
$urls = array(
'http://www.example.com',// example.com
'http://subdomain.example.com',// example.com
'http://www.example.uk.com',// example.uk.com
'http://www.example.co.uk',// example.co.uk
'http://www.example.com.ac',// example.com.ac
'http://example.com.ac',// example.com.ac
'http://www.example.accident-prevention.aero',// example.accident-prevention.aero
'http://www.example.sub.ar',// sub.ar
'http://www.congresodelalengua3.ar',// congresodelalengua3.ar
'http://congresodelalengua3.ar',// congresodelalengua3.ar
'http://www.example.pvt.k12.ma.us',// example.pvt.k12.ma.us
'http://www.example.lib.wy.us',// example.lib.wy.us
'com',// empty
'.com',// empty
'http://big.uk.com',// big.uk.com
'uk.com',// empty
'www.uk.com',// www.uk.com
'.uk.com',// empty
'stackoverflow.com',// stackoverflow.com
'.foobarfoo',// empty
'',// empty
false,// empty
' ',// empty
1,// empty
'a',// empty
);
Versión reciente con explicaciones (alemán):
http://www.programmierer-forum.de/domainnamen-ermitteln-t244185.htm
Mi solución en https://gist.github.com/pocesar/5366899
y las pruebas están aquí http://codepad.viper-7.com/GAh1tP
Funciona con cualquier TLD y patrones de subdominio horribles (hasta 3 subdominios).
Hay una prueba incluida con muchos nombres de dominio.
No pegaré la función aquí debido a la extraña sangría para el código en StackOverflow (podría tener bloques de código cercados como github)
Reseñas y valoraciones
Recuerda que puedes dar recomendación a este post si si solucionó tu problema.