Как вставить массив в столбец базы данных, который имеет строковый тип?

У меня есть несколько флажков в моей форме, и когда я выбираю некоторые из них и отправляю форму, я получаю сообщение об ошибке «Преобразование массива в строку». Мой столбец базы данных user_preferences имеет тип строки, поэтому это причина ошибки. Я просто не знаю, как вставить несколько значений в этот столбец. Любая помощь приветствуется. Вот мой код.

UserController.php

public function update(StoreUserInfo $request, User $user)
{
    //return $request->userPreferences;
    if ( !($user->id == Auth::user()->id)) {
        abort(404);
    }

    $request->validated();

    $user->where('id', $user->id)->update(
        [
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'email' => $request->email,
            'city' => $request->city,
            'type' => $request->type,
            'user_preferences' => $request->userPreferences,
            'updated_at' =>  Carbon::now()
        ]
    );
        return redirect()->back()->with('message', 'User information updated');
}

edit.blade.php

<div class = "row page-hero d-flex align-items-center justify-content-center">
    <label for = "preferences" class = "text-center">Select your preferences</label>         
</div>
<div class = "row">                
    <div class = "col-md-1" style = "margin-right:15px; margin-left:60px;">
        <div class = "custom-control custom-checkbox">
            <input id = "kuca" name = "userPreferences[]" value = "kuca" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "kuca">Kuca</label>
        </div>
    </div>
    <div class = "col-md-1" style = "margin-right:15px;">
        <div class = "custom-control custom-checkbox">
            <input id = "stan" name = "userPreferences[]" value = "stan" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "stan">Stan</label>
        </div>
    </div>
    <div class = "col-md-1" style = "margin-right:50px;">
        <div class = "custom-control custom-checkbox">
            <input id = "apartman" name = "userPreferences[]" value = "apartman" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "apartman">Apartman</label>
        </div>
    </div>
    <div class = "col-md-1" style = "margin-right:15px;">
        <div class = "custom-control custom-checkbox">
            <input id = "soba" name = "userPreferences[]" value = "soba" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "soba">Soba</label>
        </div>
    </div>
    <div class = "col-md-1" style = "margin-right:15px;">
        <div class = "custom-control custom-checkbox">
            <input id = "lokal" name = "userPreferences[]" value = "lokal" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "lokal">Lokal</label>
        </div>
    </div>
    <div class = "col-md-1" style = "margin-right:15px;">
        <div class = "custom-control custom-checkbox">
            <input id = "plac" name = "userPreferences[]" value = "plac" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "plac">Plac</label>
        </div>
    </div>
    <div class = "col-md-1" style = "margin-right:15px;">
        <div class = "custom-control custom-checkbox">
            <input id = "garaza" name = "userPreferences[]" value = "garaza" type = "checkbox" class = "custom-control-input">
            <label class = "custom-control-label" for = "garaza">Garaza</label>
        </div>
    </div>           
</div>

Вы можете сериализовать значения. Или вы можете сделать реляционное сопоставление 2 таблиц в mysql. Либо работает.

Andrei 24.07.2019 12:43

Вы можете использовать функцию сериализации php для хранения в виде строки, а затем десериализовать значение при получении... или вы также можете использовать json_encode для хранения, а затем json_decode значения при получении.... но я хотел бы предложить вам сохранить множественное значение в отдельной таблице

Rajat Sharma 24.07.2019 12:50
Стоит ли изучать 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 и хотите разрабатывать...
2
2
109
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Использовать json_encode

Вы можете кодировать в своем запросе на обновление или указать поле в модели.

