laravel 图片上传功能 修改头像
一、要实现这个功能,要做以下几个步骤:
1. 用户表中创建 avatar 字段,来存放用户头像的 url 。
2. 创建个头像上传的方法:实现--接收图片--保存图片--返回路径。
3. 控制器调用方法,传入参数,得到图片路径实现,路径存入数据库。
4. 创建 FormRequest 类,实现表单请求验证。
此处需要具体说下3和4:
3: 在做项目中,我们不止上传头像需要用到『图片上传功能』,比如发布帖子功能中,我们也将会允许用户上传图片,所以此处我们需要预先设计一下图片上传相关的逻辑,我们可以将『图片上传』核心操作做成一个工具类。
我们将使用 app/Handlers
文件夹来存放本项目的工具类,『工具类(utility class)』是指一些跟业务逻辑相关性不强的类,Handlers
意为 处理器 ,ImageUploadHandler 意为图片上传处理器,简单易懂。
4: 表单请求验证(FormRequest) 是 Laravel 框架提供的用户表单数据验证方案,此方案相比手工调用 validator
来说,能处理更为复杂的验证逻辑,更加适用于大型程序。
表单请求验证(FormRequest)的工作机制,是利用 Laravel 提供的依赖注入功能,在控制器方法,比如在控制器的 update()
方法声明中,传参 UserRequest。这将触发表单请求类的自动验证机制,验证发生在 UserRequest 中,并使用此文件中方法 rules()
定制的规则,只有当验证通过时,才会执行 控制器 update()
方法中的代码。否则抛出异常,并重定向至上一个页面,附带验证失败的信息。
authorize()
方法是表单验证自带的另一个功能 —— 权限验证,本进行用户授权时候使用,修改 return 为 true;
,意味所有权限都通过即可。
二、具体的上传步骤
1. 在 user 表中创建字段 avatar 用来存储用户头像路径。
2. php artisan make:controller UserController 创建用户控制器,已有省略这步
3. 在 app 目录下创建文件夹 Handles 用来存放工具,此处我们存放 ImageUploadHandle.php 这个上传图片的工具,去创建这个文件。
4. php artisan make:request UserRequest 创建用户请求,此类继承于 FormRequest 类,拥有更复杂的处理方式。
一次请求的逻辑顺序为:模板上点击提交,通过路由到达 UserController 控制器,在控制器的 store( UserRequest $request) 方法上,使用以来注入,这样,数据传送过来会先到 UserRequest 中进行验证,验证通过后进行图片的保存操作,在这里我们需要调用图片保存的方法,步骤为:在上方 use 引入图片上传工具类 use App\Handles\ImageUploadHandle 引入后,在 store( ImageUploadHandle $upload) 方法中以来注入,这样子就可以调用方法来进行保存: $result[ ' avatar ' ] = $this->save(参数) 调用并且在此处传入参数,参数为:1-文件、2-文件夹、3-用户id ,$result 为 $result = $request->all() 接下来就要到图片上传工具里面去编辑实际的逻辑,这个 save 方法保存完成图片后返回图片的路径,我们使用 update( $result ) 存储头像。这样子即完成了整个逻辑。
上面的4个步骤我们依次来处理( UserRequest 的验证逻辑我就不写了,很简单,要不然篇幅太长)。
1. 在 UserController 中:
use App\Handles\ImageUploadHandle;
public function store( UserRequest $request , ImageUploadHandle $upload , User $user) // $user 为当前登陆用户的实列,也是依赖注入
{
$result[ ' avatar ' ] = $this->save( $request->avatar , ' avatar' , $user ); // 传入参数为 文件 文件名 登陆用户-主要是想用登陆用户的id
User :: where( ' id ' , $user->id ) -> update( $result );
return redirect()->route( ' 你个人信息的首页,填写路由name ' );
}
2. 在 ImageUploadHandle.php 中
namespace App\Handles\ImageUploadHandle
class ImageUploadHandle
{
$allowed_ext = [ ' jpg ' , ' gif ' , ' png ' , ' jpeg ' ]; //允许上传的后缀格式的图片,后面要验证用
public function save( $file , $folder , $user )
{
// 先设置一个文件存放的路径,一般存在public 或者 storage 下,这里我把它存在 storage 下
// public_path() 获取项目的 public 的物理路径,从服务器的跟路径开始,
$file_path = public_path() . ' / storage / upload / ' . $folder . ' / ' . $user->id ;
// 获取图片的后缀,如果文件后缀存在,即为它自己,如果不存在,设置图片后缀为 png,图片名字等会自己定义,所有后缀等会用来拼接
$ext = strtolower($file->getClientOriginalExtension()) ?: 'png';
// 设置图片的名字,名字为当前的时间+随机字符串10个+刚才获取的后缀
$file_name = time() . str_random( 10 ) . ' / ' . $ext ;
// 判断后缀是否是允许的,如果获取到文件的后缀,而不是自己设定的png ,就要对其进行判断,是不是图片, 不在返回 false 结束
if( ! in_array( $ext , $this->allowed_ext ) ) { return false }
//存储图片,意思:参数一:路径 参数二:名字,把文件存到这个路径下,使用这个名字保存。
$file->move( $file_path , $file_name);
// 返回一个路径用于存入数据库,asset 用于获取文件的链接,结果为字符串。
return asset( " storage/upload/ . {$folder} . ' / ' . {$user->id}. ' / ' . {$file_name} '");
}
}
这样子,图片上传工具写完,但是有一点再,我们数据库图片的路径是存储再 storage 下,而域名指向的是 public 下面。
所以这里使用了 artisan 的链接: php artisan storage:link 这样会再 public 目录下创建一个 storage 目录,这个目录直接指向 storage/app/public,
所以我们加载 localhost/storage/upload/avatar/1/212121.jpg
实际路径是:localhost/storage/app/public/upload/avatar/1/212121.jpg
再模板总需要调用头像直接去使用 {{ $user->avatar }} 既可以加载出来头像
大家可以试试吧,有哪里报错,留言。