跟社区学laravel博客实战4

新建一个分支:

git checkout master
git checkout -b sign-up

 

我们之前已使用 Tinker 成功创建了一个用户对象。

运行下面命令使用 Tinker 来查询用户的信息,确保该用户对象在数据库中确实存在:

$ php artisan tinker


从数据库中获取第一号用户的个人信息:
>>> App\Models\User::first()
=> App\Models\User {#2909
     id: 1,
     name: "Summer",
     email: "summer@example.com",
     email_verified_at: null,
     created_at: "2018-12-12 09:09:53",
     updated_at: "2018-12-12 09:21:53",
   }


通过 Tinker 返回的信息可以看到,id 为 1,
用户名为 Summer 的用户信息被成功返回。
接下来让我们开始着手构建用户个人页面,
并在此页面上对用户信息进行显示。

新增的 resource 方法将遵从 RESTful 架构为用户资源生成路由。该方法接收两个参数,第一个参数为资源名称,第二个参数为控制器名称。

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

接下来我们定义方法:
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 show(User $user)
    {
        return view('users.show', compact('user'));

        return view('users.show', [
            'user'=>$user
        ]);
    }

    //所以在视图里访问 user 变量的时候,实际访问的就是这个数组里 user 键所对应的内容

    //创建一个包含变量名和它们的值的数组
*/

Laravel 会自动解析定义在控制器方法(变量名匹配路由片段)中的 Eloquent 模型类型声明。

在上面代码中,由于 show() 方法传参时声明了类型 —— Eloquent 模型 User,对应的变量名 $user 会匹配路由片段中的 {user},这样,Laravel 会自动注入与请求 URI 中传入的 ID 对应的用户模型实例。

此功能称为 『隐性路由模型绑定』,是『约定优于配置』设计范式的体现,同时满足以下两种情况,此功能即会自动启用:
路由声明时必须使用 Eloquent 模型的单数小写格式来作为路由片段参数,User 对应 {user}:

Route::get('/users/{user}', 'UsersController@show')->name('users.show');

在使用资源路由 Route::resource('users', 'UsersController'); 时,默认已经包含了上面的声明。

控制器方法传参中必须包含对应的 Eloquent 模型类型声明,并且是有序的:

public function show(User $user)
{
    return view('users.show', compact('user'));
}

当请求 weibo.test/users/1  并且满足以上两个条件时,Laravel 将会自动查找 ID 为 1 的用户并赋值到变量 $user 中,如果数据库中找不到对应的模型实例,会自动生成 HTTP 404 响应。
return view('users.show', compact('user'));
我们将用户对象 $user 通过 compact 方法转化为一个关联数组,并作为第二个参数传递给 view 方法,将数据与视图进行绑定。
show 方法添加完成之后,我们便能在视图中使用 user 变量来访问通过 view 方法传递给视图的用户数据。
由于我们还没有创建用户个人页面,因此这时访问用户页面时会出现如下报错。
View [users.show] not found.

下面让我们来新建一个用户个人页面。

$ vi resources/views/users/show.blade.php


@extends('layouts.default')
@section('title', $user->name)

@section('content')
{{ $user->name }} - {{ $user->email }}
@stop

由于我们使用了 view('users.show', compact('user')) 将用户数据与视图进行绑定,因此在视图中可以直接使用 $user 来访问用户实例。

 

Gravatar 头像和侧边栏

$ vi app/Models/User.php
   

 public function gravatar($size = '100')
    {
        $hash = md5(strtolower(trim($this->attributes['email'])));
        return "http://www.gravatar.com/avatar/$hash?s=$size";
    }


1 为 gravatar 方法传递的参数 size 指定了默认值 100;
2 通过 $this->attributes['email'] 获取到用户的邮箱;
3 使用 trim 方法剔除邮箱的前后空白内容;
4 用 strtolower 方法将邮箱转换为小写;
5 将小写的邮箱使用 md5 方法进行转码;
6 将转码后的邮箱与链接、尺寸拼接成完整的 URL 并返回;




