我正在做一个简单的大学项目,一个电影目录,但我遇到了一个无法找到解决方案的问题。当尝试更新电影时,我收到 422 错误,我无法找出问题所在。我使用 Laravel 10 创建了我的 API,我与您分享我的控制器,特别是更新方法,因为这是我收到错误的地方,以及我的路线:
影片控制器.php
public function updateMovie(Request $request, $id)
{
Log::info('Request data:', $request->all());
Log::info('Request files:', $request->file());
if (!$request->has('title')) {
Log::error('Title is missing');
}
if (!$request->has('synopsis')) {
Log::error('Synopsis is missing');
}
if (!$request->has('year')) {
Log::error('Year is missing');
}
$validatedData = $request->validate([
'title' => 'required|string|max:255',
'synopsis' => 'required|string',
'year' => 'required|integer|min:1900|max:' . date('Y'),
'cover' => 'nullable|file|mimes:jpeg,png,jpg,gif|max:2048',
]);
api.php
Route::put('/movies/{id}', [MovieController::class, 'updateMovie']);
我认为问题不在于我的 API,而在于我的客户端。我使用 Angular 16 作为前端。现在,我将向您展示我的编辑组件和我服务的配置:
电影.编辑.组件.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MovieService } from '../../services/movie.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-movie-edit',
templateUrl: './movie-edit.component.html',
styleUrls: ['./movie-edit.component.scss']
})
export class MovieEditComponent implements OnInit {
movieForm: FormGroup;
movieId!: number;
movie: any;
constructor(
private route: ActivatedRoute,
private router: Router,
private movieService: MovieService,
private fb: FormBuilder
) {
this.movieForm = this.fb.group({
title: ['', Validators.required],
synopsis: ['', Validators.required],
year: ['', [Validators.required, Validators.min(1900), Validators.max(new Date().getFullYear())]],
cover: [null]
});
}
ngOnInit(): void {
this.movieId = Number(this.route.snapshot.paramMap.get('id'));
this.getMovieDetails();
}
getMovieDetails(): void {
this.movieService.getMovieById(this.movieId).subscribe({
next: (data) => {
this.movie = data;
this.movieForm.patchValue({
title: this.movie.title,
synopsis: this.movie.synopsis,
year: this.movie.year
});
},
error: (error) => {
console.error('Error fetching movie details', error);
}
});
}
onFileChange(event: any): void {
if (event.target.files.length > 0) {
const file = event.target.files[0];
this.movieForm.patchValue({
cover: file
});
}
}
onSubmit(): void {
if (this.movieForm.valid) {
const formData = new FormData();
const title = this.movieForm.get('title')?.value || '';
const synopsis = this.movieForm.get('synopsis')?.value || '';
const year = this.movieForm.get('year')?.value;
const cover = this.movieForm.get('cover')?.value;
console.log('Title:', title);
console.log('Synopsis:', synopsis);
console.log('Year:', year);
console.log('Cover:', cover);
formData.append('title', title);
formData.append('synopsis', synopsis);
if (year !== undefined && year !== null) {
formData.append('year', year.toString());
}
if (cover) {
formData.append('cover', cover);
}
formData.forEach((value, key) => {
console.log(key, value);
});
this.movieService.updateMovie(this.movieId, formData).subscribe({
next: () => {
this.router.navigate(['/movie', this.movieId]);
},
error: (error) => {
console.error('Error updating movie', error);
}
});
}
}
}
电影.服务.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class MovieService {
private apiUrl = 'http://localhost:8000/api/movies';
constructor(private http: HttpClient) {}
getAllMovies(): Observable<any> {
return this.http.get(this.apiUrl);
}
getMovieById(id: number): Observable<any> {
return this.http.get(`${this.apiUrl}/${id}`);
}
createMovie(movie: any): Observable<any> {
const formData = new FormData();
formData.append('title', movie.title);
formData.append('synopsis', movie.synopsis);
formData.append('year', movie.year.toString());
formData.append('cover', movie.cover);
return this.http.post(this.apiUrl, formData);
}
updateMovie(id: number, formData: FormData): Observable<any> {
return this.http.put(`${this.apiUrl}/${id}`, formData);
}
deleteMovie(id: number): Observable<any> {
return this.http.delete(`${this.apiUrl}/${id}`);
}
}
看起来数据没有到达后端;FormData 从 Angular 发送的方式似乎存在问题。
这是日志文件中显示的内容:
[2024-10-08 00:33:17] local.INFO: Request data:
[2024-10-08 00:33:17] local.INFO: Request files:
[2024-10-08 00:33:17] local.ERROR: Title is missing
[2024-10-08 00:33:17] local.ERROR: Synopsis is missing
[2024-10-08 00:33:17] local.ERROR: Year is missing
请帮忙,我需要在两周内提交这项活动。
您可以尝试
POST
使用带有参数的方法_method="PUT"
,因为提交时 PHP 无法multipar-form-data
正确识别使用该PUT
方法上传文件。因此,将您的提交表单方法更改为
POST
并添加由于您正在使用
FormData
,我认为您需要Content-Type
为POST
和PUT
请求设置标题。为了将来进行调试,您可以将变量输出到日志文件中。
请使用 Json 数据从 angular 提交数据,而不是 formData... { "year": document.getElementByID(" year"), .... .... } 像这样