如何检查php中是否存在url

I'm working on a Symfony 2 project and I'm making a custom constraint to check if an url exist. I checked around and found this:

How can I check if a URL exists via PHP?

The problem is if I try a totally random adresse like www.flskkhfkhsdf.com, it gives me a warning and it stop my code. Is there an other way to do that?

The warning:

Warning: get_headers(): php_network_getaddresses: getaddrinfo failed: No such host is known.

Here is my code:

<?php

namespace AdminBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

Class ContrainteUrlExistValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        $file_headers = get_headers($value);
        if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
            $this->context->buildViolation($constraint->message)
                ->setParameter('%string%', $value)
                ->addViolation();
        }
    }
}

I found a solution that works:

<?php

namespace AdminBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

Class ContrainteUrlExistValidator extends ConstraintValidator
{
    public function validate($url, Constraint $constraint)
    {
        //Vérifie si l'url peut être vide
        if(empty($url)&&$constraint->peutEtreVide)
        {
            return;
        }

        //Pattern pour trouver les url qui commence par http:// ou https://
        $pattern='/^(https?:\/\/)/';

        //Valide l'url et s'assure le preg_match a trouvé un match
        if(filter_var($url, FILTER_VALIDATE_URL)&&!empty(preg_match($pattern, $url, $matches)))
        {
            //Trouve l'host
            $hostname=parse_url($url, PHP_URL_HOST);

            //Tente de trouver l'adresse IP de l'host
            if (gethostbyname($hostname) !== $hostname)
            {
                //Cherche les données de l'entête
                $headers=get_headers($url);

                //Tente de trouver une erreur 404
                if(!strpos($headers[0], '404'))
                {
                    return;
                }
            }
        }

        //Crée une erreur
        $this->context->buildViolation($constraint->message)
                    ->setParameter('%string%', $url)
                    ->addViolation();
    }
}

I don't know about Symfony-specific solutions, I will give you some core PHP functions.

gethostbyname is what you need. On a valid hostname, it will return the ip address. On a non-existent hostname, it will return the hostname unmodified.

So you can do something like

if (gethostbyname($hostname) == $hostname) {
    $this->context->buildViolation...
}

Of course you have to extract the base hostname from the given URL, but you can do that with parse_url:

$hostname = parse_url($url, PHP_URL_HOST)

And of course you have to validate the URL first, but you can do that with filter_var:

if ( ! filter_var($url, FILTER_VALIDATE_URL)) {
    // URL not valid
}

EDIT: full code

The full code can be more or less like this:

public function validate($value, Constraint $constraint)
{
    if ( ! filter_var($value, FILTER_VALIDATE_URL)) {
        $this->failValidation();
        return;
    }

    $hostname = parse_url($value, PHP_URL_HOST);
    if (empty($hostname)) {
        $this->failValidation();
        return;
    }

    if (gethostbyname($hostname) == $hostname) {
        $this->failValidation();
        return;
    }
}

protected function failValidation($value, Constraint $constraint) 
{
    $this->context->buildViolation($constraint->message)
            ->setParameter('%string%', $value)
            ->addViolation();
}

You can use any HTTP client library like Guzzle or Buzz to access the URL. These libraries will throw an exception if any error occurs.

Use the HTTP method "HEAD" to avoid downloading the whole page.