接下来让我们来构建一个全局通用的局部视图,用于展示用户的头像和用户名等基本信息。

$ vi 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>



该视图将被嵌套在用户个人页面中进行使用,
因此我们需要对用户个人页面进行更改,
加入我们新创建的用户信息局部视图。

$ vi 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



接下来对样式再进行优化。
$vi resources/sass/app.scss


/* User gravatar */

section.user_info {
  padding-bottom: 10px;
  margin-top: 20px;
  text-align: center;
  .gravatar {
    float: none;
    max-width: 70px;
  }
  h1 {
    font-size: 1.4em;
    letter-spacing: -1px;
    margin-bottom: 3px;
    margin-top: 15px;
  }
}

.gravatar {
  float: left;
  max-width: 50px;
  border-radius: 50%;
}




npm run dev

 

Git 代码版本控制
接着让我们将这些修改加入到版本控制中:

$ git add -A
$ git commit -m "用户显示页面"

 

 

在我们接下来要进行的用户注册功能开发中,第一个步骤即是构建注册表单。首先我们需要把之前在 Tinker 中创建的所有用户数据进行删除,将数据库重置。重置的方法很简单,只需借助 migrate:refresh 命令,即可完成数据库的重置操作。

$ php artisan migrate:refresh

refresh 的作用是重置数据库并重新运行所有迁移。

 

表单构建#
现在让我们更改之前已创建的用户注册页面,加入表单元素。

$ vi 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') }}">
        {{ csrf_field() }}

        <div class="form-group">
          <label for="name">名称:</label>
          <input type="text" name="name" class="form-control" value="{{ old('name') }}">
        </div>

        <div class="form-group">
          <label for="email">邮箱:</label>
          <input type="text" name="email" class="form-control" value="{{ old('email') }}">
        </div>

        <div class="form-group">
          <label for="password">密码:</label>
          <input type="password" name="password" class="form-control" value="{{ old('password') }}">
        </div>

        <div class="form-group">
          <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') }}



Laravel 为了安全考虑,会让我们提供一个 token(令牌)来防止我们的应用受到 CSRF(跨站请求伪造)的攻击。
修复该异常的方法很简单,我们只需要在表单元素中添加 Blade 模板为我们提供的 csrf_field 方法即可。

该方法在 Blade 模板中调用如下:

{{ csrf_field() }}


上面这段代码转换为 HTML 如下所示:

<input type="hidden" name="_token" value="fhcxqT67dNowMoWsAHGGPJOAWJn8x5R5ctSwZrAq">

由于输入框为 hidden 类型,因此该 input 元素在页面上是不可见的。
现在让我们为注册表单添加 csrf_field 方法。
接着让我们将本次修改加入到版本控制中:

$ git add -A
$ git commit -m "用户注册表单"

 

用户数据验证#

如果你现在填写注册表单并进行提交,则会出现报错,因为表单还不能真正使用。我们还需要在用户控制器中添加一个用于处理表单数据提交后的 store 方法,用于处理用户创建的相关逻辑。
 

$ vi 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;
    }
}

在实际开发中,我们经常需要对用户输入的数据进行 验证,在验证成功后再将数据存入数据库。在 Laravel 开发中,提供了多种数据验证方式,在本教程中,我们使用其中一种对新手较为友好的验证方式 - validator 来进行讲解。

validator 由 App\Http\Controllers\Controller 类中的 ValidatesRequests 进行定义,

因此我们可以在所有的控制器中使用 validate 方法来进行数据验证。

validate 方法接收两个参数,

第一个参数为用户的输入数据,

第二个参数为该输入数据的验证规则。

 

这时候如果你再次填写注册表单并进行提交,

你会发现表单依旧处于不可用状态,这是因为:


在表单信息验证失败时,在页面上没有给出错误提示;

在表单信息验证通过后,页面没有重定向跳转到其它页面,并给出注册成功的提示;

下面让我们针对上面两种情况继续完善注册表单。

git add -A
git commit -m "增加 CSRF 验证"

 

 

显示表单错误信息

$ vi 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



