Laravel 大型项目系列教程(二)之用户管理

Laravel大型项目系列教程(二)

本节教程将大概实现用户的注册、修改个人信息、管理用户功能

1.创建用户注册视图

$ php artisan generate:view users.create

修改app/views/users/create.blade.php

@extends('_layouts.default')

@section('main')
  <div class="am-g am-g-fixed">
    <div class="am-u-lg-6 am-u-md-8">
      <br/>
      @if (Session::has('message'))
        <div class="am-alert am-alert-{{ Session::get('message')['type'] }}" data-am-alert>
          <p>{{ Session::get('message')['content'] }}</p>
        </div>
      @endif
      @if ($errors->has())
        <div class="am-alert am-alert-danger" data-am-alert>
          <p>{{ $errors->first() }}</p>
        </div>
      @endif
      {{ Form::open(array('url' => 'register', 'class' => 'am-form')) }}
        {{ Form::label('email', 'E-mail:') }}
        {{ Form::email('email', Input::old('email')) }}
        <br/>
        {{ Form::label('nickname', 'NickName:') }}
        {{ Form::text('nickname', Input::old('nickname')) }}
        <br/>
        {{ Form::label('password', 'Password:') }}
        {{ Form::password('password') }}
        <br/>
        {{ Form::label('password_confirmation', 'ConfirmPassword:') }}
        {{ Form::password('password_confirmation') }}
        <br/>
        <div class="am-cf">
          {{ Form::submit('Register', array('class' => 'am-btn am-btn-primary am-btn-sm am-fl')) }}
        </div>
      {{ Form::close() }}
      <br/>
    </div>
  </div>
@stop

修改layouts/nav.blade.php中的@else部分:

@else
  <div class="am-topbar-right">
    <a href="{{ URL::to('register') }}" class="am-btn am-btn-secondary am-topbar-btn am-btn-sm topbar-link-btn"><span class="am-icon-pencil"></span> Register</a>
  </div>
  <div class="am-topbar-right">
    <a href="{{ URL::to('login') }}" class="am-btn am-btn-primary am-topbar-btn am-btn-sm topbar-link-btn"><span class="am-icon-user"></span> Login</a>
  </div>
@endif

routes.php中增加:

Route::get('register', function()
{
    return View::make('users.create');
});

启动开发服务器,浏览器中访问localhost:8000,导航条中多了一个Register按钮:

点击Register按钮,进入用户注册页面:

2.实现用户注册

routes.php中增加:

Route::post('register', array('before' => 'csrf', function()
{
    $rules = array(
        'email' => 'required|email|unique:users,email',
        'nickname' => 'required|min:4|unique:users,nickname',
        'password' => 'required|min:6|confirmed',
    );
    $validator = Validator::make(Input::all(), $rules);
    if ($validator->passes())
    {
        $user = User::create(Input::only('email', 'password', 'nickname'));
        $user->password = Hash::make(Input::get('password'));
        if ($user->save())
        {
            return Redirect::to('login')->with('message', array('type' => 'success', 'content' => 'Register successfully, please login'));
        } else {
            return Redirect::to('register')->withInput()->with('message', array('type' => 'danger', 'content' => 'Register failed'));
        }
    } else {
        return Redirect::to('register')->withInput()->withErrors($validator);
    }
}));

上面表单验证规则的unique:users,email能确保users表中的email字段是唯一的,切记usersemail之间不能有空格confirmed确保提交的数据必须有一个名为password_conformation的字段且与password字段的值相等。

例如当输入已存在的email时,会出现错误提示:

之后我们再修改两个地方,把routes.phppost login内的

return Redirect::to('login')->withInput()->with('message', 'E-mail or password error');

修改为:

return Redirect::to('login')->withInput()->with('message', array('type' => 'danger', 'content' => 'E-mail or password error'));

login.blade.php中的

@if (Session::has('message'))
  <div class="am-alert am-alert-danger" data-am-alert>
    <p>{{ Session::get('message') }}</p>
  </div>
@endif

修改为:

@if (Session::has('message'))
  <div class="am-alert am-alert-{{ Session::get('message')['type'] }}" data-am-alert>
    <p>{{ Session::get('message')['content'] }}</p>
  </div>
@endif

现在你就可以尝试注册,如果注册成功就会跳转到登录页面,并给出成功的提示:

注册成功之后你可以试试是否能用刚注册的账号成功登录。

3.修改个人信息

用户注册之后我们还应该让他能够修改信息,在_layouts/nav.blade.php中添加修改个人信息的选项:

<li><a href="{{ URL::to('user/'. Auth::id() . '/edit') }}"><span class="am-icon-user"></span> Information</a></li>

添加视图users/edit.blade.php

$ php artisan generate:view users.edit

修改users/edit.blade.php

@extends('_layouts.default')

