如何在 Laravel 項目中輕松實現(xiàn)上傳頭像功能?

在 web 開發(fā)中經(jīng)常使用圖片上傳功能住涉,目前有許多免費的資源可以讓開發(fā)者輕松實現(xiàn)圖片上傳功能,那如何在 laravel 項目中輕松實現(xiàn)上傳頭像功能呢枪狂?最近我在開發(fā)我的個人網(wǎng)站時就用到這個功能椒袍,下面我說說我的具體實現(xiàn)思路。

設(shè)計數(shù)據(jù)表字段

我們需要在 users 用戶表里面添加一個 avatar 字段來存用戶的頭像地址劳殖,生成用戶表的遷移文件database/migrations/[timestamp]_create_users_table.php 中的代碼如下:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('sex')->nullable();
            $table->string('phone')->unique()->nullable();
            $table->string('password')->nullable();
            $table->string('avatar')->nullable();
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

打開頭像修改頁面

routes/web.php 中添加打開修改頭像頁面的路由:

Route::get('users/{user}/edit_avatar','UsersController@editAvatar')->middleware('auth')->name('users.edit_avatar');

使用命令創(chuàng)建 UsersController 控制器铐尚,命令如下:

php artisan make:controller UsersController

該命令會在 app/Http/Controllers 下生成 UsersController.php 文件,在 UsersController.php 中添加 editAvatar 方法哆姻,用以打開修改頭像的頁面宣增,代碼如下:

<?php

namespace App\Http\Controllers;

use App\Handlers\ImageUploadHandler;
use App\Models\User;
use App\Notifications\EmailVerificationNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Mail;

class UsersController extends Controller
{
    
    public function editAvatar(User $user)
    {
        return view('users.edit_avatar', compact('user'));
    }
}

修改頭像頁面如下:

修改頁面截圖

resources/views/users/edit_avatar.blade.php 文件中實現(xiàn)這個界面,代碼如下:

@extends('layouts.app')
@section('title')
    基本信息
@stop
@section('content')
    <section class="section" >
        <div class="container">
            <div class="columns">
                <div class="column is-3">
                    <div class="card">
                        <div class="card-content">
                            <nav class="panel ">
                                <a class="panel-block" href="{{url('users/'.$user->id.'/edit')}}">
                            <span class="panel-icon">
                              <i class="fa fa-book" aria-hidden="true"></i>
                            </span>
                                    個人信息
                                </a>
                                <a class="panel-block is-active"  href="{{ route('users.edit_avatar',$user->id) }}">
                            <span class="panel-icon">
                              <i class="fa fa-picture-o" aria-hidden="true"></i>
                            </span>
                                    修改頭像
                                </a>
                                <a class="panel-block" href="{{ route('users.edit_password',$user->id) }}">
                            <span class="panel-icon">
                              <i class="fa fa-lock" aria-hidden="true"></i>
                            </span>
                                    修改密碼
                                </a>
                                <div class="panel-block">
                                    <a class="button is-link is-outlined is-fullwidth">
                                        建議反饋
                                    </a>
                                </div>
                            </nav>
                        </div>
                    </div>
                </div>
                <div class="column is-9">
                    <div class="card">
                        <div class="card-content">
                            <h2 class="title is-4"><span class="icon"><i class="fa fa-picture-o"></i></span> 請選擇圖片</h2>
                            <hr>
                            @if(\Illuminate\Support\Facades\Session::has('mes'))
                                <p class="field">
                                   <span class="has-text-danger">
                                       {{\Illuminate\Support\Facades\Session::get('mes')}}
                                   </span>
                                </p>
                            @endif
                            <form action="{{route('users.update_avatar',$user->id)}}" method="post" enctype="multipart/form-data">
                                {{csrf_field()}}
                               <div class="columns">
                                   <div class="column is-3">
                                       <div class="">
                                           <strong>請選擇圖片:</strong>
                                           <figure class="image is-1by1"><img src="{{asset($user->avatar)}}"></figure>
                                       </div>
                                   </div>
                               </div>
                                <div class="columns">
                                    <div class="column is-3">
                                        <div class="file is-boxed">
                                            <label class="file-label">
                                                <input class="file-input" type="file" name="avatar">
                                                <span class="file-cta">
                                                  <span class="file-icon">
                                                    <i class="fa fa-upload"></i>
                                                  </span>
                                                  <span class="file-label">
                                                    選擇一張圖片
                                                  </span>
                                                </span>
                                            </label>
                                        </div>
                                    </div>
                                </div>
                                <div class="columns">
                                    <div class="column is-3">
                                        <button class="button is-link" type="submit">
                                            <span>上傳頭像</span>
                                        </button>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
@stop

上傳圖片并修改頭像