Blade 支持所有的循环语句和条件判断语句,
如 @if, @elseif, @else, @for, @foreach, @while 等等,
应用在 Blade 中的表达式都需要以 @ 开头

Laravel 默认会将所有的验证错误信息进行闪存。当检测到错误存在时,Laravel 会自动将这些错误消息绑定到视图上,因此我们可以在所有的视图上使用 errors 变量来显示错误信息。需要注意的是,在我们对 errors 进行使用时,要先使用 count($errors) 检查其值是否为空。

$ vi 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="form-group">
          <label for="name">名称:</label>
          <input type="text" name="name" class="form-control" value="{{ old('name') }}">
        </div>

        <div class="form-group">
          <label for="email">邮箱:</label>
          <input type="text" name="email" class="form-control" value="{{ old('email') }}">
        </div>

        <div class="form-group">
          <label for="password">密码:</label>
          <input type="password" name="password" class="form-control" value="{{ old('password') }}">
        </div>

        <div class="form-group">
          <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

 

添加语言包

composer require "overtrue/laravel-lang:~3.0"




$ vi config/app.php


<?php

return [
    .
    .
    .
    'locale' => 'zh-CN',





//        Illuminate\Translation\TranslationServiceProvider::class,
Overtrue\LaravelLang\TranslationServiceProvider::class,



还可以手动设置,
具体操作方法,随后专门写一篇blog
git add -A
git commit -m "中文的错误提示信息"

 

注册成功

目前用户注册失败的逻辑已经处理完成,让我们接着完善用户注册成功后的处理逻辑。
当用户注册完成,且表单信息验证通过后,我们需要做以下两个操作:
将用户提交的信息存储到数据库,并重定向到其个人页面;

在网页顶部位置显示注册成功的提示信息;

让我们针对这两个操作来写具体的逻辑实现代码。
保存用户并重定向

$ vi app/Http/Controllers/UsersController.php


<?php

namespace App\Http\Controllers;
.
.
.
class UsersController extends Controller
{
    .
    .
    //store 方法接受一个 Illuminate\Http\Request 实例参数

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



redirect()->route('users.show', [$user]);

注意这里是一个『约定优于配置』的体现,
此时 $user 是 User 模型对象的实例。
route() 方法会自动获取 Model 的主键,也就是数据表 users 的主键 id,以上代码等同于:

redirect()->route('users.show', [$user->id]);



$name = $request->name;
如果需要获取用户输入的所有数据,可使用:
$data = $request->all();

用户模型 User::create() 创建成功后会返回一个用户对象,
并包含新注册用户的所有信息。
我们将新注册用户的所有信息赋值给变量 $user,并通过路由跳转来进行数据绑定



session()->flash('success', '欢迎,您将在这里开启一段新的旅程~');

现在验证通过的注册用户已经能够成功创建,并进行重定向跳转了。
接下来我们要做的就是,用户注册成功后,在页面顶部位置显示注册成功的提示信息。

使用 session() 方法来访问会话实例。而当我们想存入一条缓存的数据,
让它只在下一次的请求内有效时,则可以使用 flash 方法。
flash 方法接收两个参数,第一个为会话的键,第二个为会话的值,
我们可以通过下面的这行代码为会话赋值。

之后我们可以使用 session()->get('success') 通过键名来取出对应会话中的数据,

取出的结果为 欢迎,您将在这里开启一段新的旅程~。

接下来的消息提示我们会用会话进行闪存,并分别为其设定好指定的键。

danger, warning, success, info 这四个键名在 Bootstrap 分别具有不同样式展现效果,

因此后面我们将使用这几个键名作为消息提示的专有设定。

现在让我们加入消息提醒视图,让会话消息在视图上进行展示。

$ vi 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) 来取出对应的值并在页面上进行显示。



$ vi 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>
Git 代码版本控制

接下来让我们将改动的代码进行提交,并切回到主分支中进行合并。
开始之前,请确保 npm run watch-poll 窗口已经关闭,然后依次执行以下命令:
$ git add -A
$ git commit -m "完成用户注册功能"
$ git checkout master
$ git merge sign-up

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值