1

I'm writing a simple function which will convert string containing url into a clickable link. Convertion itself is simple but part of basic validation if a string contains one of protocol prefixes seems to be surprisingly difficult.

Currently my code looks like this:

<?php

function link2code($link) {
    if (stripos($link, 'http://' or 'https://' or 'ftp://' or 'ftps://') === true) {
        return "<a href=\"$link\">$link</a>";
    } else {
        echo('Please provide whole link with protocol part, for example: http://myawesomewebsite.com');
    }
}

echo link2code("http://127.0.0.1");

As you can see i want to return boolean value telling if needle is in haystack. How can i achieve it?

spectatorx
  • 373
  • 2
  • 7
  • 22
  • I don't think you can use `or` like that. And I usually use `!== False` https://3v4l.org/ikEYT – Andreas Jul 15 '17 at 19:46
  • Possible duplicate of [Using an array as needles in strpos](https://stackoverflow.com/questions/6284553/using-an-array-as-needles-in-strpos) – Sean Jul 15 '17 at 19:46

7 Answers7

4

You can use preg_match for that:

if(preg_match("~^(ht|f)tps?://~i", $link)) { //...etc
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Isn't that a bit heavy function for such a small task? – Andreas Jul 15 '17 at 19:48
  • 1
    Not in my opinion. It is a simple pattern, so the regex-based matching will not be that heavy. Note how the OP code (and some answers) do not verify that the match is at the very start of the string. – trincot Jul 15 '17 at 19:50
  • I find this method to be the most elegant and satisfying as i wanted to avoid using arrays. Regular expressions are powerful tools. Thank you for help, now code works the way i wanted. P.S. I'm impressed with number and variety of answers to this thread. I want to thank all other people here for their suggestions as well. – spectatorx Jul 15 '17 at 22:47
  • @spectatorx yes regex is powerful. Too powerful for this task. The regex answers in this thread performs about 50% slower than the non regex (not all). Just out of curiosity, what is your "issue" with arrays? – Andreas Jul 16 '17 at 04:52
  • Nothing against arrays, i just think in this situation they are not necessary but this is just personal and very situational preference. – spectatorx Jul 16 '17 at 09:05
  • @spectatorx is guess we are different then. This is in my opinion a perfect example to use array. Bunched up the strings to one variable that you can pass to functions. I don't know if you can measure performance on "loose" strings but arrays are slightly more efficient than variables https://stackoverflow.com/questions/14337685/php-many-variables-or-one-array/14338038#14338038 . On a side note I'm noticed there was even more difference than it earlier wrote on some occasions between regex and non regex. Some was 0.006 compared to 0.033 if it's remember correct from last night's tests – Andreas Jul 16 '17 at 12:36
3

checkout this code :

class Test
{

     public function index()
     {
         $link = "http://127.0.0.1";
         $this->checkLink("http://127.0.0.1");        //Yes
         $this->checkLink("hsttp://127.0.0.1");        //No
     }

     private function checkLink($link)
     {
         if (stripos($link, 'http://') !== false
             || stripos($link, 'http://') !== false
             || stripos($link, 'ftp://') !== false
             || stripos($link, 'ftps://') !== false)
         {
             echo 'Yes';
         }
         else
         {
             echo 'No';
         }
      }

}
Ali Faris
  • 17,754
  • 10
  • 45
  • 70
1

You can it iterate by defining a custom function and find the if match found create a link.

function strPosition($haystack, $needle, $offset=0) {
  if (!is_array($needle)) $needle = array($needle);
    foreach ($needle as $query) {
      if (strpos($haystack, $query, $offset) !== false) return true; // stop on first true result
    }
    return false;
}

function link2code($link) {
  $array = array('http://', 'https://', 'ftp://', 'ftps://');

  $match = strPosition($link, $array);
  if ($match == true) {
    return "<a href=\"$link\">$link</a>";
  } else {
    echo('Please provide whole link with protocol part, for example: http://myawesomewebsite.com');
  } 
}
Muhammad Usman
  • 1,403
  • 13
  • 24
1

It can be done using a regex. Although using multiple times stripos() would work as well. The line will be longer than, but it could be cheaper.

for readability, I prefer regex

<?php

function link2code($link) {
    if (preg_match('#^(https?|ftps?)://#i', $link)) {
        return "<a href=\"$link\">$link</a>";
    } else {
        echo('Please provide whole link with protocol part, for example: http://myawesomewebsite.com');
    }
}

echo link2code("http://127.0.0.1");
Ivo P
  • 1,722
  • 1
  • 7
  • 18
1

You could try rephrasing the question:

Instead of checking if one the protocols in in the link, try checking if the protocol in the link is one of the protocols:

function link2code($link) {

    $scheme = parse_url($link, PHP_URL_SCHEME);
    if(!in_array($scheme,['http','https','ftp','ftps']) {
        return "<a href=\"$link\">$link</a>";
    } else { 
        echo ()
    }
}

Outside of the scope of your question:

Your function does different things:

  • it validates the url
  • it returns string or it returns void
  • in some cases it echoes.

You could try to separate the validation from the formatting and making sure your functions always return a string, or throw an exception.

function link2code($link) {
    if(validateLink($link)) {
        return "<a href=\"$link\">$link</a>";
    } else {
        throw new \Exception("Please provide whole link with protocol part, for example: http://myawesomewebsite.com'");
    }
}

function validateLink($link) {
    $scheme = parse_url($link, PHP_URL_SCHEME);
    return in_array($scheme,['http','https','ftp','ftps']);
}
Maarten van Middelaar
  • 1,691
  • 10
  • 15
0

You can use in_array().
http://php.net/manual/en/function.in-array.php

function link2code($link) {
    $arr = array('http:/', 'https:', 'ftp://', 'ftps:/');
    If(in_array(substr($link,0,6), $arr)){
        return "<a href=\"$link\">$link</a>";
    } else {
         echo('Please provide whole link with protocol part, for example: http://myawesomewebsite.com');
    }
}

echo link2code("https://127.0.0.1");

https://3v4l.org/meI1r
The array contains the minimum common number of characters (6) so that I can compare against the same in the function.
So the substr will look at the six first chars if they don't match with array it's not a only link string.

Meaning the string click here https://127.0.0.1 will fail

Of course if you don't need to validate that it is a link only string you can remove the substr from the code and add "full" items in the array.

Andreas
  • 23,610
  • 6
  • 30
  • 62
0

Try with regular expressions and preg_match

function link2code($link) {
    if ( ! preg_match('/^(http(s)?|ftp(s)?):\/\//i', $link)) {
        echo 'Please provide whole link with protocol part, for example: http://myawesomewebsite.com';
        return FALSE;
    }
    return sprintf('<a href="%1$s">%1$s</a>', $link);
}

echo link2code("http://127.0.0.1");
echo link2code("https://127.0.0.1");
kip
  • 1,120
  • 7
  • 11