我想在PHP中创建一个简单的Path
类。我决定使用一些类似多态的机制来实现它,但我发现没有办法同时为它们做这些:静态和非静态函数。您是否有任何想法如何以优雅的方式实现absolute()
功能?
class Path {
private $path = '';
// Some code here [...]
public function absoulte() {
return "http://$_SERVER[HTTP_HOST]$this->path";
}
public static function absoulte($path) {
return "http://$_SERVER[HTTP_HOST]$path";
}
}
答案 0 :(得分:1)
您可以尝试使用“__callStatic”。如果你在这个类上调用任何静态函数,它将触发。 “$ name”将是方法名称,“$ arguments”是传递的任何参数。 :d
class Path {
private $path = '';
// Some code here [...]
public function absoulte() {
return "http://$_SERVER[HTTP_HOST]$this->path";
}
public static function __callStatic($name,$arguments) {
if ($name == "absoulte") { return "http://$_SERVER[HTTP_HOST]$arguments"; }
}
}
答案 1 :(得分:1)
好的,我试一试,看看它对你有帮助。 :)
我认为实际上有很多方法可以实现您所描述的公共界面,尽管它们在编码和维护方面似乎都相当复杂。因此,如果不是真的有必要,我的建议是不要走这条路。我会举一些例子......
__call
和__callStatic
我们可以简单地使用__call
和__callStatic
作为我们方法的代理,并使用稍微不同的参数调用实际方法。顶部的PhpDoc应该支持IDE了解这里发生了什么。
/**
* @method string absolute()
* @method static string absolute(string $path)
*/
class Path
{
protected $path;
public function __construct(string $path)
{
$this->path = $path;
}
public function __call(string $name, array $args)
{
if ($name === 'absolute') {
return self::getAbsolutePath($this->path);
}
// ... other functions ...
}
public function __callStatic(string $name, array $args)
{
if ($name === 'absolute' && count($args) >= 1) {
return self::getAbsolutePath($args[0]);
}
// ... other functions ...
}
private static function getAbsolutePath(string $path): string
{
return "http://{$_SERVER[HTTP_HOST]}{$path}";
}
}
因为我们既可以以静态方式也可以以非静态方式访问PHP中的方法,我们只需使用这些信息来返回正确的结果。
/**
* @method string absolute()
* @method static string absolute(string $path)
*/
class Path
{
protected $path;
public function __construct(string $path)
{
$this->path = $path;
}
public function absolute(?string $path): string
{
if (isset($this) && $this instanceof self) {
$path = $this->path;
}
return "http://{$_SERVER[HTTP_HOST]}{$path}";
}
}
我认为还有其他方法可以实现这一点,可能是使用代理类左右。但正确的做法也取决于我们迄今为止看到的其他要求。因为一个参数$path
很容易处理,但是你的类越复杂,实现不同场景的工作就越多。
总结一下,我想了解上面的评论:如果有办法解决问题,尽量不要实施两次。你会发现自己处于以后在多个地方寻找虫子的情况。因此,最好的想法就是让两个不同的接口具有通用实现。它实际上甚至可以有意义,因为相同的方法名称在静态环境和非静态环境中都不一定有意义。所以考虑使用这样的东西:
/**
* @method string absolute()
* @method static string absolute(string $path)
*/
class Path
{
protected $path;
public function __construct(string $path)
{
$this->path = $path;
}
public function getAbsolutePath(): string
{
return self::absolute($this->path);
}
public static function absolute(string $path): string
{
return "http://{$_SERVER[HTTP_HOST]}{$path}";
}
}
答案 2 :(得分:1)
它已经解决了,但也许可以帮助其他人。以下是使用func_num_args()
和func_get_arg()
函数的另一种方法。
class Path {
private $path = '';
// ...
public function absolute() {
switch (func_num_args()) {
case 0: return "http://" . $_SERVER[HTTP_HOST] . $this->path;
case 1: return "http://" . $_SERVER[HTTP_HOST] . func_get_arg(0);
default: trigger_error("Invalid number of arguments", E_USER_ERROR);
}
}
}