Есть ли лучший способ циклически проходить через эти PHP коды, может быть, с foreach l oop? - PullRequest
3 голосов
/ 15 апреля 2020

Я использую 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);
}

?>

Этот ручной способ работает, когда есть только два продукта (10 и 20) и две валюты (1 и 2) поскольку мне нужно сделать это только 4 раза, чтобы получить все необходимые мне цены.

Однако я собираюсь значительно расширить количество продуктов по крайней мере до 12 продуктов и 9 валют, поэтому нереально c делать их вручную.

Я считаю, что это можно сделать более эффективно с помощью PHP foreach l oop, но я пробовал несколько дней, но мне не удалось заставить его работать, возможно, из-за моего более слабого понимания концепции.

Мне удалось разделить это на следующее: -

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

?>

Теперь передо мной стоит задача - как превратить это в foreach l oop, который будет циклически проходить через каждый продукт и каждый валюты.

Цените указатели в правильном направлении.

Спасибо!

Ответы [ 2 ]

6 голосов
/ 15 апреля 2020

Абсолютно. Посмотрите на этот пример:)

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

Как вы можете видеть внизу, в «примере использования» я извлек все детали (почти все), чтобы мы могли легко определить:

  • как мы хотим нормализовать кэшированные данные (используя CacheNormalizer)
  • как мы хотим создать URL, который мы хотим кэшировать (используя PlanDomainToCache).

ОБНОВЛЕНО:

Если вы хотите увидеть, как можно извлечь / отделить каждую деталь от конечного кода, инвертируя зависимости вверх даже для слоя «Постоянство»: https://gist.github.com/Chemaclass/01d3f42685ff69f6897192202a32014d

0 голосов
/ 15 апреля 2020

Если я правильно интерпретировал код, вы хотите найти оба продукта для обеих валют. Это можно сделать с помощью вложенного foreach l oop после определения продуктов и валют.

$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'] . '&currency=' . $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 output with $output[10]['US'] for example
...