-1

考虑以下 PHP 片段:

<?php

class Is
{
    function __get($key)
    {
        $class = __CLASS__ . '_' . $key;

        if (class_exists($class) === true)
        {
            return $this->$key = new $class();
        }

        return false;
    }

    function Domain($string)
    {
        if (preg_match('~^[0-9a-z\-]{1,63}\.[a-z]{2,6}$~i', $string) > 0)
        {
            return true;
        }

        return false;
    }
}

class Is_Domain
{
    function Available($domain)
    {
        if (gethostbynamel($domain) !== false)
        {
            return true;
        }

        return false;
    }
}

$Is = new Is();

var_dump($Is->Domain('google.com')); // true
var_dump($Is->Domain->Available('google.com')); // false

?>

是否可以像这样调用 Available() 方法(如果未调用 Available 方法,仍然只返回 true 或 false)?

var_dump($Is->Domain('google.com')->Available()); // false

如果是,如何?

编辑:这会奏效吗?

class Is
{
    function __get($key)
    {
        // same as before
    }

    function Domain($string)
    {
        if (preg_match('~^[0-9a-z\-]{1,63}\.[a-z]{2,6}$~i', $string) > 0)
        {
            return (bool) $this->Domain;
        }

        return false;
    }
}

class Is_Domain
{
    function __toString()
    {
        return true;
    }

    function Available($domain)
    {
        if (gethostbynamel($domain) !== false)
        {
            return true;
        }

        return false;
    }
}

提前致谢!

PS:这个片段被截断了,所以不要指望它本身就很有意义。

4

3 回答 3

5

本质上,您希望一个方法根据是否会发生对结果的后续方法调用来返回布尔值或对象。我认为如果没有一些大规模的 hack(例如,自己阅读 PHP 文件并向前看),这将是不可能的,这不应该是因为您的对象不应该担心使用它们的上下文。

相反,您可以在第一次调用时返回一个在这两种情况下都相关的对象,例如 DomainLookupResult,它有两个方法,例如 Exists() 和 IsAvailable()。然后你可以这样做:

$result = $Is->Domain('google.com');
$isValid = $result->Exists();
$isAvaliable = $result->IsAvailable();

//or chaining:

$isValid = $Is->Domain('google.com')->Exists();
$isAvailable = $Is->Domain('google.com')->IsAvailable();
于 2009-08-20T13:54:16.350 回答
3

如果它们返回一个对象,您只能链接方法调用!这是因为您只能调用对象上的方法。

您的代码的问题是这些方法返回一个非对象值,无论是真还是假。而且这个问题并没有通过链接方法更好地解决。您应该在适用的地方使用它。就像链接许多 setter,而不是您想要使用的方法本质上的 getter。

var_dump($Is->Domain->Available('google.com')); // false
//is the same as
$res = $Is->Domain;
$res = $res->Available('google.com'));
var_dump($res);

所以你看到第一个 res 是一个布尔值 true 或 false,你不能调用它的方法。

编辑 这可能是一个“解决方案”。虽然这不是一个好的解决方案,因为没有链接会更好。

class Domain
{
    public $domain;

    function setDomain($domain) {
        $this->domain = $domain;

        return $this;
    }

    function isDomain($domain = null) {
        if (is_string($domain)) {
            $this->setDomain($domain);
        }
        $result = gethostbynamel($this->domain) !== false;

        return new Result($this, $result);
    }

    function isValid() {
        $result = (bool) preg_match('', $this->domain);
        return new Result($this, $result)
    }
}

class Result
{
    public $result;
    public $object;

    public function __construct($object, $result)
    {
        $this->result = $result;
        $this->object = $object;
    }

    public function __call($method, $arguments)
    {
        if (is_object($this->result)) {
            return call_user_func_array(array($this->result, $method), $arguments);
        }
        if (!$this->result) {
            return $this;
        }
        return call_user_func_array(array($this->object, $method), $arguments);
    }
}

$domain = new Domain();
var_dump($domain->isValid('google.com')->isAvailable()->result);

/编辑

这将解决您上面的问题。

var_dump($Is->Domain('validandfreedomain.com') && $Is_Domain->Available('validandfreedomain.com')); // true

如果你非常想为这个问题链接一个方法,你可以让它更像这样。

class Domain
{
    public $domain;

    function setDomain($domain) {
        $this->domain = $domain;

        return $this;
    }

    function isAvailable() {
        return gethostbynamel($this->domain) !== false;
    }

    function isValid() {
        return (bool) preg_match('', $this->domain);
    }
}

$domain = new Domain();
$result = $domain->setDomain('validandfreedomain.com')->isValid() && $domain->isAvailable();
于 2009-08-20T13:54:26.053 回答
0

有可能,如果您的函数返回一个对象,您可以调用它的方法,依此类推(参见方法链接)。唯一的限制是 - 据我所知 - 你不能链接来自由 new ( new Object()->method1()->method2() ) 创建的对象的调用。

至于您的示例,我认为使用动态类或方法链接的东西没有意义。

于 2009-08-20T13:57:17.280 回答