我正在开发一个Symfony 2项目,我正在制作一个自定义约束来检查是否存在url。我查了一下,发现了这个:
How can I check if a URL exists via PHP?
问题是,如果我尝试像www.flskkhfkhsdf.com这样的完全随机的广告,它会给我一个警告并停止我的代码。还有其他办法吗?
警告:
警告:get_headers():php_network_getaddresses:getaddrinfo failed:没有这样的主机。
这是我的代码:
<?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();
}
}
}
答案 0 :(得分:1)
我不知道特定于Symfony的解决方案,我将为您提供一些核心PHP函数。
gethostbyname就是您所需要的。在有效的主机名上,它将返回IP地址。在不存在的主机名上,它将返回未修改的主机名。
所以你可以做点什么
if (gethostbyname($hostname) == $hostname) {
$this->context->buildViolation...
}
当然,您必须从给定的网址中提取基本主机名,但您可以使用parse_url执行此操作:
$hostname = parse_url($url, PHP_URL_HOST)
当然,您必须首先验证网址,但您可以使用filter_var执行此操作:
if ( ! filter_var($url, FILTER_VALIDATE_URL)) {
// URL not valid
}
完整代码可能或多或少如下:
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();
}
答案 1 :(得分:0)
您可以使用任何HTTP客户端库(如Guzzle或Buzz)来访问该URL。如果发生任何错误,这些库将抛出异常。
使用HTTP方法“HEAD”以避免下载整个页面。
答案 2 :(得分:0)
我找到了一个有效的解决方案:
<?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();
}
}