Собираем файлы для передачи в php

Структура массива файлов

var files = [
    {
        file_id  : '[ИД_ФАЙЛА]',
        action   : 'add',
        orig_name: '[ИМЯ_ОРИГИНАЛЬНОГО_ФАЙЛА]'
    }, {
        file_id: '[ИД_ФАЙЛА]',
        action : 'remove'
    }, {
        file_id: '[ИД_ФАЙЛА]',
        action : 'ЧТО_ТО_ИНОЕ'
    }
];
  • file_id (integer|string) - ИД файла, взять из атрибута data-file-id
  • action (string) - Действие совершаемое с файлом, взять из элемента data-file-action
  • orig_name (string) - Имя оригинального файла, взять из элемента <span class="js-name">...</span>

В простом случае это можно сделать так

var files = [];

form.find('.js-files__file').each(function () {
    var elem   = $(this);
    var action = elem.attr('data-file-action');
    var file   = {
        file_id: elem.attr('data-file-id'),
        action : action
    };

    if (action === 'add') {
        file.orig_name = elem.find('.js-name').text();
    }

    files.push(file);
});

Обработка файлов в php

Добавление файла

use Lemurro\Api\Core\Helpers\File\FileAdd;

$container_type = CONTAINER_TYPE;
$container_id = CONTAINER_ID;

$file_id = 123;
$orig_name = 'orig_name.ext';

$file_add = new FileAdd($this->dic);

$result = $file_add->run(
    $file_id,
    $orig_name,
    $container_type,
    $container_id
);
  • CONTAINER_TYPE (string, PascalCase, обязательно) - это тип контейнера (куда был прикреплён файл), лучше всего использовать название раздела (например: Example), далее это слово будет использоваться для подключения класса проверки прав доступа /app/Checker/FileExample.php
  • CONTAINER_ID (integer, не обязательно) - ИД вашей записи в БД куда был прикреплён загруженный файл, чтобы потом использовать при проверке прав доступа

* Если вы не хотите выполнять проверку прав доступа, тогда укажите CONTAINER_TYPE = 'Default' и CONTAINER_ID = null

Удаление файла

use Lemurro\Api\Core\Helpers\File\FileRemove;

$file_id = 123;

$file_remove = new FileRemove($this->dic);
$result = $file_remove->run($file_id);

Вот пример возможной реализации обработки

use Lemurro\Api\Core\Helpers\File\FileAdd;
use Lemurro\Api\Core\Helpers\File\FileRemove;

$container_type = CONTAINER_TYPE;
$container_id = CONTAINER_ID;

$file_add = new FileAdd($this->dic);
$file_remove = new FileRemove($this->dic);

$files_ids = [];
$files_errors = [];

if (isset($data['files']) && is_array($data['files'])) {
    foreach ($data['files'] as $file) {
        switch ($file['action']) {
            case 'add':
                $result = $file_add->run(
                    $file['file_id'],
                    $file['orig_name'],
                    $container_type,
                    $container_id
                );

                if (isset($result['errors'])) {
                    $files_errors[] = array_merge($file, $result);
                } else {
                    $files_ids[] = $result['data']['id'];
                }
                break;

            case 'remove':
                $result = $file_remove->run($file['file_id']);

                if (isset($result['errors'])) {
                    $files_ids[] = $file['file_id'];
                    $files_errors[] = array_merge($file, $result);
                }
                break;

            default:
                $files_ids[] = $file['file_id'];
                break;
        }
    }
}

В результате вы получите 2 массива данных

  • $files_ids - Массив ИД файлов: новых и старых
  • $files_errors - Массив ошибок добавления \ удаления файлов

Или можно воспользоваться фасадом

use Lemurro\Api\Core\Helpers\File\FileManipulate;

$container_type = CONTAINER_TYPE;
$container_id = CONTAINER_ID;

$manipulate = (new FileManipulate($this->dic))->run(
    $data['files'],
    $container_type,
    $container_id
);

В результате вы получите 2 массива данных

  • $manipulate['ids'] - Массив ИД файлов: новых и старых
  • $manipulate['errors'] - Массив ошибок добавления \ удаления файлов
  • $manipulate['class_file_add'] - Экземпляр класса FileAdd, для возможности выполнить метод undo

Что-то пошло не так?

Если вы уже загрузили файлы в постоянное хранилище, а дальше в вашем коде произошла ошибка, тогда вам необходимо воспользоваться методом undo класса FileAdd:

use Lemurro\Api\Core\Helpers\File\FileAdd;

$file_add = new FileAdd($this->dic);

// Здесь вы загрузили все файлы

// Здесь в вашем коде случилась ошибка

// Выполним метод undo, чтобы вернуть файлы обратно
$file_add->undo();

или так, если вы используете фасад FileManipulate:

use Lemurro\Api\Core\Helpers\File\FileAdd;
use Lemurro\Api\Core\Helpers\File\FileManipulate;

$container_type = CONTAINER_TYPE;
$container_id = CONTAINER_ID;

// Здесь вы загрузили все файлы
$manipulate = (new FileManipulate($this->dic))->run(
    $data['files'],
    $container_type,
    $container_id
);

if (!empty($manipulate['ids'])) {
    // Здесь в вашем коде случилась ошибка

    /* @var FileAdd $class_file_add */
    $class_file_add = $manipulate['class_file_add'];

    // Выполним метод undo, чтобы вернуть файлы обратно
    $class_file_add->undo();
}

* Метод undo вернёт все загруженные файлы обратно во временное хранилище, а также удалит их упоминания в таблице files

* Настоятельно рекомендуется манипуляции с файлами и вашим кодом завернуть в транзакцию, чтобы при ошибках и откате всё вернулось обратно