简体   繁体   English

调用 PHP 上的链式方法

[英]Recall chained methods on PHP

I call an object that returns an array given certain chained methods:我调用一个对象,该对象在给定某些链式方法的情况下返回一个数组:

Songs::duration('>', 2)->artist('Unknown')->genre('Metal')->stars(5)->getAllAsArray();

The problem lies that every time I want to get this array, for example, in another script, I have to chain everything again .问题在于,每次我想要获取这个数组时,例如在另一个脚本中,我必须再次链接所有内容 Now imagine that in over 10 scripts.现在想象一下,在 10 多个脚本中。

Is there a way to recall the chained methods for later use?有没有办法调用链式方法供以后使用?

If you can not cache your results as suggested, as I commented, here are a couple ideas.如果您无法按照建议缓存结果,正如我所评论的,这里有一些想法。 If your application allows for mixing of functions (as in you are permitted by standards of your company's development rules) and classes, you can use a function wrapper:如果您的应用程序允许混合使用函数(因为您公司的开发规则标准允许您这样做)和类,您可以使用函数包装器:

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

If you are only allowed to use classes and __callStatic() is not forbidden in your development and is also available in the version of PHP you are using, you might try that:如果您只允许使用类并且__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();
    }

This should return the same as your chain:这应该返回与您的链相同的内容:

print_r(\Songs::Unknown_Metal(5));

It should be noted that overloading is hard to follow because there is no concrete method called Unknown_Metal so it's harder to debug.需要注意的是,重载很难遵循,因为没有名为Unknown_Metal具体方法,因此更难调试。 Also note I have not tested this particular set-up out locally, but I have notated what should happen where.另请注意,我没有在本地测试过这个特定的设置,但我已经注明了应该在何处发生的情况。

If those are not allowed, I would then make a method to shorten that chain:如果这些不被允许,那么我将制定一种方法来缩短该链:

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

Since you can't cache the result, you could cache the structure of the call chain in an array.由于您无法缓存结果,您可以将调用链的结构缓存在数组中。

$chain = [
    'duration' => ['>', 2],
    'artist' => 'Unknown',
    'genre' => 'Metal', 
    'stars' => 5,
    'getAllAsArray' => null
];

You could use that with a function that emulates the chained call using the cached array:您可以将它与使用缓存数组模拟链接调用的函数一起使用:

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

I wrote a lib doing exactly what you're looking for, implementing the principle suggested by Don't Panic in a high quality way: https://packagist.org/packages/jclaveau/php-deferred-callchain我写了一个库,完全符合你的要求,以高质量的方式实现了 Don't Panic 建议的原则: https : //packagist.org/packages/jclaveau/php-deferred-callchain

In your case you would code在你的情况下,你会编码

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

Hoping it will match your needs!希望它能满足您的需求!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM