2

I have the following array with urls

$data = Array ( 'http://localhost/my_system/users',
        'http://localhost/my_system/users/add_user', 
        'http://localhost/my_system/users/groups',
        'http://localhost/my_system/users/add_group' );

Then I have a variable

$url = 'http://localhost/my_system/users/by_letter/s';

I need a function that will return the closest url from the array if $url does not exist. Something like

function get_closest_url($url,$data){

}



get_closest_url($url,$data); //returns 'http://localhost/my_system/users/'

$url2 = 'http://localhost/my_system/users/groups/ungrouped';

get_closest_url($url2,$data); //returns 'http://localhost/my_system/users/groups/'

$url3 = 'http://localhost/my_system/users/groups/add_group/x/y/z';

get_closest_url($url3,$data); //returns 'http://localhost/my_system/users/groups/add_group/'
Kevin R
  • 75
  • 8
  • 1
    check this .. https://stackoverflow.com/questions/14421303/php-nearest-string-comparison – スージン Oct 03 '17 at 01:03
  • 1
    Those are not strings. Where's your `;` at the end of each line? – StackSlave Oct 03 '17 at 01:25
  • can you please fix your code formatting? – rsm Oct 03 '17 at 01:32
  • What about urls like those: ```localhost/something``` and ```localhost/my_systems/no_users```. They are not presented in your list, so what function should return in those cases? – Rulisp Oct 03 '17 at 01:56
  • I suspect you need to use 'curl_*()' or something like 'file_get_contents() functions. Your urls can be rewritten by the web-server (apache/nginx/etc), and there is no way to detect without actual 'ping' the url... but it will be relatively long to check every inexistent path... imo – Wizard Oct 03 '17 at 03:01
  • @scarletwitch I tried that but if you have more urls there could be other close matches that are totally different urls. leventhstein checks for similar characters regardless of the sequence...what am looking for is the closest substring... – Kevin R Oct 04 '17 at 02:33
  • @PHPglue Sorry about the formatting, I have fixed it. This is my first post...still learning the ropes :) – Kevin R Oct 04 '17 at 02:39
  • @rsm Sorry about the formatting, I have fixed it. – Kevin R Oct 04 '17 at 02:39

2 Answers2

1

You can explode both the current URL and each of the URLs in $data, intersect the arrays, then return the array with the most elements (best match). If there's no matches, return false:

<?php
$data = [ "localhost/my_system/users",
        "localhost/my_system/users/add_user", 
        "localhost/my_system/users/by_letter/groups",
        "localhost/my_system/users/add_group"];
$url = "localhost/my_system/users/by_letter/s";
function getClosestURL($url, $data) {
    $matches = [];
    $explodedURL = explode("/", $url);
    foreach ($data as $match) {
        $explodedMatch = explode("/", $match);
        $matches[] = array_intersect($explodedMatch, $explodedURL);
    }
    $bestMatch = max($matches);
    return count($bestMatch) > 0 ? implode("/", $bestMatch) : false; // only return the path if there are matches, otherwise false
}

var_dump(getClosestURL($url, $data)); //returns localhost/my_system/users/by_letter
var_dump(getClosestURL("local/no/match", $data)); //returns false

Demo

You don't mention how you want to specifically check if the URL exists. If it needs to be "live", you can use get_headers() and check the first item for the HTTP status. If it's not 200, you can then go ahead with the URL intersection.

$headers = get_headers($url);
$httpStatus = substr($headers[0], 9, 3);
if ($httpStatus === "200") {
    return $url; // $url is OK
}
// else, keep going with the previous function
ishegg
  • 9,685
  • 3
  • 16
  • 31
0
function get_closest_url($item,$possibilities){
    $result = [];
    foreach($possibilities as $possibility){
        $lev = levenshtein($possibility, $item);
        if($lev === 0){
            #### we have got an exact match
            return $possibility;
        }
        #### if two possibilities have the same lev we return only one
        $result[$lev] = $possibility;
    }
    #### return the highest
    return $result[min(array_keys($result))];
}

That should do it.

  • Since levenshtein checks similaries in terms of characters it won't always return the correct url. For example if $url = 'http://localhost/my_system/users/profile'; The function will return 'http://localhost/my_system/users/groups' instead of 'http://localhost/my_system/users' – Kevin R Oct 04 '17 at 03:15