我称返回某些链接方法的数组的对象为:
Songs::duration('>', 2)->artist('Unknown')->genre('Metal')->stars(5)->getAllAsArray();
问题在于每次我想要获取这个数组,例如在另一个脚本中,我必须再次链接一切。现在想象一下,在超过10个脚本中都需要这样做。
有没有一种方法可以在以后调用链接的方法?
如果您无法按照建议进行缓存,正如我所评论的那样,这里有几个想法。如果您的应用程序允许混合使用函数(例如,符合公司开发规则的标准),您可以使用函数包装器:
// The function can be as complex as you want
// You can make '>', 2 args too if they are going to be different all the time
function getArtists($array)
{
return \Songs::duration('>', 2)->artist($array[0])->genre($array[1])->stars($array[2])->getAllAsArray();
}
print_r(getArtists(array('Unkown','Metal',5)));
如果您只允许使用类,并且在您的开发中未禁用__callStatic()
,并且该函数在您使用的PHP版本中可用,则可以尝试使用它:
// If you have access to the Songs class
public __callStatic($name,$args=false)
{
// This should explode your method name
// so you have two important elements of your chain
// Unknown_Metal() should produce "Unknown" and "Metal" as key 0 and 1
$settings = explode("_",$name);
// Args should be in an array, so if you have 1 value, should be in key 0
$stars = (isset($args[0]))? $args[0] : 5;
// return the contents
return self::duration('>', 2)->artist($settings[0])->genre($settings[1])->stars($stars)->getAllAsArray();
}
这应该返回与您的链相同的内容:
print_r(\Songs::Unknown_Metal(5));
需要注意的是,重载很难跟踪,因为没有具体的方法叫做Unknown_Metal
,所以调试更加困难。此外,请注意我尚未在本地测试过这个特定的设置,但我已经注明了应该发生的情况。
如果不允许这些,那么我会创建一个缩短该链的方法:
public function getArtists($array)
{
// Note, '>', 2 can be args too, I just didn't add them
return self::duration('>', 2)->artist($array[0])->genre($array[1])->stars($array[2])->getAllAsArray();
}
print_r(\Songs::getArtists(array('Unkown','Metal',5)));
由于您无法缓存结果,因此可以在数组中缓存调用链的结构。
$chain = [
'duration' => ['>', 2],
'artist' => 'Unknown',
'genre' => 'Metal',
'stars' => 5,
'getAllAsArray' => null
];
你可以使用一个函数来模拟使用缓存数组的链式调用:
function callChain($object, $chain) {
foreach ($chain as $method => $params) {
$params = is_array($params) ? $params : (array) $params;
$object = call_user_func_array([$object, $method], $params);
}
return $object;
}
$result = callChain('Songs', $chain);
我写了一个库,完全实现了你所寻找的功能,并以高质量的方式实现了Don't Panic建议的原则:https://packagist.org/packages/jclaveau/php-deferred-callchain
在你的情况下,你需要编写以下代码:
$search = DeferredCallChain::new_(Songs::class) // or shorter: later(Songs::class)
->duration('>',2) // static syntax "::" cannot handle chaining sadly
->artist('Unknown')
->genre('Metal')
->stars(5)
->getAllAsArray();
print_r( $search($myFirstDBSongs) );
print_r( $search($mySecondDBSongs) );
__callStatic()
(如果你的PHP允许这种重载方法)来部分地通过函数名和参数来执行操作。比如\Songs::unknown_metal(5);
,当然假设'>', 2
是相同的...否则它们也必须作为参数传递进去。 - Rasclatt