考虑以下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 :这个代码段被截断了,所以不要指望它只是通过它自己的意义。
答案 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)
请查看方法链接。
答案 3 :(得分:0)
如果你的函数返回一个对象,你可以调用它的方法,等等(参见method chaining)。唯一的限制是 - 据我所知 - 你不能链接来自new(new Object() - &gt; method1() - &gt; method2())创建的对象的调用。
至于你的例子,我认为使用动态类或方法链接都没有意义。