694

I'm trying to check if a string starts with http. How can I do this check?

$string1 = 'google.com';
$string2 = 'http://www.google.com';
Mridang Agarwalla
  • 43,201
  • 71
  • 221
  • 382
Andrew
  • 227,796
  • 193
  • 515
  • 708
  • 3
    Since it's such a widely used framework, it's worth mentioning that if you're using Laravel, you have the `starts_with` and `ends_with` helper functions available to you. – alexw Mar 28 '18 at 00:49
  • We can remove some comments from here since are answers, added as comments - also somehow already mentioned in the already existing answers. – Valerio Bozz Jul 06 '23 at 07:42

5 Answers5

1231

PHP 8 or newer:

Use the str_starts_with function:

str_starts_with('http://www.google.com', 'http')

PHP 7 or older:

Use the substr function to return a part of a string.

substr( $string_n, 0, 4 ) === "http"

If you're trying to make sure it's not another protocol. I'd use http:// instead, since https would also match, and other things such as http-protocol.com.

substr( $string_n, 0, 7 ) === "http://"

And in general:

substr($string, 0, strlen($query)) === $query
Pikamander2
  • 7,332
  • 3
  • 48
  • 69
Kendall Hopkins
  • 43,213
  • 17
  • 66
  • 89
  • 117
    There is no need to hardcodede string length as said below if your needle is a variable. Just use substr( $string, 0, strlen($query) ) === $query. – webrama.pl Jan 16 '14 at 11:58
  • 21
    Be careful when using multibyte utf8 strings! mb_substr is your friend – CoR May 08 '15 at 19:19
  • 3
    You are not required to use `mb_*` functions when you use `substr($string, 0, strlen($query)) === $query` – Finesse Jan 16 '18 at 02:11
  • 1
    strpos solution from awgy uses fewer resources.. – richp10 Jan 19 '18 at 10:41
  • strpos version is better since you don't need sto store off the string you're checking or duplicate the code that accesses it. – Charlie Apr 15 '18 at 05:16
  • @CoR And therefore, `mb_strlen` is also your friend! – rybo111 Jun 29 '19 at 14:26
  • `0, 3` Checks the first 4 characters, if I am correct. So, this will make sure that the test doesn't get a `true` return just because it had `http` somewhere in the domain. – Jesse Feb 03 '20 at 03:44
  • Should the first line of this answer be `0, 3`, not `0, 4`? – Jesse Feb 03 '20 at 03:44
  • 2
    @JesseSteele it's position, length and not start position, end position – Temani Afif May 06 '20 at 13:33
  • 3
    Per the [str_starts_with RFC](https://wiki.php.net/rfc/add_str_starts_with_and_ends_with_functions), the most CPU and memory efficient way to generically check if a string starts with another string prior to PHP 8 is `strncmp($haystack, $needle, strlen($needle)) === 0`. – Evan Byrne Jun 07 '21 at 16:19
815

Use strpos():

if (strpos($string2, 'http') === 0) {
   // It starts with 'http'
}

Remember the three equals signs (===). It will not work properly if you only use two. This is because strpos() will return false if the needle cannot be found in the haystack.

CodeZombie
  • 5,367
  • 3
  • 30
  • 37
awgy
  • 16,596
  • 4
  • 25
  • 18
  • 39
    It’s not necessary to search the whole string (`strpos` stops if the needle is found or the end is reached) if you just need to look at a specific position. – Gumbo May 07 '10 at 18:48
  • Which is trivial for short strings, but I'll upvote your substr() suggestion. – awgy May 07 '10 at 19:10
  • 9
    please use substr instead, as strpos searches the entire haystack for the needle, while substr just checks the beginning (which is most faster for long strings) – nonchip Apr 15 '13 at 08:33
  • As Gumbo says, there is no performance advantage to substr. Use strpos() because it does not require you to hardcode a string length as a parameter, reducing errors. – doublemarked Aug 21 '13 at 16:39
  • 22
    @doublemarked No, there *is* a performance advantage to `substr`, which was Gumbo's point. Sure, if the needle is found at the start of the string, `strpos` will return early, but if it's *not* found, it will needlessly search the entire string. There's a tradeoff here; `strpos` reduces the chance of an error-causing typo, but `substr` theoretically ought to perform better, and I guess that could conceivably matter if your haystack was some enormous string, like the text of a novel. I always use `strpos` for the reason you gave, but I've upvoted both answers; `substr` might have its place. – Mark Amery Nov 01 '13 at 10:32
  • 2
    I am sorry to resurrect the old thread, just wanted to say that this is so far the cleanest and most elegant solution to my point of view. – Vladimir Hraban Jan 29 '14 at 11:54
  • 14
    This is a minor quibble, but the backwards comparison style is anti-intuitive. I'd recommend editing the answer to use the regular comparison order. (There used to be a trivial reason some programmers did that for a period of time, but it's not necessary.) It's more readable and intuitive as "if (strpos($string2, 'http') === 0) ... – orrd Aug 20 '14 at 04:13
  • 2
    substr() generates garbage, whereas strpos() does not. Unless your string is VERY LONG, the integer return of strpos() beats the generated garbage of substr() for performance. – Jon Watte Apr 18 '16 at 04:53
  • 7
    @orrd Hmmm... yeeeees, a yoda condition; unnecessary, it is. hrrrrm, Use it, you should not. – Armstrongest Nov 03 '17 at 16:08
  • Best solution for now – Loenix Mar 26 '19 at 14:52
  • Would substr not perform worse because it creates a copy of the string, which is a memory allocation? – himself Nov 05 '19 at 08:56
  • To your micro-performance concerns about `substr` searching the entire string - just add an explicit offset: `strpos($string2, 'http', 0) === 0`, then it'll search from the start of the string only. – mindplay.dk Apr 07 '20 at 13:26
  • @mindplay.dk 0 is the default, and is only start position, not end. – NiKiZe Jun 30 '20 at 15:05
  • Although not applicable to a function return, when comparing variables to values - backwards comparisons do offer one great advantage. It's impossible to make an accidental variable assignment when writing them backwards. If missing an equals sign, $a = 0 is an assignment 0 = $a is not. I always argued against them until it was presented to me in this way. – Michael Jul 30 '21 at 15:36