Вы можете использовать свойство $casts (https://laravel.com/docs/5.8/eloquent-mutators#array-and-json-casting):

class User extends Model
{

    protected $casts = [
        'user_preferences' => 'array',
    ];
}

Делая это, Laravel автоматически сериализует массив в JSON и наоборот.

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

Вы можете использовать функцию php implode() для объединения массива строк в одну строку следующим образом:

$user->where('id', $user->id)->update(
    [
        'first_name' => $request->first_name,
        'last_name' => $request->last_name,
        'email' => $request->email,
        'city' => $request->city,
        'type' => $request->type,
        'user_preferences' => implode(',', $request->userPreferences),
        'updated_at' =>  Carbon::now()
    ]
);

https://php.net/имплоде

Затем, когда вы отображаете значения в своем show.blade.php, вы можете использовать $userPreferences = explode(',', $row->userPreferences);, чтобы вернуть массив.

https://php.net/взрыв

Это работает, но знайте, что когда я пытаюсь изменить first_name, чтобы обновить его, я получаю эту ошибку «implode (): переданы недопустимые аргументы». Вы можете помочь?

mrmar 24.07.2019 16:16

ну, вы должны обновить свое представление, чтобы восстановить выбранные значения, чтобы при редактировании имени вы повторно отправляли ранее выбранные значения обратно.

Latheesan 24.07.2019 17:00

Я не уверен, что знаю, как это сделать. Вы можете немного помочь?

mrmar 25.07.2019 08:53

Вы можете разделить значение запятой (,) и сохранить строку.

Например.

$preferences = implode(',',$request->userPreferences);
$user->where('id', $user->id)->update(
    [
        'first_name' => $request->first_name,
        'last_name' => $request->last_name,
        'email' => $request->email,
        'city' => $request->city,
        'type' => $request->type,
        'user_preferences' => $preferences,
        'updated_at' =>  Carbon::now()
    ]
);

Я думаю, что самое простое решение - сохранить ваше значение в JSON. Есть функция php, которая позволяет кодировать и декодировать объекты и массивы в JSON, а именно json_encode и json_decode соответственно.

В вашем случае вы можете просто изменить оператор обновления на:

$user->where('id', $user->id)->update(
        [
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'email' => $request->email,
            'city' => $request->city,
            'type' => $request->type,
            'user_preferences' => json_encode($request->userPreferences),
            'updated_at' =>  Carbon::now()
        ]
    );

Когда вы получаете данные из модели, вам нужно декодировать строку обратно в массив. Вы можете сделать это следующим образом:

$user = User::find($user->id);
if ($user) {
    $preferences = json_decode($user->user_preferences);
}

Как указано в других ответах, Laravel может автоматизировать это для вас с помощью Кастинг массивов и JSON.

Если я это сделаю, это сработает, но когда я обновлю, например, позже, просто first_name, мои значения в user_preferences станут нулевыми. Как я могу это решить?

mrmar 25.07.2019 08:59

Вы можете использовать функцию json_encode при вставке данных в базу данных.

После этого вы можете ввести cast в Users Model, чтобы получить нормальный массив при выборке записей. Добавьте следующую функцию в модель пользователя.

public funtion getUserPreferencesAttribute()
{
     return json_decode($this->attributes['user_preferences']);
}

Если я это сделаю, это сработает, но когда я обновлю, например, позже, просто first_name, мои значения в user_preferences станут нулевыми. Как я могу это решить?

mrmar 25.07.2019 09:11

@Marko Если вы не отправите настройки, они будут нулевыми. вы должны добавить эти настройки при обновлении

Sagar Gautam 25.07.2019 09:15

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

mrmar 25.07.2019 09:18

@Marko Тогда вам нужно условное обновление. Если в запросе есть userPreferences, обновите столбец настроек, в противном случае не обновляйте этот.

Sagar Gautam 25.07.2019 09:24

Я успешно сохранился в базе данных. У меня проблемы с их проверкой. Как я должен писать, что в виду. У меня есть что-то подобное, но не работает. value = "{{ old('user_preferences', $user->user_preferences) }}" . В нем говорится, что «htmlspecialchars() ожидает, что параметр 1 будет строкой, массив задан»

mrmar 25.07.2019 09:51

@Marko, это не столбец с одним значением, он содержит массив значений настроек, поэтому вам нужно перебрать его и проверить лезвие.

Sagar Gautam 25.07.2019 09:54

Если вы используете Laravel и более позднюю версию MySQL, вам может быть лучше создать тип поля JSON и привести его к массиву в вашей красноречивой модели.

Затем Laravel автоматически закодирует и декодирует поле для вас.

Это также будет означать, что вы можете запросить поле, используя model::where('preference->type', 'thing').

Возможно, это можно сделать со строковым типом поля, но я не уверен в этом на 100%, но это будет работать с JSON.

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