Консоль Symfony для cron или расписания задач в сочетании с Task Runner

Для моего проекта мне нужно импортировать 12-15 файлов, от CSV, xml до gz. Поскольку все файлы имеют свою структуру, мне пришлось создать по одной команде для каждого файла. Но это уже слишком и хочется создать общий импорт для всех файлов.

Требования:

  • Скрипт импорта должен запускаться каждый час.
  • В скрипте импорта должна быть импортированная категория + товары из импорта
  • Сценарий импорта должен проверить, соответствует ли моя категория категории импорта, если да, он должен добавить информацию в база данных, если не игнорировать.
  • Импорт не должен влиять на веб-сайт, если он выполняется в фоновом режиме.

Что у меня в данный момент в команде:

$handle = fopen("https://example.csv",'r');

$output->writeln('Downloading done!');

$categortArray = [];
$categortA = [];
while (($row = fgetcsv($handle, 4096, ";")) !== FALSE)
{
    $categortA [ $row[21]] = $row[23] ;
    $categortArray [] = $row[21];
}

$output->writeln('Updating category list !');
$result = array_unique($categortArray);
$result2 = array_unique($categortA);

$distributor = $distributor->findByName("Name of Distributor");

foreach ($result as $productgroup) {
    $result = $categoryRepository->findByTitle($productgroup);
    if (empty($result)){
        $category = new Category();
        $category->setTitle($productgroup);
        $category->setDescription("Category Description");
        $category->setDistributor($distributor);

        $categoryService->create($category);
    }
}

foreach ($result2 as $key => $productgroup) {
    $result = $categoryRepository->findByTitle($key);

    /** @var $result Category */
    if ($result !== null) {
        $category = new Category();
        $category->setTitle($productgroup);
        $category->setParent($result[0]);
        $category->setDescription("Name of Distributor");
        $category->setDistributor($distributor);

        $categoryService->create($category);
    }
}

while (($row = fgetcsv($handle, 4096, ";")) !== FALSE)
{

    foreach ($child as $c) {
        if ($c->getTitle() === $row['21']) {
            $product = new Product();
            $product->setName($row[1]);
            $product->setCategory($categoryTop);
            $product->setSku($row[14]);
            $product->setEanUpc($categoryTop->getId());
            $this->productService->save($product);
        }
    }
}

Варианты, о которых я могу думать:

  • Вытяните весь сценарий автоматического импорта за одну команду и запускайте его каждые час. Это несложный вариант, но я не думаю, что это лучшее решение, поскольку он потребует много ресурсов на моем сервере.
  • Создайте планировщик задач в сочетании с средством запуска задач, где мы регистрируем каждое событие различных шагов, таких как загрузка файла, чтение файла, проверка наличия, проверка соответствия категории, проверка наличия продукта, проверка наличия актуальных запасов продукта и т. д. Для этого варианта я хочу создать свой собственный планировщик + бегун, но у меня нет такого большого опыта и я не знаю, поможет ли это моему проекту. Поскольку каждая задача будет помещена в очередь, это упрощает проверку, если что-то не удается

Также приветствуются советы по моей текущей команде Symfony.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
231
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Раньше я решал что-то похожее, теперь эти советы зависят от того, сколько данных вам нужно синхронизировать (у меня было около 8 источников каждый, около 10 000 элементов, синхронизация которых не длилась более 15 минут).

Архитектура решения такая

  • Для каждого источника у вас есть Tranformer, который загружает исходный файл и анализирует его в один общий TransformedDTO, в вашем случае это может быть либо один продукт, который содержит категорию, либо два преобразованных объекта для двух разных процессоров.
  • Затем у вас есть процессор - он получает TransformedDTO, теперь для оптимизации я рассчитал контрольную сумму данных и сравнил ее с контрольной суммой из последнего запуска на основе продукта. Теперь делаю обновление только при необходимости. Если вы вставляете только товары, этот шаг не нужен.
  • Здесь вы можете сделать, чтобы этот процессор просто проверял, изменился ли продукт, если да, вы добавляете обновление в очередь и обрабатываете это другим процессором. Но это всего лишь следующий возможный шаг.

Преимущества этого решения:

  • Добавление нового импорта состоит из простого написания одного трансформатора.
  • У вас может быть некоторая логика кэширования / оптимизации в вашем процессоре (обычно это узкое место, так как он должен выполнять довольно много операций), но поскольку он общий, для этого есть место, и одна оптимизация влияет на все.

Планирование зависит от ваших потребностей - я бы придерживался возможности запускать разные расписания в разное время и проверять, с каким интервалом обновляются источники, и синхронизировать с этим время обновления.

Пример TransformedDTO. Это не что иное, как заполнитель для ваших данных, который работает как ввод для процессоров и как выходные преобразователи.

class Product {
    public $sku;
    public $category;
    public $name;
    // Everything else which your processor know how to process
}

@ m-kebza, что вы имеете в виду под Transformer / TreansformerDTO, не могли бы вы это уточнить?

user8928150 01.06.2018 02:36

DTO - объект передачи данных, это будет всего лишь один общий объект, который будет использоваться как заполнитель для данных. Таким образом, у процессоров есть своего рода интерфейс / контракт, и они знают, что они получат за данные.

M. Kebza 01.06.2018 03:41

@ m-kebza у вас есть пример?

user8928150 01.06.2018 08:55

Добавлен небольшой пример, но остальное в основном зависит от вашей конкретной логики.

M. Kebza 01.06.2018 09:12

@ M-kebza, но этот публичный артикул и т. д. Уже включен в модель сущности продукта, так в чем же разница?

user8928150 02.06.2018 00:02

Идея заключается в том, что ваши процессоры не могут отображать данные о вашей сущности (а информация из источников в любом случае может быть неполной).

M. Kebza 02.06.2018 02:58

@ m-kebza, но у меня уже есть функция удаления обновления вставки в моем сервисе продуктов, которая выполняет функцию сопоставления данных. Я до сих пор не понимаю, что именно вы имеете в виду, не могли бы вы уточнить немного подробнее, чтобы я понял, что вы пытаетесь.

user8928150 02.06.2018 03:13

Идея состоит в том, чтобы разделить отображение данных из разных источников в ваше приложение. Означает, что позже вы можете добавить множество различных сопоставлений без изменения основных функций приложения.

M. Kebza 02.06.2018 04:03

@ M-kebza также включает в себя создание нескольких сопоставителей для каждого дистрибьютора, поскольку каждый дистрибьютор имеет свои собственные правила и набор данных, в некоторых есть xml, некоторые csv и т.д. и т.д. Так что в основном мне нужна логика вне класса сущности, и я поставил ее в службу или преобразователь данных.

user8928150 02.06.2018 10:37

Точно, для каждого дистрибьютора у вас будет средство отображения данных, которое будет создавать, какой вывод будет преобразован в DTO, который вы будете обрабатывать. Итак, в конце концов, ваша сущность не должна знать, как обрабатывать источник данных, потому что это будет логика этого преобразователя / процессора данных.

M. Kebza 02.06.2018 10:44

Другие вопросы по теме