Как можно устранить ошибку, связанную с базой данных?

Здравствуйте! Я разрабатываю админку, и передо мной стоит задача загрузки большого количества фотографий. Загружаемые изображения сохраняются в корневой директории сайта, но пути к этим изображениям необходимо отправить в базу данных. В настоящее время в базу данных попадает массив, вместо ожидаемой строки. Как мне исправить этот момент? 

Вот пример кода, с которым я работаю:

<pre><code class="php">$uploaddir = "../uploads-gallery";

foreach ($_FILES["images"]["error"] as $key =&gt; $error) {
    if ($error == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES["images"]["tmp_name"][$key];

        // Функция basename() помогает защититься от атак на файловую систему;
        // иногда требуется дополнительная проверка или очистка имени файла
        $name = basename($_FILES["images"]["name"][$key]);
        move_uploaded_file($tmp_name, "$uploaddir/$name");
    }
};

$images = $_FILES["images"]["name"];</code></pre>
  • 10 октября 2024 г. 20:14
Ответы на вопрос 4
Проблема, с которой вы сталкиваетесь, заключается в том, что переменная `$images`, на которую ссылаются после выполнения цикла, содержит массив имен загруженных файлов. Чтобы сохранить пути к изображениям в базе данных, вам нужно преобразовать этот массив в строку.

Вот, как вы можете модифицировать ваш код, чтобы исправить это:

1. Создать новый массив для хранения полных путей к загруженным изображениям.
2. После загрузки каждого изображения добавлять его путь в этот массив.
3. После завершения цикла преобразовать массив в строку (например, с использованием функции `implode()`) для сохранения в базе данных.

Вот пример модифицированного кода:

```php
$uploaddir = "../uploads-gallery";
$imagePaths = []; // Массив для хранения путей к загруженным файлам

foreach ($_FILES["images"]["error"] as $key => $error) {
    if ($error == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES["images"]["tmp_name"][$key];
        $name = basename($_FILES["images"]["name"][$key]);
        
        if (move_uploaded_file($tmp_name, "$uploaddir/$name")) {
            // Добавляем путь к загруженному изображению в массив
            $imagePaths[] = "$uploaddir/$name";
        }
    }
}

// Преобразуем массив путей в строку, разделенную запятыми
$imagePathsString = implode(',', $imagePaths);

// Теперь $imagePathsString можно сохранить в базу данных
```

### Замечания:
- Убедитесь, что путь к директории для загрузки существует и у PHP есть права на запись в эту директорию.
- Рекомендуется дополнительно проверять имя файла и файл перед его загрузкой (например, вы можете проверять расширение файла, размер файла и тип содержания).
- Если ваши изображения могут быть загружены с одинаковыми именами, стоит добавить уникальное идентификатор к имени файла, чтобы избежать перезаписи.
- После получения `$imagePathsString` вы можете использовать его в SQL-запросе для сохранения пути к изображениям в базе данных.
Смотрите, в переменной $images = $_FILES["images"]["name"]; находится массив. 
А поле в таблице у вас имеет формат text.
PHP - не волшебник, он не понимает, в каком именно формате вам нужно запихнуть данные в это поле, и он пытается, как может, и пишет в дефолтном формате.

Преобразование внутренних типов языка программирования в строки либо в те типы, которые понимает база данных, называется сериализацией. Т.е. нам надо PHP-шный массив преобразовать в тот формат в котором это поле в базе.

Это можно сделать при помощи стандартной функции php serialize .

$images = $_FILES["images"]["name"];
$imagesSerialized = serialize($images); 


А когда вытащите содержимое из базы, то нужно будет использовать функцию unserialize

Правда само содержимое в поле будет в специальном формате, и его будет трудно понимать, если будете своими глазами смотреть базу. Чтобы сделать это поле в базе более читаемым, ежели это вам надо, можно пойти двумя путями:

1. Вместо serialize - unserialize использовать json_encode и json_decode . Тогда в базе текст будет в джесончике, и его проще будет смотреть в базе.

2. Можно сделать еще лучше, и сделать само поле в базе в формате JSON (В MySQL и Postgres это точно есть.). И тогда можно будет использовать json_encode и json_decode .
Чем это отличается от п.1? Тем, что можно будет использовать поля из такого объекта в запросах. Искать, менять и т.д.
Очевидно, что поле формы с множественной загрузкой файлов выдает массив, чтобы записать значения в базу надо всё-же : 
$uploaddir = "../uploads-gallery";

foreach ($_FILES["images"]["error"] as $key => $error) {
    if ($error == UPLOAD_ERR_OK) {
        $tmp_name = $_FILES["images"]["tmp_name"][$key];

        // Функция basename() помогает защититься от атак на файловую систему;
        // иногда требуется дополнительная проверка или очистка имени файла
        $name = basename($_FILES["images"]["name"][$key]);
        move_uploaded_file($tmp_name, "$uploaddir/$name");
        ... функция записи в таблицу имени файла ($_FILES["images"]["name"][$key]);
    }
};
Представим, что проблему сохранения вы как-то решили... А что вы намерены делать с сохранённым значением? 

Вариант 1 - всегда только извлекать весь массив целиком, в том виде, в каком он сохранялся. Никаких извлечений части массива, никаких по нему поисков, сортировок и прочего. Тогда преобразуйте массив во вменяемый сериализованный формат и сохраняйте в поле БД. Виктор Кожухарь в своём ответе разобрал этот вариант.

Вариант 2 - возможна какая-то обработка. Извлечение части массива по какому-то критерию (порядковый номер, соответствие шаблону и пр.), поиск в массиве по заданному критерию, сортировка самого массива либо массивов по какому-то критерию.. Тогда однозначно делите массив на отдельные элементы и сохраняйте их по одному (конечно, соответствующим образом должна измениться структура БД). Делить можно и на стороне PHP (как показывает Евгений в своём ответе), и в запросе на запись на стороне MySQL. Первое, как я понимаю, вам проще сделать, но правильно - второй вариант.
Похожие вопросы