2 回答
TA貢獻1911條經驗 獲得超7個贊
絕對地。看看這個例子:)
<?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¤cy=%d',
$plan->product(),
$plan->currency()
);
}
}
);
foreach ($plansToCache as $plan) {
$cacheManager->updateIfNecessary($plan);
}
正如您在底部看到的,在“使用示例”中,我提取了所有細節(幾乎所有細節),因此我們可以輕松定義:
我們要如何規范化緩存數據(使用 CacheNormalizer)
我們要如何構建要緩存的 URL(使用 PlanDomainToCache)。
更新:
如果您想了解如何從結束代碼中提取/解耦每個細節,即使對于“持久性”層也向上反轉依賴關系:https ://gist.github.com/Chemaclass/01d3f42685ff69f6897192202a32014d
TA貢獻1871條經驗 獲得超8個贊
如果我正確地解釋了代碼,您想要查找兩種貨幣的兩種產品。這可以在您定義產品和貨幣后使用嵌套的 foreach 循環來完成。
$cacheDirectory = $_SERVER['DOCUMENT_ROOT'] . '/cache/';
$url = 'https://remotedomain.com/?get=price';
const MAX_CACHE_TIME = 1600;
// Optional
$output = [];
$productList = [
[
'id' => 10,
'name' => 'SM',
],
[
'id' => 20,
'name' => 'LG',
]
];
$currencies = [
'US' => 1,
'EU' => 2,
];
foreach ($productList as $product) {
foreach ($currencies as $currencyName => $currencyId) {
$cacheFile = $cacheDirectory . $product['name'] . '_' . $currencyName . '.cache';
if (!file_exists($cacheFile) || filemtime($cacheFile) > MAX_CACHE_TIME) {
// No cache or too old
$data = file_get_contents($url . '&product=' . $product['id'] . '¤cy=' . $currencyId);
$relevantData = substr($data, 17, 2);
file_put_contents($cacheFile, $relevantData);
// Optional, put the data in an array
$output[$product['id']][$currencyId] = $relevantData;
} else {
$output[$product['id']][$currencyId] = file_get_contents($cacheFile);
}
}
}
// Read outputwith $output[10]['US'] for example
- 2 回答
- 0 關注
- 119 瀏覽
添加回答
舉報