135

There is also the strncmp() function and strncasecmp() function which is perfect for this situation:

if (strncmp($string_n, "http", 4) === 0)

In general:

if (strncmp($string_n, $prefix, strlen($prefix)) === 0)

The advantage over the substr() approach is that strncmp() just does what needs to be done, without creating a temporary string.

dave
  • 2,762
  • 1
  • 16
  • 32
Sid
  • 2,136
  • 1
  • 11
  • 10
  • 9
    strncmp() is good because it doesn't generate garbage, like substr() does. It's also better than strpos() because it doesn't need to scan the entire string. It's less convenient in that you have to actually hard-code or calculate the length of the prefix, and if you get this wrong/change it later, the function may stop working. – Jon Watte Apr 18 '16 at 04:55
  • 4
    Wow there are lots of answers out there to this simple problem. I've chosen yours as the best: simply return strncmp($url, 'http', 4) === 0. Lots of string functions to chose from in the manual, but this is the obvious fit for the problem and I'd hazard a guess it's the best performing. – Andy H Oct 04 '16 at 11:36
  • This is really nice answer, and is really exactly does what is asked is to compare start of strings, not find, compare. Don't know why this isn't selected answer or have so few upvotes. – Abdul Rehman Nov 13 '19 at 07:47
  • this should definitely be the fastest way – hanshenrik Sep 01 '20 at 07:12
48

You can use a simple regex (updated version from user viriathus as eregi is deprecated)

if (preg_match('#^http#', $url) === 1) {
    // Starts with http (case sensitive).
}

or if you want a case insensitive search

if (preg_match('#^http#i', $url) === 1) {
    // Starts with http (case insensitive).
}

Regexes allow to perform more complex tasks

if (preg_match('#^https?://#i', $url) === 1) {
    // Starts with http:// or https:// (case insensitive).
}

Performance wise, you don't need to create a new string (unlike with substr) nor parse the whole string if it doesn't start with what you want. You will have a performance penalty though the 1st time you use the regex (you need to create/compile it).

This extension maintains a global per-thread cache of compiled regular expressions (up to 4096). http://www.php.net/manual/en/intro.pcre.php

user276648
  • 6,018
  • 6
  • 60
  • 86
  • 3
    regex is much more complex, then a strpos or substr operation, so it costs more performance and in this task it is definetly not needed –  Jun 08 '16 at 11:39
  • 2
    @Sharpy35: maybe, but I don't think of performance cost unless I've detected that it is making the system too slow. Avoid premature optimizations. Also regex is so much more powerful, it's really something developers should know. – user276648 Jun 09 '16 at 01:30
  • 1
    i didnt said that i dont know regex ;) i am just avoiding to use it whenever i can :) –  Jun 09 '16 at 08:33
  • I think it's unfair to discuss "Performance wise" when this is the least performant method – jaggedsoft Dec 11 '16 at 19:06
  • Main problem with a regex in that case is probably going to be that it is quite error-prone (need to appropriately escape characters f.i.) – Eric Grange Jun 15 '17 at 11:47
  • This is definitly better way to handle: the scope is to see if a string start with "http". This is related with parse_url function that cannot handle some particular case. The regex is the correct way to create your own function – Max Cuttins Nov 06 '17 at 14:46
  • @Berkant Haha, I totally agree and I usually try to avoid RegEx(p)s whenever I can, but **sadly**, this seems to be the **most elegant and readable solution :(** And code maintability turned out to be a big treasure. – jave.web Jul 22 '19 at 22:58
  • 1
    To my surprise (at least on PHP 7.3.6), this actually seems to be faster than strpos! (and it is only a little bit slower than substr) – jave.web Jul 22 '19 at 23:16
15

You can check if your string starts with http or https using the small function below.

function has_prefix($string, $prefix) {
   return substr($string, 0, strlen($prefix)) == $prefix;
}

$url   = 'http://www.google.com';
echo 'the url ' . (has_prefix($url, 'http://')  ? 'does' : 'does not') . ' start with http://';
echo 'the url ' . (has_prefix($url, 'https://') ? 'does' : 'does not') . ' start with https://';
Salim
  • 2,446
  • 1
  • 14
  • 12
TURTLE
  • 3,728
  • 4
  • 49
  • 50
  • 2
    If anyone reads answer this then the ternaries `? true : false` are redundant and can be removed completely – Rob Farr Oct 26 '17 at 14:47
  • Here we can use the "===" strict check, but in that case we would duplicate this answer: https://stackoverflow.com/a/2790919/3451846 – Valerio Bozz Jul 06 '23 at 07:40