如何通过应用程序中的表单为用户创建个人资料?我正在使用 laravel 8

Posted

技术标签:

【中文标题】如何通过应用程序中的表单为用户创建个人资料?我正在使用 laravel 8【英文标题】:How can I create a profile for a user through a form in my application? I am using laravel 8 【发布时间】:2021-06-05 16:43:09 【问题描述】:

大家好,我是 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');

为了提供更好的上下文,个人资料描述、网址和图像列不在我的用户模型中,而是在我的个人资料模型中。我已经定义了这些关系,以便更好地理解以下文件的代码:

这是我的 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);
    

这是用户表文件:

<?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);
    

这是配置文件表文件:

<?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');
    

【问题讨论】:

这能回答你的问题吗? Update logged in user account settings with laravel 5 and Auth 你能在update()之前添加dd($user-&gt;profile)到控制器并告诉我们返回什么吗? array:3 [▼ "description" => "这是我的个人资料描述..." "url" => "instagram.com/p/BjoCd24D6if" "image" => Illuminate\Http\UploadedFile # 980 ▶] @EdenGaitor,转储怎么会运气好'user_id'? 对不起@steven7mwesigwa。您发送的链接没有为我提供实现我想要的东西所需的洞察力。我不想更改用户设置,我只想允许编辑个人资料信息。这就是我创建与配置文件模型分开的用户模型的原因。我也是 laravel 的新手,我使用的是 laravel 8 而不是版本 5。所以提供的答案中显示的一些语法对我来说有点吓人,因为它一点也不熟悉。尽管如此,我会继续尝试解决这个问题。我希望你能提供一个替代方案。如果我可以为您提供更多信息,请告诉我。 【参考方案1】:

Updates

save 方法也可以用来更新已经存在的模型 在数据库中。要更新模型,您应该检索它并设置任何 您要更新的属性。然后,您应该调用模型的 save 方法。

    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']);

将您的 &lt;form&gt; action 属性编辑为:

<form action="'/users/'. $user->id. '/profile'" enctype="multipart/form-data" method="post">

我希望你在routes/web.php 文件中定义了这条路线/users/$user

$fillable成员变量添加到App\Models\Profilemodel.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();

【讨论】:

也许值得说明的是,描述、url 和图像字段不是我的用户模型中的列。但是,这种关系是在我的 User.php 文件中定义的: public function profile() return $this->hasOne(Profile::class); 我的profile.php文件中也定义了反比关系: public function user() return $this->belongsTo(User::class); 配置文件模型是描述、网址和图像列所在的位置 我不知道这是否会有所作为 @EdenGaitor,我已经更新了答案以适合您的结构。【参考方案2】:
$data = $this->validate($request, [
            'description' => 'nullable',
            'url' => 'required',
            'image' => 'nullable',
        ]);

        $user->description= $data['description'];
        $user->url= $data['url'];
        $user->image= $data['image'];

        $user->save();

【讨论】:

不工作。也许值得说明的是,描述、网址和图像字段不是我的用户模型中的列。但是,这种关系是在我的 User.php 文件中定义的: public function profile() return $this->hasOne(Profile::class); 我的 profile.php 文件中也定义了反向关系: public function user() return $this->belongsTo(User::class); 我不知道这是否会有所作为 该 cade 将被更新并保存在您的数据库中。这只是对数据的验证。 你可以发送你的模型代码你将定义配置文件关系【参考方案3】:

您需要验证传入的$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

【讨论】:

也许值得一提的是,描述、url 和图像字段不是我的用户模型中的列。但是,这种关系是在我的 User.php 文件中定义的: public function profile() return $this->hasOne(Profile::class); 我的 profile.php 文件中也定义了反向关系: public function user() return $this->belongsTo(User::class); 我不知道这是否会有所作为 配置文件模型是描述、网址和图像列所在的位置

以上是关于如何通过应用程序中的表单为用户创建个人资料?我正在使用 laravel 8的主要内容,如果未能解决你的问题,请参考以下文章

Mailchimp:自定义配置文件更新表单中的字段

通过上传表单将图像上传到Django用户个人资料

如何正确预填充颤振表单字段?

如何在 HTML 表单中“预填充”文本区域的值? [复制]

如何:在注册/创建时设置 Firebase 用户的个人资料信息? (颤动网络)

如何从锚标记内提交我的 x 可编辑字段值以及我的表单/提交内容?