@section('main')
  <div class="am-g am-g-fixed">
    <div class="am-u-lg-6 am-u-md-8">
      <br/>
      @if (Session::has('message'))
        <div class="am-alert am-alert-{{ Session::get('message')['type'] }}" data-am-alert>
          <p>{{ Session::get('message')['content'] }}</p>
        </div>
      @endif
      @if ($errors->has())
        <div class="am-alert am-alert-danger" data-am-alert>
          <p>{{ $errors->first() }}</p>
        </div>
      @endif
      {{ Form::model($user, array('url' => 'user/' . $user->id, 'method' => 'PUT', 'class' => 'am-form')) }}
        {{ Form::label('email', 'E-mail:') }}
        <input id="email" name="email" type="email" readonly="readonly" value="{{ $user->email }}"/>
        <br/>
        {{ Form::label('nickname', 'NickName:') }}
        <input id="nickname" name="nickname" type="text" value="{{{ $user->nickname }}}"/>
        <br/>
        {{ Form::label('old_password', 'OldPassword:') }}
        {{ Form::password('old_password') }}
        <br/>
        {{ Form::label('password', 'NewPassword:') }}
        {{ Form::password('password') }}
        <br/>
        {{ Form::label('password_confirmation', 'ConfirmPassword:') }}
        {{ Form::password('password_confirmation') }}
        <br/>
        <div class="am-cf">
          {{ Form::submit('Modify', array('class' => 'am-btn am-btn-primary am-btn-sm am-fl')) }}
        </div>
      {{ Form::close() }}
      <br/>
    </div>
  </div>
@stop

routes.php中添加:

Route::get('user/{id}/edit', array('before' => 'auth', 'as' => 'user.edit', function($id)
{
    if (Auth::user()->is_admin or Auth::id() == $id) {
        return View::make('users.edit')->with('user', User::find($id));
    } else {
        return Redirect::to('/');
    }
}));

上面的as命名路由,在生成URL时也可以使用别名。例如Redirect::route('user.edit', $id)

现在登录后在右上角会发现多了一个Information的选项,点击后会显示用户个人信息的页面:

你是不是发现了表单中的Form::model($user),它会根据View::make('users.edit')->with('user', User::find($id))传过来的user进行自动填充。

之后就要实现真正地修改用户信息了,在routes.php中增加:

Route::put('user/{id}', array('before' => 'auth|csrf', function($id)
{
    if (Auth::user()->is_admin or (Auth::id() == $id)) {
        $user = User::find($id);
        $rules = array(
            'password' => 'required_with:old_password|min:6|confirmed',
            'old_password' => 'min:6',
        );
        if (!(Input::get('nickname') == $user->nickname))
        {
            $rules['nickname'] = 'required|min:4||unique:users,nickname';
        }
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->passes())
        {
            if (!(Input::get('old_password') == '')) {
                if (!Hash::check(Input::get('old_password'), $user->password)) {
                    return Redirect::route('user.edit', $id)->with('user', $user)->with('message', array('type' => 'danger', 'content' => 'Old password error'));
                } else {
                    $user->password = Hash::make(Input::get('password'));
                }
            }
            $user->nickname = Input::get('nickname');
            $user->save();
            return Redirect::route('user.edit', $id)->with('user', $user)->with('message', array('type' => 'success', 'content' => 'Modify successfully'));
        } else {
            return Redirect::route('user.edit', $id)->withInput()->with('user', $user)->withErrors($validator); 
        }
    } else {
        return Redirect::to('/');
    }
}));

现在尝试修改信息,如果失败,就会出现错误提示就像下面这样:

如果成功就会像下面这样:

这样修改个人信息的功能就完成了。

4.管理用户

上面的完成之后,我们就需要管理员能够管理用户,例如可以修改其他用户的昵称、重置它们的密码、锁定用户等。先需要重写下_layouts/nav.blade.php@if (Auth::check())里的内容:

@if (Auth::user()->is_admin)
<ul class="am-nav am-nav-pills am-topbar-nav">
  <li class=""><a href="#">Users</a></li>
</ul>
@endif
<div class="am-topbar-right">
  <div class="am-dropdown" data-am-dropdown="{boundary: '.am-topbar'}">
    <button class="am-btn am-btn-secondary am-topbar-btn am-btn-sm am-dropdown-toggle" data-am-dropdown-toggle><span class="am-icon-users"></span> {{{ Auth::user()->nickname }}} <span class="am-icon-caret-down"></span></button>
    <ul class="am-dropdown-content">
      <li><a href="{{ URL::to('user/'. Auth::id() . '/edit') }}"><span class="am-icon-user"></span> Information</a></li>
      <li><a href="{{ URL::to('logout') }}"><span class="am-icon-power-off"></span> Exit</a></li>
    </ul>
  </div>
</div>

创建用户列表视图:

$ php artisan generate:view admin.users.list

修改views/admin/users/list.blade.php

@extends('_layouts.default')