用戶點擊選擇一張圖片按鈕后選中一張圖片矛缨,然后點擊上傳頭像按鈕爹脾,即可修改頭像成功。接下來繼續(xù)實現(xiàn)上傳圖片功能箕昭,在
routes/web.php 中添加修改頭像路由:

Route::post('users/{user}/update_avatar','UsersController@updateAvatar')->middleware('auth')->name('users.update_avatar');

app/Htpp/Controllers/UsersController.php 中添加 updateAvatar方法灵妨,用以修改頭像,代碼如下:

public function updateAvatar(User $user,Request $request,ImageUploadHandler $uploader)
{
    if ($request->avatar) {
        $result = $uploader->save($request->avatar, 'avatars', 1);
        if ($result) {
            $data['avatar'] = $result['path'];
        }
    }
    $user->avatar=$data['avatar'];
    $user->save();
    return redirect()->route('users.edit_avatar', $user->id)->with('success', '更新成功');
}

細(xì)心的你可能已經(jīng)注意到了盟广,這里引入一個 ImageUploadHandler 類闷串,并用它的 save 方法來處理圖片上傳,該類的代碼也很簡單筋量,代碼如下:

app/Handlers/ImageUploadHandler.php

<?php
namespace App\Handlers;

class ImageUploadHandler
{
    // 只允許以下后綴名的圖片文件上傳
    protected $allowed_ext = ["png", "jpg", "gif", 'jpeg'];

    public function save($file, $folder, $file_prefix)
    {
        // 構(gòu)建存儲的文件夾規(guī)則烹吵,值如:uploads/images/avatars/201709/21/
        // 文件夾切割能讓查找效率更高。
        $folder_name = "uploads/images/$folder/" . date("Ym/d", time());

        // 文件具體存儲的物理路徑桨武,`public_path()` 獲取的是 `public` 文件夾的物理路徑肋拔。
        // 值如:/home/vagrant/Code/larabbs/public/uploads/images/avatars/201709/21/
        $upload_path = public_path() . '/' . $folder_name;

        // 獲取文件的后綴名,因圖片從剪貼板里黏貼時后綴名為空呀酸,所以此處確保后綴一直存在
        $extension = strtolower($file->getClientOriginalExtension()) ?: 'png';

        // 拼接文件名凉蜂,加前綴是為了增加辨析度,前綴可以是相關(guān)數(shù)據(jù)模型的 ID
        // 值如:1_1493521050_7BVc9v9ujP.png
        $filename = $file_prefix . '_' . time() . '_' . str_random(10) . '.' . $extension;

        // 如果上傳的不是圖片將終止操作
        if ( ! in_array($extension, $this->allowed_ext)) {
            return false;
        }

        // 將圖片移動到我們的目標(biāo)存儲路徑中
        $file->move($upload_path, $filename);

        return [
            'path' => config('app.url') . "/$folder_name/$filename"
        ];
    }

}

實現(xiàn)效果如下:

修改成功截圖

至此簡單的頭像上傳功能已然完成性誉,各位大神可能會覺得很簡單窿吩,要的就是簡單,寫這樣的文章是為了增強(qiáng)自己的記憶错览,同時給初學(xué)者一些參考纫雁,后面我會接著寫如何在評論里面實現(xiàn)拖拽/粘貼上傳圖片。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末倾哺,一起剝皮案震驚了整個濱河市轧邪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羞海,老刑警劉巖忌愚,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異却邓,居然都是意外死亡硕糊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來癌幕,“玉大人衙耕,你說我怎么就攤上這事昧穿∩自叮” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵时鸵,是天一觀的道長胶逢。 經(jīng)常有香客問我,道長饰潜,這世上最難降的妖魔是什么初坠? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮彭雾,結(jié)果婚禮上碟刺,老公的妹妹穿的比我還像新娘。我一直安慰自己薯酝,他們只是感情好半沽,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吴菠,像睡著了一般者填。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上做葵,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天占哟,我揣著相機(jī)與錄音,去河邊找鬼酿矢。 笑死榨乎,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘫筐。 我是一名探鬼主播蜜暑,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼严肪!你這毒婦竟也來了史煎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤驳糯,失蹤者是張志新(化名)和其女友劉穎篇梭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酝枢,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡恬偷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了帘睦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袍患。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡坦康,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诡延,到底是詐尸還是另有隱情滞欠,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布肆良,位于F島的核電站筛璧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惹恃。R本人自食惡果不足惜夭谤,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望巫糙。 院中可真熱鬧朗儒,春花似錦、人聲如沸参淹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽承二。三九已至榆鼠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亥鸠,已是汗流浹背妆够。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留负蚊,地道東北人神妹。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像家妆,于是被迫代替她去往敵國和親鸵荠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容