我一直在尝试使用__call来动态返回类的属性值,而不是创建一系列函数,其唯一目的是返回这些值。我的想法是能够请求(例如) $ this-&gt; fetch_PersonFirstName()并让班级检查 $ this-&gt; person [“first_name”] < / strong>已设置并返回值。另一个例子是调用 $ this-&gt; fetch_BookGenreTitle()并让该类返回 $ this-&gt; book [“genre”] [“title”] 。我知道这样的事情需要做一些检查才能自动确定,例如,因为 $ this-&gt; book [“genre_title”] 不存在,那么它应该检查 $ this-&gt; book [“genre”] [“title”] 。
到目前为止,我已经提出了(由于某种原因)返回数组值(例如我的人员示例)的代码,但是当我尝试返回多维数组的值时,我的问题很快就会出现(比如我上面的书中的例子)。请记住,我仍然试图想办法让__call方法检查一个是否存在,如果它不存在,那么另一个。
请在这里告诉我一句话。我一直在撞墙,试图解决这个问题,这让我很伤心。
<?php
class Test
{
protected $person;
protected $book;
public function __construct()
{
$this->person["first_name"] = "John Smith";
$this->book["genre"]["title"] = "Suspense";
}
public function __call($method, $args)
{
$args = implode(", ", $args);
if (preg_match("/^fetch_([A-Z]{1,}[a-z]{1,})(.*)?/", $method, $match))
{
print_r($match);
echo "<br><br>";
$property = strtolower($match[1]);
$indexes = $match[2];
if (property_exists("Test", $property))
{
if ($indexes)
{
$indexes = preg_split("/(?<=[a-z])(?=[A-Z])/", $indexes);
$num_indexes = count($indexes);
$count_indexes = 1;
for ($count=0; $count<$num_indexes; $count++)
{
$record = strtolower($indexes[$count]);
$index .= $record;
$array .= "{$record}";
$var_index = $index;
$var_array = $array;
echo $var_index." {$count}<br>";
echo $var_array." {$count}<br>";
//print_r($this->{$property}{$var_array});
if ($count_indexes == $num_indexes)
{
if (isset($this->{$property}{$var_index}))
{
return $this->{$property}{$var_index};
}
else
{
return $this->{$property}{$var_array};
}
}
else
{
$index .= "_";
}
$count_indexes++;
}
echo "<br><br>";
}
else
{
return $this->{$property};
}
}
}
}
}
?>
<?php
$test = new Test();
echo $test->fetch_PersonFirstName();
echo "<br><br>";
echo $test->fetch_BookGenreTitle();
?>
答案 0 :(得分:1)
再次感谢大家。我想我终于有了我的解决方案,适用于多维数组或任何深度和帐户,以确定属性是否,例如 $ this-&gt; book [“genre_title”] 或 $ this-&gt; book [“genre”] [“title”] :)
我发布下面的代码,因为其他人可能会随机发现它在将来有用
<?php
class Test
{
protected $person;
protected $book;
public function __construct()
{
$this->person["first_name"] = "John Smith";
$this->book["genre"]["title"] = "Suspense";
}
public function __get($var)
{
if (preg_match_all("/([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)/", $var, $matches))
{
$matches = $matches[1];
$property = strtolower($matches[0]);
if (property_exists($this, $property))
{
unset($matches[0]);
$matches = array_values($matches);
$num_matches = count($matches);
$var = &$this->{$property};
if (!$num_matches)
{
return $var;
}
else
{
foreach($matches as &$match)
{
$match = strtolower($match);
$index .= $match;
if ($probe = $this->iterateArray($var, $index))
{
$var = $probe;
unset($index);
}
elseif ($probe = $this->iterateArray($var, $index))
{
$var = $probe;
}
else
{
$index .= "_";
}
}
return $var;
}
}
}
}
public function iterateArray($var, $index)
{
if (array_key_exists($index, $var))
{
return $var[$index];
}
else
{
return false;
}
}
}
?>
<?php
$test = new Test();
echo $test->PersonFirstName;
echo "<br><br>";
echo $test->BookGenreTitle;
?>
有很多方法可以改进/简化代码,在这种情况下,任何想要这样做的人都非常欢迎发布改进版本。
答案 1 :(得分:0)
您需要查看property overloading,而不是method overloading,因为您已经在问题标题中找到了自己。
答案 2 :(得分:0)
鉴于“BookGenreTitle”:
property_exists($this, "Book")
array_key_exists("genre", $this->book)
$this->book["genre"]
array_key_exists("genre_title", $this->book)
$this->book["genre_title"]
array_key_exists("genre", $this->book) && array_key_exists("title", $this->book["genre"])
可能有一种方法可以使用循环或某种递归而不是硬编码最大深度,但我现在不会进入...
哦,正如另一张海报所说,你想要的是财产超载(__get
和__set
)。