Это возможно в PHP? - PullRequest
       37

Это возможно в PHP?

0 голосов
/ 20 августа 2009

Рассмотрим следующий фрагмент 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 (), подобный этому (и при этом возвращать только true или false, если метод Available не вызывается)?

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 ]

5 голосов
/ 20 августа 2009

По сути, вы хотите, чтобы метод возвращал либо bool, либо объект в зависимости от того, произойдет ли последующий вызов метода для результата. Я не думаю, что это будет возможно без какого-либо массового взлома (например, чтения файла 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();
3 голосов
/ 20 августа 2009

Вы можете связывать вызовы методов, только если они возвращают объект! Это потому, что вы можете вызывать методы только для объектов.

Проблема с вашим кодом состоит в том, что методы возвращают не объектное значение, истинное или ложное. И проблема никак не решается лучше с помощью цепочки методов. Вы должны использовать это там, где это применимо. Подобно цепочке множества сеттеров, а не геттеров, которые по сути представляют собой методы, которые вы хотите использовать.

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();
1 голос
/ 20 августа 2009

Пожалуйста, посмотрите на метод цепочки.

Дополнительная информация

0 голосов
/ 20 августа 2009

Возможно, если ваша функция возвращает объект, вы можете вызвать его метод и т. Д. (См. цепочка методов ). Насколько мне известно, единственным ограничением является то, что вы не можете связывать вызовы от объекта, созданного новым (new Object () -> method1 () -> method2 ()).

Что касается вашего примера, я не вижу смысла в использовании динамического класса или цепочки методов.

...