Проблема с целыми числами, передающими данные из Vue в Laravel с использованием FormData

Я успешно обновляю базу данных с помощью Vue 2 до контроллера Laravel 8 с помощью Axios. Однако я застрял при попытке передать целое число в мою базу данных.

В моей базе данных есть столбец number_of_searches, и он должен быть целым числом.

Laravel Migration выглядит так:

$table->integer('number_of_searches')->nullable();

Модель выглядит примерно так:

class Product extends Model
{
    protected $fillable = [
        'product_title', 
        'number_of_searches' => 'integer',
    ];
}

Моя функция Vue updateProduct () использует FormData и добавляет значения, поступающие из формы. Это выглядит так:

updateProduct(product){
   let data = new FormData();
   data.append('_method', 'PATCH');
   data.append('product_title', product.product_title);
   data.append('number_of_searches', product.number_of_searches);
   axios.post('/api-route-to-update/product_id/', data)
   .then(function (response) {
      console.log(response);
      })
   .catch(function (error) {
      console.log(error);            
       });
}

Мой контроллер обновлений выглядит так:

public function update(Request $request, $product_id){
   $product = Product::findOrFail($product_id);
   $product->update($request->all());
   $product->save();
}

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

<input v-model="product.number_of_searches" type="number" min="1" max="999">

Сгенерированный json, который перейдет из axios в мой контроллер, выглядит так:

{ "id": 5, "product_title": "The Product Title will work great", "number_of_searches": "222"}

Вы заметите, что 'number_of_searches' передается как строка, поэтому моя база данных не работает, потому что это неправильный тип данных, для этого требуется целое число. После прочтения документации и других потоков кажется, что FormData всегда будет возвращать строки, и что я должен просто иметь дело с этим на стороне сервера.

Итак, что я сделал, я вошел в свой внутренний метод updateProduct () и попытался изменить запрос.

Сначала я попробовал несколько таких методов, как:

//this one
$requestData = $request->all();
$requestData['number_of_searches'] = 123;

//also this one
$request->merge(['number_of_searches' => 123]);

//and this
$data = $request->all();
$data['number_of_searches'] = 123;

Спустя бесчисленное количество часов я не могу изменить исходный запрос. После некоторых исследований выяснилось, что запросы защищены и не могут быть изменены, что имеет смысл. Поэтому я попытался создать новый запрос, который клонирует $ request- ›all (), например:

$new_request = new Request($request->all());
$new_request->merge(['number_of_searches' => 123]);

Но мне не удалось принудительно переопределить "number_of_searched"

У меня вопрос:

Должен ли я полностью отказаться от FormData в этом случае? Какой метод вы предлагаете для передачи форм с целыми числами, числами с плавающей запятой или другими типами данных через аксиомы или выборку? Или что я не так делаю? Мне трудно поверить, что FormData будет отправлять только строки (что делает parseInt бесполезным перед использованием axios). Я уверен, что делаю что-то не так с самого начала.

С другой стороны, возможно, мне нужно полностью изменить свой подход к контроллеру при получении данных. Я работаю над приложением с большим количеством полей, и мне нравится $ request- ›all (), потому что оно упрощает то, что я пытаюсь сделать. Я бы не отказался использовать intval на стороне сервера, и все, но это кажется слишком сложным.


person toolnin    schedule 31.10.2020    source источник


Ответы (1)


На стороне Vue вы можете использовать модификатор number для v-model, чтобы убедиться, что он не преобразует значение в строку:

v-model.number="product.number_of_searches"

На стороне запроса вы можете использовать $request->merge, чтобы переопределить значение в запросе.

$request->merge([
  'number_of_searches' => (int) $request->get('number_of_searches');
]);

На стороне модели в хуке updating в методе boot вы можете гарантировать, что значение будет преобразовано как int при сохранении:

static::updating(function ($model) {
    $model->number_of_searches = (int) $model->number_of_searches;
});

Это должно дать вам конец до конца.

person Ohgodwhy    schedule 31.10.2020
comment
Ваш код определенно приблизил меня. База данных теперь обновляет столбец number_of_searches, однако каждый раз сохраняет 0. Я считаю, что слияния все еще не происходит. Две вещи успешны: v-model.number теперь возвращает json с целым числом, а не строкой, что именно то, что мне нужно (при попытке этой вставки без остальной части вашего кода база данных по-прежнему имеет значение Null). Если я использую загружаемый метод без обновления контроллера (слияния), он все равно вставляет 0. Кажется, что загруженный метод устанавливает нулевое значение по умолчанию, поэтому я уверен, что слияние является проблемой. - person toolnin; 31.10.2020
comment
Я понял это. Я полностью отказался от слияния на контроллере. Я использовал предложенный вами метод с ботами, а также обновил ввод до v-model.number. Другая проблема, которую мне нужно было исправить, заключается в том, что в модели продукта я изменил number_of_searches = ›integer на number_of_searches. Интересно, почему это целочисленное объявление внутри $ fillable может вызвать проблему, когда JSON уже отправляет целое число. Большое спасибо за то, что помог мне разобраться в этом! - person toolnin; 31.10.2020