7

I've done some researching on validating URLs in PHP and found that there are many different answers on StackOverflow, some better than others, and some very old and outdated.

I have a field where users can input their website's url. The user should be able to enter the URL in any form, for example:

example.com
www.example.com
http://example.com
http://www.example.com
https://example.com
https://www.example.com

PHP comes with a function to validate URLs, however, it marks the URL as invalid if it doesn't have http://.

How can I validate any sort of URL, with or without http:// or https://, that would ensure the URL is valid?

Thanks.

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
Bagwell
  • 2,018
  • 5
  • 18
  • 24
  • 2
    Why don't you simply append `http://` to it anyway? – Ali Dec 18 '13 at 22:17
  • Check out `parse_url()` as a function to explode the URL into components, you could then fix up any thing you need to, and then stitch it all back together for validation. Someone wrote a `unparse_url()` function in the user comments. – Scuzzy Dec 18 '13 at 22:18
  • Check if string starts with http, if it does not, append it. – Hanlet Escaño Dec 18 '13 at 22:19
  • @ChosenWann That's not validating the entire URL though. – Bagwell Dec 18 '13 at 22:26
  • 1
    @Scuzzy: `parse_url()` is a highly unfit choice to start any form of URL validation. It is incredibly hard to find any input that doesn't make it through `parase_url()`. Even strings with several schemata and linebreaks make it through. – DaSourcerer Dec 18 '13 at 22:26
  • @jprofitt That question is from 2008. It's old, things have changed since then. – Bagwell Dec 18 '13 at 22:26
  • @Bagwell append `http://` to it then validate all of it? – Ali Dec 18 '13 at 22:27
  • 2
    @Bagwell the internet is old, it still uses TCP/IP. – HamZa Dec 18 '13 at 22:28
  • Just ran a test prepending 'https://' to the variable. `https://foobar` passes; `https://foo bar` fails. In other words, there's a whole lot that's going to pass through as a result—but then again, I guess this would have passed through originally anyway, meaning at the very least it isn't introducing any security risk that isn't already there if you're just relying on `filter_var()` to do the job for you... – Kaji Dec 12 '17 at 08:32

4 Answers4

25

Use filter_var() as you stated, however, by definition a URL must contain a protocol. Using just http will check for https as well:

$url = strpos($url, 'http') !== 0 ? "http://$url" : $url;

Then:

if(filter_var($url, FILTER_VALIDATE_URL)) {
    //valid
} else {
    //not valid
}
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • Unfortunately, this will return `true` although `$url = '0812345'`. It will add prefix 'http://' and `filter_var('http://0812345', FILTER_VALIDATE_URL)` will return `true`. Any suggestion solution? – ibnɘꟻ Mar 04 '21 at 03:33
  • @fendiSetiawan What makes you think that’s not a valid URL? – AbraCadaver Mar 04 '21 at 03:34
  • Sure, if I run `parse_url('http://0812345')` it will return '0812345' as `hostname`. Technically, it's true. But, if user visit that url, it will return not found. Since it's not IP address or domain with TLD. I expect some validation that return true only if it's valid IP address or url website with TLD (example.com). Am I get wrong here? Or Am I just not knowing how url are called "valid"? – ibnɘꟻ Mar 04 '21 at 03:43
  • 1
    There’s valid and then there’s existing or reachable. There should be a question somewhere that addresses that. If not then ask one. You can post the link here as I have some ideas. – AbraCadaver Mar 04 '21 at 04:09
  • Ah... I see... The "unreachable URL" is what I looking for. Thank you for your help. Sorry if my question make some miss-understanding. Thanks. – ibnɘꟻ Mar 04 '21 at 04:25
3

I've also seen this used:

$url = "http://example.com";
if (preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i", $url)) {
  echo "URL is valid";
}
else {
  echo "URL is invalid";
}

Source: http://codekarate.com/blog/validating-url-php

James Binford
  • 2,753
  • 1
  • 14
  • 12
0

You can create a custom validation rule then add the following method in it :

protected function prepareForValidation()
{
        $urlWithHttp = strpos($this->url, 'http') !== 0 ? "http://$this->url" : $this->url;

        $this->merge([
            'url' => $urlWithHttp,
        ]);

}
Popouerk
  • 11
  • 1
-2

You could also let html validate the url:

Website: <input type="url" name="website" required pattern="https?://.+">
Daniel
  • 43
  • 7
  • 5
    Client side validation should never be trusted. – S. Saad Jun 18 '19 at 14:21
  • 1
    @Aniket Chowdhury Here's why your answer is out of topic: 1. OP mentions he'd looking for a way to do said validation in PHP 2. Even if we disregard the above, "Let the html validate the url" implies, in the context of the question asked by OP, to let the front end do the validation and accept it at the backend, which is totally not acceptable. Whether front end validation should or should not be done is not the matter at hand, hence the flag. – S. Saad Aug 13 '20 at 18:54