如何通过应用程序中的表单为用户创建配置文件?我正在使用 laravel 8
How can I create a profile for a user through a form in my application? I am using laravel 8
大家好,我是 Laravel 的新手。
我的数据库中有一个用户,有姓名、用户名和密码,现在我想通过我的应用程序中的表单为该用户创建一个配置文件,用户可以在其中提交配置文件图像、描述和 url.我还希望用户能够在之后编辑和提交更改。我该怎么做?
我在 web.php 的路线是:
Route::get('/users/{user}/edit', [UserController::class, 'edit']);
Route::patch('/users/{user}', [UserController::class, 'update']);
我在edit.blade.php文件中的表格如下:
<form action="/users/{{ $user->id }}" enctype="multipart/form-data" method="post">
@csrf
@method('PATCH')
<div class="form-group">
<label for="description" class="edit_description_label">Description</label>
<div class="edit_description_div">
<input id="description"
type="text"
class="form-control @error('description') is-invalid @enderror"
name="description"
value="{{ old('description') ?? $user->profile->description ?? '' }}"
autocomplete="description" autofocus>
@error('description')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="form-group">
<label for="url" class="edit_title_label">URL</label>
<div class="edit_url_div">
<input id="url"
type="text"
class="form-control @error('url') is-invalid @enderror"
name="url"
value="{{ $user->profile->url ?? '' }}"
autocomplete="url" autofocus>
@error('url')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="create_post_image_div">
<label for="image" class="create_image_label">Profile Image</label>
<input type="file" class="form-control-file" id="image" name="image">
@error('image')
<div class="invalid-feedback-div">
<strong>{{ $message }}</strong>
</div>
@enderror
<div class="create_post_btn_div">
<button class="create_post_btn">Save Profile</button>
</div>
</div>
</form>
最后,我在 UserController 中的方法是:
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}
public function edit(User $user)
{
return view('user.edit', ['user' => $user]);
}
public function update(Request $request, User $user)
{
$data = request()->validate([
'description' => '',
'url' => '',
'image' => '',
]);
$user->profile->update($data);
return redirect('/users/{$user->id}');
}
为了提供更好的上下文,配置文件描述、url 和图像列不在我的用户模型中,而是在我的配置文件模型中。我已经定义了这些关系,以便更好地理解以下文件的代码:
这是我的 User.php 文件中的代码:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'username',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
}
这是用户 Table 文件:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('username')->unique();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
这是 Profile.php 文件:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
use HasFactory;
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
这是配置文件 Table 文件:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('description')->nullable();
$table->string('url')->nullable();
$table->string('image')->nullable();
$table->timestamps();
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('profiles');
}
}
您需要验证传入的 $request
对象,请尝试将控制器的更新函数代码更改为:
public function update(Request $request, User $user)
{
$data = $request->validate([
'description' => '',
'url' => '',
'image' => '',
]);
$user->profile->update($data);
return redirect('/users/{$user->id}');
}
看看文档,它们很有帮助:https://laravel.com/docs/8.x/validation#quick-writing-the-validation-logic
The save
method may also be used to update models that already exist
in the database. To update a model, you should retrieve it and set any
attributes you wish to update. Then, you should call the model's
save
method.
use App\Models\Profile;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
public function updateProfile($user)
{
$data = request()->validate($this->validationBag());
$profile = Profile::where('user_id', $user)->first();
if (isset($data['image'])) {
$this->updateProfileImage($data['image'], $profile);
}
$profile->description = $data['description'];
$profile->url = $data['url'];
$profile->save();
return redirect("/users/$user");
}
public function createProfile($user)
{
$data = request()->validate($this->validationBag());
$profile = Profile::create([
'user_id' => $user,
'description' => $data['description'],
'url' => $data['url'],
]);
if (isset($data['image'])) {
$this->updateProfileImage($data['image'], $profile);
}
return redirect("/users/$user");
}
private function updateProfileImage(UploadedFile $image, Profile $profile) {
tap($profile->image, function ($previous) use ($image, $profile) {
$profile->forceFill([
'image' => $image->storePublicly(
'profile-photos', ['disk' => 'public']
),
])->save();
if ($previous) {
Storage::disk('public')->delete($previous);
}
});
}
private function validationBag()
{
return [
'description' => '',
'url' => '',
'image' => '',
];
}
假定路线。
Route::put('/users/{user}/profile', [UserController::class, 'updateProfile'])->name('update.user.profile');
Route::post('/users/{user}/profile', [UserController::class, 'createProfile']);
Route::get('/users/{user}', [UserController::class, 'index']);
将您的 <form>
action
属性编辑为:
<form action="{{'/users/'. $user->id. '/profile'}}" enctype="multipart/form-data" method="post">
希望您在 routes/web.php
文件中定义了这条路线 /users/{$user}
。
给App\Models\Profile
增加一个$fillable
成员变量model.i.e:
protected $fillable = ["user_id", "description", "url", "image"];
与问题没有太大关系,但您可能还想向 CreateProfilesTable
迁移添加外键约束。即:
$table->foreignId("user_id")->constrained();
由于是一对一的关系,在'profiles table '(CreateProfilesTable
迁移)的user_id
列上添加唯一键约束也是有意义的。即:
$table->string('user_id')->unique();
$data = $this->validate($request, [
'description' => 'nullable',
'url' => 'required',
'image' => 'nullable',
]);
$user->description= $data['description'];
$user->url= $data['url'];
$user->image= $data['image'];
$user->save();
大家好,我是 Laravel 的新手。
我的数据库中有一个用户,有姓名、用户名和密码,现在我想通过我的应用程序中的表单为该用户创建一个配置文件,用户可以在其中提交配置文件图像、描述和 url.我还希望用户能够在之后编辑和提交更改。我该怎么做?
我在 web.php 的路线是:
Route::get('/users/{user}/edit', [UserController::class, 'edit']);
Route::patch('/users/{user}', [UserController::class, 'update']);
我在edit.blade.php文件中的表格如下:
<form action="/users/{{ $user->id }}" enctype="multipart/form-data" method="post">
@csrf
@method('PATCH')
<div class="form-group">
<label for="description" class="edit_description_label">Description</label>
<div class="edit_description_div">
<input id="description"
type="text"
class="form-control @error('description') is-invalid @enderror"
name="description"
value="{{ old('description') ?? $user->profile->description ?? '' }}"
autocomplete="description" autofocus>
@error('description')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="form-group">
<label for="url" class="edit_title_label">URL</label>
<div class="edit_url_div">
<input id="url"
type="text"
class="form-control @error('url') is-invalid @enderror"
name="url"
value="{{ $user->profile->url ?? '' }}"
autocomplete="url" autofocus>
@error('url')
<div class="invalid-feedback-div">
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
</div>
@enderror
</div>
</div>
<div class="create_post_image_div">
<label for="image" class="create_image_label">Profile Image</label>
<input type="file" class="form-control-file" id="image" name="image">
@error('image')
<div class="invalid-feedback-div">
<strong>{{ $message }}</strong>
</div>
@enderror
<div class="create_post_btn_div">
<button class="create_post_btn">Save Profile</button>
</div>
</div>
</form>
最后,我在 UserController 中的方法是:
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}
public function edit(User $user)
{
return view('user.edit', ['user' => $user]);
}
public function update(Request $request, User $user)
{
$data = request()->validate([
'description' => '',
'url' => '',
'image' => '',
]);
$user->profile->update($data);
return redirect('/users/{$user->id}');
}
为了提供更好的上下文,配置文件描述、url 和图像列不在我的用户模型中,而是在我的配置文件模型中。我已经定义了这些关系,以便更好地理解以下文件的代码:
这是我的 User.php 文件中的代码:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'username',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
}
这是用户 Table 文件:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('username')->unique();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
这是 Profile.php 文件:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
use HasFactory;
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
这是配置文件 Table 文件:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('description')->nullable();
$table->string('url')->nullable();
$table->string('image')->nullable();
$table->timestamps();
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('profiles');
}
}
您需要验证传入的 $request
对象,请尝试将控制器的更新函数代码更改为:
public function update(Request $request, User $user)
{
$data = $request->validate([
'description' => '',
'url' => '',
'image' => '',
]);
$user->profile->update($data);
return redirect('/users/{$user->id}');
}
看看文档,它们很有帮助:https://laravel.com/docs/8.x/validation#quick-writing-the-validation-logic
The
save
method may also be used to update models that already exist in the database. To update a model, you should retrieve it and set any attributes you wish to update. Then, you should call the model'ssave
method.
use App\Models\Profile;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
public function updateProfile($user)
{
$data = request()->validate($this->validationBag());
$profile = Profile::where('user_id', $user)->first();
if (isset($data['image'])) {
$this->updateProfileImage($data['image'], $profile);
}
$profile->description = $data['description'];
$profile->url = $data['url'];
$profile->save();
return redirect("/users/$user");
}
public function createProfile($user)
{
$data = request()->validate($this->validationBag());
$profile = Profile::create([
'user_id' => $user,
'description' => $data['description'],
'url' => $data['url'],
]);
if (isset($data['image'])) {
$this->updateProfileImage($data['image'], $profile);
}
return redirect("/users/$user");
}
private function updateProfileImage(UploadedFile $image, Profile $profile) {
tap($profile->image, function ($previous) use ($image, $profile) {
$profile->forceFill([
'image' => $image->storePublicly(
'profile-photos', ['disk' => 'public']
),
])->save();
if ($previous) {
Storage::disk('public')->delete($previous);
}
});
}
private function validationBag()
{
return [
'description' => '',
'url' => '',
'image' => '',
];
}
假定路线。
Route::put('/users/{user}/profile', [UserController::class, 'updateProfile'])->name('update.user.profile');
Route::post('/users/{user}/profile', [UserController::class, 'createProfile']);
Route::get('/users/{user}', [UserController::class, 'index']);
将您的 <form>
action
属性编辑为:
<form action="{{'/users/'. $user->id. '/profile'}}" enctype="multipart/form-data" method="post">
希望您在 routes/web.php
文件中定义了这条路线 /users/{$user}
。
给App\Models\Profile
增加一个$fillable
成员变量model.i.e:
protected $fillable = ["user_id", "description", "url", "image"];
与问题没有太大关系,但您可能还想向 CreateProfilesTable
迁移添加外键约束。即:
$table->foreignId("user_id")->constrained();
由于是一对一的关系,在'profiles table '(CreateProfilesTable
迁移)的user_id
列上添加唯一键约束也是有意义的。即:
$table->string('user_id')->unique();
$data = $this->validate($request, [
'description' => 'nullable',
'url' => 'required',
'image' => 'nullable',
]);
$user->description= $data['description'];
$user->url= $data['url'];
$user->image= $data['image'];
$user->save();