有没有更好的方法循环这些 PHP 代码,也许使用 foreach 循环?

Jam*_*mes 3 php foreach loops file-get-contents file-put-contents

file_get_contents用来获取远程定价(每天更新),用于substr仅保留我想要的部分(从输出中去除货币符号和其他数据并仅保留数字)并用于file_put_contents将其存储到我引用的缓存目录中到以后。

这就是我现在所拥有的:-

<?php

$cacheDirectory = $_SERVER['DOCUMENT_ROOT'] . '/cache/';

// Small Plan - US
$cachefile_SM_US = $cacheDirectory . 'SM_US.cache';

if(file_exists($cachefile_SM_US)) {
    if(time() - filemtime($cachefile_SM_US) > 1600) {
        // too old , re-fetch
        $cache_SM_US = file_get_contents('https://remotedomain.com/?get=price&product=10&currency=1');
        $substr_SM_US = substr($cache_SM_US,17,2);
        file_put_contents($cachefile_SM_US, $substr_SM_US);
        } else {
            // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_SM_US = file_get_contents('https://remotedomain.com/?get=price&product=10&currency=1');
    $substr_SM_US = substr($cache_SM_US,17,2);
    file_put_contents($cachefile_SM_US, $substr_SM_US);
}

// Large Plan - US
$cachefile_LG_US = $cacheDirectory . 'LG_US.cache';

if(file_exists($cachefile_LG_US)) {
    if(time() - filemtime($cachefile_LG_US) > 1600) {
        // too old , re-fetch
        $cache_LG_US = file_get_contents('https://remotedomain.com/?get=price&product=20&currency=1');
        $substr_LG_US = substr($cache_LG_US,17,2);
        file_put_contents($cachefile_LG_US, $substr_LG_US);
    } else {
        // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_LG_US = file_get_contents('https://remotedomain.com/?get=price&product=20&currency=1');
    $substr_LG_US = substr($cache_LG_US,17,2);
    file_put_contents($cachefile_LG_US, $substr_LG_US);
}

// Small Plan - EU
$cachefile_SM_EU = $cacheDirectory . 'SM_EU.cache';

if(file_exists($cachefile_SM_EU)) {
    if(time() - filemtime($cachefile_SM_EU) > 1600) {
        // too old , re-fetch
        $cache_SM_EU = file_get_contents('https://remotedomain.com/?get=price&product=10&currency=2');
        $substr_SM_EU = substr($cache_SM_EU,17,2);
        file_put_contents($cachefile_SM_EU, $substr_SM_EU);
        } else {
            // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_SM_EU = file_get_contents('https://remotedomain.com/?get=price&product=10&currency=2');
    $substr_SM_EU = substr($cache_SM_EU,17,2);
    file_put_contents($cachefile_SM_EU, $substr_SM_EU);
}

// Large Plan - EU
$cachefile_LG_EU = $cacheDirectory . 'LG_EU.cache';

if(file_exists($cachefile_LG_EU)) {
    if(time() - filemtime($cachefile_LG_EU) > 1600) {
        // too old , re-fetch
        $cache_LG_EU = file_get_contents('https://remotedomain.com/?get=price&product=20&currency=2');
        $substr_LG_EU = substr($cache_LG_EU,17,2);
        file_put_contents($cachefile_LG_EU, $substr_LG_EU);
    } else {
        // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_LG_EU = file_get_contents('https://remotedomain.com/?get=price&product=20&currency=2');
    $substr_LG_EU = substr($cache_LG_EU,17,2);
    file_put_contents($cachefile_LG_EU, $substr_LG_EU);
}

?>
Run Code Online (Sandbox Code Playgroud)

当只有两种产品 ( 10and 20) 和两种货币 ( 1and 2)时,这种手动方式有效,因为我只需要执行 4 次即可获得所需的所有定价。

但是,我打算将产品数量显着增加到至少 12 种产品和 9 种货币,因此手动执行这些操作是不现实的。

我相信这可以通过 PHP foreach 循环更有效地完成,但我尝试了几天并没有设法让它工作,也许是因为我对这个概念的理解较弱。

我设法把它分成了这个:-

<?php

$cacheDirectory = $_SERVER['DOCUMENT_ROOT'] . '/cache/';

$url = 'https://remotedomain.com/?get=price';
$productA = 10;
$productB = 20;
$USD = 1;
$EUR = 2;

// Small Plan - US
$cachefile_SM_US = $cacheDirectory . 'SM_US.cache';

if(file_exists($cachefile_SM_US)) {
    if(time() - filemtime($cachefile_SM_US) > 1600) {
        // too old , re-fetch
        $cache_SM_US = file_get_contents($url . '&product=' . $productA . '&currency=' . $USD);
        $substr_SM_US = substr($cache_SM_US,17,2);
        file_put_contents($cachefile_SM_US, $substr_SM_US);
        } else {
            // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_SM_US = file_get_contents($url . '&product=' . $productA . '&currency=' . $USD);
    $substr_SM_US = substr($cache_SM_US,17,2);
    file_put_contents($cachefile_SM_US, $substr_SM_US);
}

// Large Plan - US
$cachefile_LG_US = $cacheDirectory . 'LG_US.cache';

if(file_exists($cachefile_LG_US)) {
    if(time() - filemtime($cachefile_LG_US) > 1600) {
        // too old , re-fetch
        $cache_LG_US = file_get_contents($url . '&product=' . $productB . '&currency=' . $USD);
        $substr_LG_US = substr($cache_LG_US,17,2);
        file_put_contents($cachefile_LG_US, $substr_LG_US);
    } else {
        // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_LG_US = file_get_contents($url . '&product=' . $productB . '&currency=' . $USD);
    $substr_LG_US = substr($cache_LG_US,17,2);
    file_put_contents($cachefile_LG_US, $substr_LG_US);
}

// Small Plan - EU
$cachefile_SM_EU = $cacheDirectory . 'SM_EU.cache';

if(file_exists($cachefile_SM_EU)) {
    if(time() - filemtime($cachefile_SM_EU) > 1600) {
        // too old , re-fetch
        $cache_SM_EU = file_get_contents($url . '&product=' . $productA . '&currency=' . $EUR);
        $substr_SM_EU = substr($cache_SM_EU,17,2);
        file_put_contents($cachefile_SM_EU, $substr_SM_EU);
        } else {
            // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_SM_EU = file_get_contents($url . '&product=' . $productA . '&currency=' . $EUR);
    $substr_SM_EU = substr($cache_SM_EU,17,2);
    file_put_contents($cachefile_SM_EU, $substr_SM_EU);
}

// Large Plan - EU
$cachefile_LG_EU = $cacheDirectory . 'LG_EU.cache';

if(file_exists($cachefile_LG_EU)) {
    if(time() - filemtime($cachefile_LG_EU) > 1600) {
        // too old , re-fetch
        $cache_LG_EU = file_get_contents($url . '&product=' . $productB . '&currency=' . $EUR);
        $substr_LG_EU = substr($cache_LG_EU,17,2);
        file_put_contents($cachefile_LG_EU, $substr_LG_EU);
    } else {
        // cache is still fresh
    }
} else {
    // no cache, create one
    $cache_LG_EU = file_get_contents($url . '&product=' . $productB . '&currency=' . $EUR);
    $substr_LG_EU = substr($cache_LG_EU,17,2);
    file_put_contents($cachefile_LG_EU, $substr_LG_EU);
}

?>
Run Code Online (Sandbox Code Playgroud)

我现在面临的挑战是如何将其变成一个 foreach 循环,该循环将循环遍历每种产品和每种货币。

欣赏正确方向的指针。

谢谢!

Che*_*ass 6

绝对地。看看这个例子:)

<?php declare(strict_types=1);

interface CacheNormalizer
{
    public function normalize(string $text): string;
}

interface PlanDomainToCache
{
    public function buildUrl(Plan $plan): string;
}

final class CachedRemoteSiteManager
{
    /** @var int Time To Live Cache */
    private $timeToLive;

    /** @var CacheNormalizer */
    private $cacheNormalizer;

    /** @var PlanDomainToCache */
    private $planDomainToCache;

    public function __construct(
        int $timeToLive,
        CacheNormalizer $cacheNormalizer,
        PlanDomainToCache $planDomainToCache
    ) {
        $this->timeToLive = $timeToLive;
        $this->cacheNormalizer = $cacheNormalizer;
        $this->planDomainToCache = $planDomainToCache;
    }

    public function updateIfNecessary(Plan $plan): void
    {
        if ($this->shouldCreateOrUpdateCache($plan)) {
            $this->createOrUpdateCache($plan);
        }
    }

    private function shouldCreateOrUpdateCache(Plan $plan): bool
    {
        return !file_exists($plan->cacheDirectory())
            || time() - filemtime($plan->cacheDirectory()) > $this->timeToLive;
    }

    private function createOrUpdateCache(Plan $plan): void
    {
        $urlToCache = $this->planDomainToCache->buildUrl($plan);
        $textToCache = file_get_contents($urlToCache);

        file_put_contents(
            $plan->cacheDirectory(),
            $this->cacheNormalizer->normalize($textToCache)
        );
    }
}

final class Plan
{
    /** @var string */
    private $cacheDirectory;

    /** @var int */
    private $product;

    /** @var int */
    private $currency;

    public function __construct(string $cacheDir, int $product, int $currency)
    {
        $this->cacheDirectory = $cacheDir;
        $this->product = $product;
        $this->currency = $currency;
    }

    public function cacheDirectory(): string
    {
        return $this->cacheDirectory;
    }

    public function product(): int
    {
        return $this->product;
    }

    public function currency(): int
    {
        return $this->currency;
    }
}

// Usage example:

$cacheDirectory = $_SERVER['DOCUMENT_ROOT'] . '/cache/';
$productA = 10;
$productB = 20;
$USD = 1;
$EUR = 2;

/** @var Plan[] */
$plansToCache = [
    new Plan($cacheDirectory . 'SM_US.cache', $productA, $USD),
    new Plan($cacheDirectory . 'LG_US.cache', $productB, $USD),
    new Plan($cacheDirectory . 'SM_EU.cache', $productA, $EUR),
    new Plan($cacheDirectory . 'LG_EU.cache', $productB, $EUR),
];

$cacheManager = new CachedRemoteSiteManager(
    $cacheTtl = 1600,
    new class implements CacheNormalizer {
        public function normalize(string $text): string
        {
            return substr($text, 17, 2);
        }
    },
    new class implements PlanDomainToCache {
        public function buildUrl(Plan $plan): string
        {
            return sprintf(
                'https://remotedomain.com/?get=price&product=%d&currency=%d',
                $plan->product(),
                $plan->currency()
            );
        }
    }
);

foreach ($plansToCache as $plan) {
    $cacheManager->updateIfNecessary($plan);
}
Run Code Online (Sandbox Code Playgroud)

正如您在底部看到的,在“使用示例”中,我提取了所有详细信息(几乎全部),以便我们可以轻松定义:

  • 我们希望如何规范化缓存数据(使用 CacheNormalizer)
  • 我们希望如何构建我们想要缓存的 URL(使用 PlanDomainToCache)。

更新:

如果您想了解如何从结束代码中提取/解耦每个细节,甚至为“持久性”层反转依赖关系:https : //gist.github.com/Chemaclass/01d3f42685ff69f6897192202a32014d