@section('main')
<div class="am-g am-g-fixed">
  <div class="am-u-sm-12">
    <br/>
    @if (Session::has('message'))
    <div class="am-alert am-alert-{{ Session::get('message')['type'] }}" data-am-alert>
      <p>{{ Session::get('message')['content'] }}</p>
    </div>
    @endif
    <table class="am-table am-table-hover am-table-striped ">
      <thead>
      <tr>
        <th>ID</th>
        <th>E-mail</th>
        <th>Nickname</th>
        <th>Management</th>
      </tr>
      </thead>
      <tbody>
      @foreach ($users as $user)
        <tr>
        <td>{{ $user->id }}</td>
        <td>{{ $user->email }}</td>
        <td>{{{ $user->nickname }}}</td>
        <td>
          <a href="{{ URL::to('user/'. $user->id . '/edit') }}" class="am-btn am-btn-xs am-btn-primary">Edit</a>
          {{ Form::open(array('url' => 'user/' . $user->id . '/reset', 'method' => 'PUT', 'style' => 'display: inline;')) }}
            <button type="button" class="am-btn am-btn-xs am-btn-warning" id="reset{{ $user->id }}">Reset</button>
          {{ Form::close() }}
          @if ($user->block)
          {{ Form::open(array('url' => 'user/' . $user->id . '/unblock', 'method' => 'PUT', 'style' => 'display: inline;')) }}
            <button type="button" class="am-btn am-btn-xs am-btn-danger" id="unblock{{ $user->id }}">Unblock</button>
          {{ Form::close() }}
          @else
          {{ Form::open(array('url' => 'user/' . $user->id, 'method' => 'DELETE', 'style' => 'display: inline;')) }}
            <button type="button" class="am-btn am-btn-xs am-btn-danger" id="delete{{ $user->id }}">Block</button>
          {{ Form::close() }}
          @endif
        </td>
      </tr>
      @endforeach
      </tbody>
    </table>
  </div>
</div>

<div class="am-modal am-modal-confirm" tabindex="-1" id="my-confirm">
  <div class="am-modal-dialog">
    <div class="am-modal-bd">
    </div>
    <div class="am-modal-footer">
      <span class="am-modal-btn" data-am-modal-cancel>No</span>
      <span class="am-modal-btn" data-am-modal-confirm>Yes</span>
    </div>
  </div>
</div>
<script>
  $(function() {
    $('[id^=reset]').on('click', function() {
      $('.am-modal-bd').text('Sure you want to reset the password for 123456?');
      $('#my-confirm').modal({
        relatedTarget: this,
        onConfirm: function(options) {
          $(this.relatedTarget).parent().submit();
        },
        onCancel: function() {
        }
      });
    });

    $('[id^=delete]').on('click', function() {
      $('.am-modal-bd').text('Sure you want to lock it?');
      $('#my-confirm').modal({
        relatedTarget: this,
        onConfirm: function(options) {
          $(this.relatedTarget).parent().submit();
        },
        onCancel: function() {
        }
      });
    });

    $('[id^=unblock]').on('click', function() {
      $('.am-modal-bd').text('Sure you want to unlock it?');
      $('#my-confirm').modal({
        relatedTarget: this,
        onConfirm: function(options) {
          $(this.relatedTarget).parent().submit();
        },
        onCancel: function() {
        }
      });
    });
  });
</script>
@stop

上面的@foreach相当于for循环,可以遍历@users中的内容。

views/_layouts/default.blade.php中的

<script src="//cdn.bootcss.com/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdn.amazeui.org/amazeui/2.1.0/js/amazeui.min.js"></script>

移到head中。

为了保证只有管理员才能管理用户,我们在app/filters.php中增加一个过滤器

Route::filter('idAdmin', function()
{
    if (!Auth::user()->is_admin) {
        return Redirect::to('/');
    }
});

routes.php中增加:

Route::group(array('prefix' => 'admin', 'before' => 'auth|isAdmin'), function()
{
    Route::get('users', function()
    {
        return View::make('admin.users.list')->with('users', User::all())->with('page', 'users');
    });
});

Route::model('user', 'User');

Route::group(array('before' => 'auth|csrf|isAdmin'), function()
{
    Route::put('user/{user}/reset', function(User $user)
    {
        $user->password = Hash::make('123456');
        $user->save();
        return Redirect::to('admin/users')->with('message', array('type' => 'success', 'content' => 'Reset password successfully'));
    });

    Route::delete('user/{user}', function(User $user)
    {
        $user->block = 1;
        $user->save();
        return Redirect::to('admin/users')->with('message', array('type' => 'success', 'content' => 'Lock user successfully'));
    });

    Route::put('user/{user}/unblock', function(User $user)
    {
        $user->block = 0;
        $user->save();
        return Redirect::to('admin/users')->with('message', array('type' => 'success', 'content' => 'Unlock user successfully'));
    });
});

上面使用了路由组Route::group路由前缀prefix路由与模型绑定Route::model,过滤器是可以有多个的用|分隔。

现在用管理员账号登录后会发现导航条多了一个Users链接,点击Users超链接会出现下图这样:

上面的用户数据需要自己添加,当点击Block的是否会出现确认的提示框:

点击Yes操作成功后会像下面这样:

5.小结

这节完成了用户管理模块,但是还有很多不完善的地方,你可以在用户列表页面添加按昵称或Email查找用户、只显示锁定的用户等功能,还有你是不是发现了在routes.php中代码显得很零乱,那是因为我们还没有使用MVC模式中的C,在下节教程中就将讲解Laravel中的控制器。

本文详细出处http://www.shiyanlou.com/courses/123

本帖已被设为精华帖!
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 12
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!