There is only one half-way reliable way to do this I think and you'll need to create a class for it; personally I use something like namespace\Domain extends namespace\URI sort of thing - a Domain, essentially being a subset of a URI - technically I create 2 classes.
Your domain will probably need a static class member to hold the list of valid TLDs and this may as well exist in the URI class as you may want to reuse it with other sub-classes.
namespace My;
class URI {
protected static $tldList;
private static $_tldRepository = 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1';
protected $uri;
public function __construct($sURI = "") {
if(!self::$tldList) {
//static method to load the TLD list from Mozilla
// and parse it into an array, which sets self::$tldList
self::loadTLDList();
}
//if the URI has been passed in - set it
if($sURI) $this->setURI($sURI);
}
public function setURI($sURI) {
$this->uri = $sURI; //needs validation and sanity checks of course
}
public function getURI() {
return $this->uri;
}
//other methods ...
}
In reality I actually make a copy of the TLD list to a file on the server and use that, and only update it every 6 months to avoid the overhead of reading in the full TLD list when you first create a URI object on any page.
Now you may have a Domain sub-class that extends \My\URI and allows you to break the URI down into component parts - there might be a method to remove the TLD (based on the TLD list you've loaded into parent::$tldList from mxr.mozilla.org) once you've taken out the valid TLD whatever is just to the left of it (between the last . and the TLD) should be the domain, anything left of that would be sub-domains.
You can have methods to extract that data as required as well.
www.mail.google.com? What should the output be in that case?parse_url, have you tried removing thewww.and.com? It is just a few string operations; use the documentation, do not be afraid to make mistakes, and you will figure it out quickly.