64. 测试头像上传(二)

未匹配的标注

本节说明

  • 对应视频教程第 64 小节:Testing Avatar Uploads: Part 2

本节内容

本节我们继续头像上传的功能。首先我们运行迁移,添加avatar_path字段:

$ php artisan migrate:refresh

进入Tinker环境:

$ php artisan tinker

填充数据:

>>> factory('App\Thread',30)->create();

注册用户 NoNo1,并新建话题:
file
我们使用授权策略来进行上传头像的权限控制。首先我们新建授权策略:

$  php artisan make:policy UserPolicy

接着注册策略:
app/Providers/AuthServiceProvider.php

.
.
protected $policies = [
    'App\Thread' => 'App\Policies\ThreadPolicy',
    'App\Reply' => 'App\Policies\ReplyPolicy',
    'App\User' => 'App\Policies\UserPolicy',
];
    .
    .

然后修改内容:
forum\app\Policies\UserPolicy.php

<?php

namespace App\Policies;

use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class UserPolicy
{
    use HandlesAuthorization;

    public function update(User $signedInUser, User $user)
    {
        return $signedInUser->id === $user->id;
    }
}

接下来我们增加上传文件的表单,并选择一张图片上传:
forum\resources\views\profiles\show.blade.php

    .
    .
    <div class="page-header">
        <h1>
            {{ $profileUser->name }}
        </h1>

        @can('update',$profileUser)
            <form method="POST" action="{{ route('avatar',$profileUser) }}" enctype="multipart/form-data">
                {{ csrf_field() }}

                <input type="file" name="avatar">

                <button type="submit" class="btn btn-primary">Add Avatar</button>
            </form>
        @endcan
    </div>
    .
    .

我们在数据库进行查看:
file
头像路径已经存到数据库中,但是我们的文件存放在 forum\storage\app\public\avatars 目录下,我们想在 public\avatars 目录下使用头像。我们运行以下命令:

$ php artisan storage:link

接着我们将头像显示出来:

    .
    .
    <div class="page-header">
        <h1>
            {{ $profileUser->name }}
        </h1>

        @can('update',$profileUser)
            <form method="POST" action="{{ route('avatar',$profileUser) }}" enctype="multipart/form-data">
                {{ csrf_field() }}

                <input type="file" name="avatar">

                <button type="submit" class="btn btn-primary">Add Avatar</button>
            </form>
        @endcan

        <img src="/{{ $profileUser->avatar_path }}" width="200" height="200">
    </div>
    .
    .

注:以上代码对我未生效,所以我使用的是以下代码:

<img src="/storage/{{ $profileUser->avatar_path }}" width="200" height="200">

我们在刷新页面:
file
我们在话题详情页面显示头像:
forum\resources\views\threads\show.blade.php

    .
    .
    <div class="panel-heading">
        <div class="level">
            <img src="/storage/{{ $thread->creator->avatar_path }}" alt="{{ $thread->creator->name }}" width="25" height="25" class="mr-1">

            <span class="flex">
                <a href="{{ route('profile',$thread->creator) }}">{{ $thread->creator->name }}</a> posted:
                {{ $thread->title }}
            </span>

            @can('update',$thread)
                <form action="{{ $thread->path() }}" method="POST">
                    {{ csrf_field() }}
                    {{ method_field('DELETE') }}

                    <button type="submit" class="btn btn-link">Delete Thread</button>
                </form>
            @endcan
        </div>
    </div>
    .
    .

页面效果:
file
但是与此同时,如果没有上传头像的用户无法显示头像:
file
我们更改一下处理逻辑,如果用户没有上传头像,我们就使用默认头像。如下:

$thread->creator->avatar();

为此我们先来新建一个测试:
forum\tests\Unit\UserTest.php

    .
    .
    /** @test */
    public function a_user_can_determine_their_avatar_path()
    {
        $user = create('App\User');

        $this->assertEquals('avatars/default.jpg',$user->avatar());

        $user->avatar_path = 'avatars/me.jpg';

        $this->assertEquals('avatars/me.jpg',$user->avatar());
    }
}

添加avatar()方法:
forum\app\User.php

    .
    .
    public function avatar()
    {
        return $this->avatar_path ?: 'avatars/default.jpg';
    }

    public function visitedThreadCacheKey($thread)
    {
        return $key = sprintf("users.%s.visits.%s",$this->id,$thread->id);
    }
}

运行测试:
file
现在我们可以有默认的头像,如果用户没有上传头像的话。我们在个人页面和话题详情页面应用:
forum\resources\views\profiles\show.blade.php

    .
    .
    <div class="page-header">
        <h1>
            {{ $profileUser->name }}
        </h1>

        @can('update',$profileUser)
            <form method="POST" action="{{ route('avatar',$profileUser) }}" enctype="multipart/form-data">
                {{ csrf_field() }}

                <input type="file" name="avatar">

                <button type="submit" class="btn btn-primary">Add Avatar</button>
            </form>
        @endcan

        <img src="/storage/{{ $profileUser->avatar() }}" width="200" height="200">
    </div>
    .
    .

forum\resources\views\threads\show.blade.php*

    .
    .
    <div class="panel-heading">
        <div class="level">
            <img src="/storage/{{ $thread->creator->avatar() }}" alt="{{ $thread->creator->name }}" width="25" height="25" class="mr-1">

            <span class="flex">
                <a href="{{ route('profile',$thread->creator) }}">{{ $thread->creator->name }}</a> posted:
                {{ $thread->title }}
            </span>
            .
            .

页面效果:
file

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2
发起讨论 查看所有版本


zh117
关于 64 节的遗漏?
1 个点赞 | 0 个回复 | 问答
CarlGao
Homestead 软链接报错?
0 个点赞 | 11 个回复 | 问答