2009-08-20 5 views
-1

Betrachten Sie den folgenden PHP-Schnipsel:Ist das in PHP möglich?

<?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 

?> 

Ist es möglich, die verfügbar() Methode wie folgt (und nach wie vor, wenn die verfügbare Methode aufgerufen wird, nicht nur wahr oder falsch zurück) zu nennen?

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

Wenn ja, wie?

EDIT: Würde das den Trick machen?

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; 
    } 
} 

Vielen Dank im Voraus!

PS: Dieses Snippet ist abgeschnitten, also erwarte nicht, dass es alleine Sinn macht.

Antwort

5

Im Wesentlichen wollen Sie eine Methode entweder einen bool oder ein Objekt auf Basis zurückzukehren, ob ein nachfolgender Methodenaufruf zu dem Ergebnis, auftreten wird. Ich denke nicht, dass dies ohne einen massiven Hack möglich ist (z. B. das Lesen der PHP-Datei in sich und den Blick nach vorne), und das sollte nicht daran liegen, dass sich Ihre Objekte nicht um den Kontext kümmern sollten, in dem sie verwendet werden.

Stattdessen könnten Sie den ersten Aufruf erhalten, um ein Objekt zurückzugeben, das in beiden Fällen relevant ist, z. DomainLookupResult, das zwei Methoden aufweist, z. Exists() und IsAvailable(). Sie könnten dann tun:

$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(); 
+0

+1, das war, was ich dachte, ich erwog auch, die Objektdomäne zurückzugeben, und wenn keine Methode der Domäne aufgerufen wurde, würde der __toString in Aktion treten und true zurückgeben, andernfalls wäre die Zeichenfolge keine Domäne, die sie einfach zurückgeben würde falsch. Denkst du, dass es eine gute Idee ist? –

+0

Bitte werfen Sie einen Blick auf meine Bearbeitung. –

+0

@eyze: Nein. Ich habe gerade getestet und Objekte, wenn Cast zu Boole sind immer wahr, __toString() heißt nicht –

1

Bitte beachten Sie die Methodenverkettung.

More information

+7

Bitte schauen Sie auf den Mond. Können Sie ihm stattdessen eine klarere Antwort geben? :) – Sampson

+0

In der Tat, das ist nicht relevant für diese Frage. –

+0

Es tut mir leid, ich habe etwas verpasst und dachte, das war die Lösung :) – Marien

3

Sie können Methodenaufrufe nur verketten, wenn sie ein Objekt zurückgeben! Dies liegt daran, dass Sie Methoden nur für Objekte aufrufen können.

Das Problem mit Ihrem Code ist, dass die Methoden einen Nicht-Objekt-Wert zurückgeben, entweder wahr oder falsch. Und das Problem wird durch Verkettungsmethoden nicht besser gelöst. Sie sollten das verwenden, wo es anwendbar ist. Wie verketten viele Setter, nicht Getter, welche Methoden Sie im Wesentlichen verwenden möchten.

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

So sehen Sie die erste res ist ein boolescher wahr oder falsch, und Sie können nicht eine Methode dazu aufrufen.

bearbeiten Dies könnte eine "Lösung" sein. Keine gute Lösung, da dies ohne Verkettung besser ist.

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); 

bearbeiten/

Dies wird Ihr Problem oben lösen.

Wenn Sie verzweifelt eine Methode für dieses Problem verketten möchten, könnten Sie es eher so machen.

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(); 
+0

Bitte beachten Sie, dass ich die __get magische Methode verwende. –

+0

@eyze: das ist irrelevant für die Frage. Sie können selbst hinzufügen, was Sie dort benötigen. Die Klasse dient nur dazu, die Verkettung zu demonstrieren, und dabei schlecht. Die Aufgabe wäre wahrscheinlich besser, wenn Sie die Domäne als Parameter zum Konstruktor hinzufügen. – OIS

+0

+1, das ist eine gültige Lösung, aber nicht die, nach der ich suche. –

0

Es ist möglich, wenn Ihre Funktion ein Objekt zurückgibt, können Sie die Methode aufrufen, und so weiter (siehe method chaining). Die einzige Einschränkung ist - soweit ich weiß -, dass Sie Aufrufe von einem Objekt, das von new erstellt wurde, nicht verketten können (new Object() -> method1() -> method2()).

Was Ihr Beispiel betrifft, sehe ich keinen Sinn darin, die dynamische Klasse oder Methodenverkettung zu verwenden.

+0

Das einzige Problem ist, wie würde ich True anstelle eines Objekts zurückgeben, wenn die Domain :: Available() -Methode danach nicht aufgerufen wird? –