这可能在PHP?

时间:2009-08-20 13:43:49

标签: php design-patterns oop reflection chain-of-responsibility

考虑以下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 个答案:

答案 0 :(得分:5)

基本上,您希望方法根据是否将发生对结果的后续方法调用来返回bool或对象。我不认为没有一些大规模的黑客攻击是可能的(例如,自己阅读PHP文件并展望未来),这不应该是因为你的对象不应该担心它们被使用的上下文。

相反,您可以获得第一次调用以返回在两种情况下都相关的对象,例如: DomainLookupResult,有两种方法,例如存在()和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();

答案 1 :(得分:3)

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

代码的问题在于方法返回非对象值,无论是true还是false。并且通过链接方法不会以任何方式更好地解决问题。你应该在适用的地方使用它。就像链接许多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();

答案 2 :(得分:1)

请查看方法链接。

More information

答案 3 :(得分:0)

如果你的函数返回一个对象,你可以调用它的方法,等等(参见method chaining)。唯一的限制是 - 据我所知 - 你不能链接来自new(new Object() - &gt; method1() - &gt; method2())创建的对象的调用。

至于你的例子,我认为使用动态类或方法链接都没有意义。