用户模块
用户迁移
php artisan migrate
会创建迁移内的表到数据库
用户模型
Laravel 默认为我们生成了用户模型文件
app/Models/User.php
创建Article
模型
php artisan make:model Article
同时创建迁移文件
如果需要在创建模型的同时顺便创建数据库迁移,则可以使用 --migration 或 -m 选项,让我们将刚刚生成的模型进行删除,尝试生成迁移文件:
rm app/Models/Article.php
php artisan make:model Article -m
Model created successfully.
Created Migration: 2020_07_29_234536_create_articles_table
可看到模型文件和迁移文件都一并生成了
Eloquent 表命名约定
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use HasFactory;
protected $table = 'my_articles';
}
创建用户对象
我们使用此命令进入 Tinker 环境:
php artisan tinker
如果中途想要退出 Tinker,可使用 ctrl + c 快捷键。
通过下面命令我们可以很轻松的创建一个用户对象:
App\Models\User::create(['name'=> 'Summer', 'email'=>'summer@example.com','password'=>bcrypt('password')])
查找用户对象
php artisan tinker
User::find(1)
当你传给 find 方法的 id 不存在时,Tinker 将会返回 null:
更新用户对象
$user = User::first()
$user->name = 'Monkey'
调用save
保存
$user->save()
通过 update 方法更新
$user->update(['name'=>'Summer'])
添加用户模块路由
Route::resource('users', 'UsersController');
上面代码将等同于:
Route::get('/users', 'UsersController@index')->name('users.index');
Route::get('/users/create', 'UsersController@create')->name('users.create');
Route::get('/users/{user}', 'UsersController@show')->name('users.show');
Route::post('/users', 'UsersController@store')->name('users.store');
Route::get('/users/{user}/edit', 'UsersController@edit')->name('users.edit');
Route::patch('/users/{user}', 'UsersController@update')->name('users.update');
Route::delete('/users/{user}', 'UsersController@destroy')->name('users.destroy');
使用 resource 方法可让我们少写了很多代码,且严格按照了 RESTful 架构对路由进行设计。
修改用户控制器
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UsersController extends Controller
{
public function create()
{
return view('users.create');
}
public function show(User $user)
{
return view('users.show', compact('user'));
}
}
新建一个用户个人页面
# resources/views/users/show.blade.php
@extends('layouts.default')
@section('title', $user->name)
@section('content')
{{ $user->name }} - {{ $user->email }}
@stop
访问 /users/1
即可看到展示用户名的页面
设置用户头像和侧边栏
# app/Models/User.php
.
.
.
public function gravatar($size = '100')
{
$hash = md5(strtolower(trim($this->attributes['email'])));
return "https://cdn.v2ex.com/gravatar/$hash?s=$size";
}
}
定义好后我们可以调用用户头像了
$user->gravatar();
指定尺寸
$user->gravatar('140');
接下来让我们来构建一个全局通用的局部视图,用于展示用户的头像和用户名等基本信息。
# resources/views/shared/_user_info.blade.php
<a href="{{ route('users.show', $user->id) }}">
<img src="{{ $user->gravatar('140') }}" alt="{{ $user->name }}" class="gravatar"/>
</a>
<h1>{{ $user->name }}</h1>
更改resources/views/users/show.blade.php
加载上面的文件
@extends('layouts.default')
@section('title', $user->name)
@section('content')
<div class="row">
<div class="offset-md-2 col-md-8">
<div class="col-md-12">
<div class="offset-md-2 col-md-8">
<section class="user_info">
@include('shared._user_info', ['user' => $user])
</section>
</div>
</div>
</div>
</div>
@stop
我们可以通过给 @include
方法传参,将用户数据以关联数组的形式传送到 _user_info
局部视图上。
@include('shared._user_info', ['user' => $user])
再次 访问 /users/1
页面查看效果
用户注册表单
重置数据库并重新运行所有迁移,我们之前创建的 1 号用户将会被删除。
php artisan migrate:refresh
表单构建
# resources/views/users/create.blade.php
@extends('layouts.default')
@section('title', '注册')
@section('content')
<div class="offset-md-2 col-md-8">
<div class="card ">
<div class="card-header">
<h5>注册</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ route('users.store') }}">
<div class="mb-3">
<label for="name">名称:</label>
<input type="text" name="name" class="form-control" value="{{ old('name') }}">
</div>
<div class="mb-3">
<label for="email">邮箱:</label>
<input type="text" name="email" class="form-control" value="{{ old('email') }}">
</div>
<div class="mb-3">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" value="{{ old('password') }}">
</div>
<div class="mb-3">
<label for="password_confirmation">确认密码:</label>
<input type="password" name="password_confirmation" class="form-control" value="{{ old('password_confirmation') }}">
</div>
<button type="submit" class="btn btn-primary">注册</button>
</form>
</div>
</div>
</div>
@stop
Laravel 提供了全局辅助函数 old 来帮助我们在 Blade 模板中显示旧输入数据。这样当我们信息填写错误,页面进行重定向访问时,输入框将自动填写上最后一次输入过的数据。
{{ old('name') }}
用户数据验证
# app/Http/Controllers/UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UsersController extends Controller
{
public function create()
{
return view('users.create');
}
public function show(User $user)
{
return view('users.show', compact('user'));
}
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|unique:users|max:50',
'email' => 'required|email|unique:users|max:255',
'password' => 'required|confirmed|min:6'
]);
return;
}
}
此时提交数据会被拦截,我们在form 表单中加入一个csrf
令牌即可
{{ csrf_field() }}
注册失败错误消息
# resources/views/shared/_errors.blade.php
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
定义好错误消息局部视图,便可以在用户的注册表单中对该视图进行引用。
# resources/views/users/create.blade.php
@extends('layouts.default')
@section('title', '注册')
@section('content')
<div class="offset-md-2 col-md-8">
<div class="card ">
<div class="card-header">
<h5>注册</h5>
</div>
<div class="card-body">
@include('shared._errors')
<form method="POST" action="{{ route('users.store') }}">
{{ csrf_field() }}
<div class="mb-3">
<label for="name">名称:</label>
<input type="text" name="name" class="form-control" value="{{ old('name') }}">
</div>
<div class="mb-3">
<label for="email">邮箱:</label>
<input type="text" name="email" class="form-control" value="{{ old('email') }}">
</div>
<div class="mb-3">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" value="{{ old('password') }}">
</div>
<div class="mb-3">
<label for="password_confirmation">确认密码:</label>
<input type="password" name="password_confirmation" class="form-control" value="{{ old('password_confirmation') }}">
</div>
<button type="submit" class="btn btn-primary">注册</button>
</form>
</div>
</div>
</div>
@stop
添加语言包
配置中文
# config/app.php
<?php
return [
.
.
.
'locale' => 'zh_CN',
.
.
.
];
发布 语言包
php artisan lang:publish
# lang/zh_CN/validation.php
'custom' => [
'email' => [
'required' => '邮箱地址不能为空!',
],
],
保存用户并重定向
# app/Http/Controllers/UsersController.php
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|unique:users|max:50',
'email' => 'required|email|unique:users|max:255',
'password' => 'required|confirmed|min:6'
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
return redirect()->route('users.show', [$user]);
}
消息提示
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|unique:users|max:50',
'email' => 'required|email|unique:users|max:255',
'password' => 'required|confirmed|min:6'
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => bcrypt($request->password),
]);
session()->flash('success', '欢迎,您将在这里开启一段新的旅程~');
return redirect()->route('users.show', [$user]);
}
我们可以使用 session()
方法来访问会话实例。而当我们想存入一条缓存的数据,让它只在下一次的请求内有效时,则可以使用 flash
方法。flash
方法接收两个参数,第一个为会话的键,第二个为会话的值,我们可以通过下面这行代码的为会话赋值。
session()->flash('success', '欢迎,您将在这里开启一段新的旅程~');
之后我们可以使用 session()->get('success')
通过键名来取出对应会话中的数据,取出的结果为 欢迎,您将在这里开启一段新的旅程~
。
在视图上展示
# resources/views/shared/_messages.blade.php
@foreach (['danger', 'warning', 'success', 'info'] as $msg)
@if(session()->has($msg))
<div class="flash-message">
<p class="alert alert-{{ $msg }}">
{{ session()->get($msg) }}
</p>
</div>
@endif
@endforeach
session()->has($msg)
可用于判断会话中 $msg
键对应的值是否为空,若为空则在页面上不进行显示。最后,我们通过 session()->get($msg)
来取出对应的值并在页面上进行显示。
现在,让我们在全局通用视图中加入消息提醒视图。
# resources/views/layouts/default.blade.php
<!DOCTYPE html>
<html>
<head>
<title>@yield('title', 'Weibo App') - Laravel 入门教程</title>
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
</head>
<body>
@include('layouts._header')
<div class="container">
<div class="offset-md-1 col-md-10">
@include('shared._messages')
@yield('content')
@include('layouts._footer')
</div>
</div>
</body>
</html>