Reputation: 49
I have a list of domains (array)
sub1.dom1.tld1
sub2.dom2.tld2
sub1.sub2.dom1.tld1
sub3.dom1.tld3
I want to achieve the following:
dom1.tld1
-> sub1.dom1.tld1
-> sub2.dom1.tld1
--> sub1.sub2.dom1.tld1
dom2.tld2
-> sub2.dom2.tld2
dom1.tld3
-> sub3.dom1.tld3
I have tried to adapt this, but it doesn't really fit:
How to alphabetically sort a php array after a certain character in a string
I would appreciate any kind of help.
Upvotes: 1
Views: 277
Reputation: 498
i'm not sure if this is a late answer, but here it how i achieved it
First i have function to get the host name from subdomain
function getHost($a)
{
$tld = preg_replace('/.*\.([a-zA-Z]+)$/', '$1', $a);
return trim(preg_replace('/.*(([\.\/][a-zA-Z]{2,}){' . ((substr_count($a, '.') <= 2 && mb_strlen($tld) != 2) ? '2,3' : '3,4') . '})/im', '$1', $a), './');
}
Next you need to loop through the subdomains and get their main domain and store it in array
$domains = [
'sub.bbb.com',
'www.aaa.com',
'*.zzz.com',
'aaa.com',
'*.sub.bbb.com',
'zzz.com',
'beta.bbb.com',
'bbb.com',
'aaa.fr',
];
$allMainDomains = array();
foreach ($domains as $domainValue) {
if (!in_array(getHost($domainValue), $allMainDomains)) {
array_push($allMainDomains, getHost($domainValue));
}
}
What we did is, we store all main domains in an array $allMainDomains
and verified not duplicates by using in_array
function
Next we can loop through the $allMainDomains
and $domains
like so
foreach ($allMainDomains as $mainDomain) {
echo '<br>' . $mainDomain . '<br>';
foreach ($domains as $subDomain) {
if (getHost($subDomain) == $mainDomain) {
echo '<br>' . $subDomain . '<br>';
}
}
echo '<hr />';
}
Note: The only thing you might need to modify is the getHost function because it skips the multiple dots (.) domains
Result
Upvotes: 0
Reputation: 3863
Here is an approach similar to @Elementary answer combine to @CBO one:
$domains = [
'sub.bbb.com',
'www.aaa.com',
'*.zzz.com',
'aaa.com',
'*.sub.bbb.com',
'zzz.com',
'beta.bbb.com',
'bbb.com',
'aaa.fr',
];
// @see https://stackoverflow.com/a/61461912/1731473
$computeDomainToSort = static function (string $domain): string {
return \implode(
'.',
array_reverse(
explode('.', $domain,
// Keep the base domain.tld collapsed for comparison.
substr_count($domain, '.')
)
)
);
};
\usort($this->domains, static function (string $domain1, string $domain2) use ($computeDomainToSort): int {
$domain1 = $computeDomainToSort($domain1);
$domain2 = $computeDomainToSort($domain2);
return strnatcmp($domain1, $domain2);
});
That way, given domains will be sorted like this:
aaa.com
www.aaa.com
aaa.fr
bbb.com
beta.bbb.com
sub.bbb.com
*.sub.bbb.com
zzz.com
*.zzz.com
The main difference is on the $computeDomainToSort
lambda function, where I keep the base domain.tld
onto one piece to have a more natural sorting.
Upvotes: 0
Reputation: 1453
You can proceed like this:
$array=array(
'sub1.dom1.tld1',
'sub2.dom2.tld2',
'sub1.sub2.dom1.tld1',
'sub2.sub2.dom1.tld1',
'sub3.sub2.dom1.tld1',
'sub3.dom1.tld3');
function cmp($a,$b){
$a=array_reverse(explode('.',$a));
$b=array_reverse(explode('.',$b));
$ca=count($a);
$cb=count($b);
$string='';;
for($i=0,$c=min($ca,$cb);$i<$c;$i++){
$result=strnatcmp($a[$i],$b[$i]);
if($result!==0) return $result;
}
return $result;
}
usort($array,'cmp');
print_r($array);
and the output is:
Array
(
[0] => sub1.dom1.tld1
[1] => sub1.sub2.dom1.tld1
[2] => sub2.sub2.dom1.tld1
[3] => sub3.sub2.dom1.tld1
[4] => sub2.dom2.tld2
[5] => sub3.dom1.tld3
)
Upvotes: 0
Reputation: 181
I've had to attack a similar headache before. In the short term I flip the order of the domain components and use a hidden sorting column in a table/view:
$sortstring = implode('.',array_reverse(explode('.', $domain)));
In the long term I saved the reverse format of the domain records before saving changes to the DB into a computed field/column so that it didn't have to be re-computed every time the domain list is viewed.
If you don't want that sub-domain, just remove the last element of the array after the flip....
Upvotes: 1