Laravel大型项目系列教程(二)之用户管理
Laravel大型项目系列教程(二)
一、前言
本节教程将大概实现用户的注册、修改个人信息、管理用户功能。
二、Let's go
1.创建用户注册视图
$ php artisan generate:view users.create
修改app/views/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::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字段是唯一的,切记users和email之间不能有空格,confirmed确保提交的数据必须有一个名为password_conformation的字段且与password字段的值相等。
例如当输入已存在的email时,会出现错误提示:

之后我们再修改两个地方,把routes.php中post 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::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
Laravel大型项目系列教程(二)之用户管理的更多相关文章
- Laravel大型项目系列教程(三)之发表文章
Laravel大型项目系列教程(三)之发表文章 一.前言 上一节教程中完成了用户管理,这节教程将大概完成发表Markdown格式文章并展示的功能. 二.Let's go 1.数据库迁移 文章模块中我们 ...
- Laravel大型项目系列教程(一)
Laravel大型项目系列教程(一) 一.课程概述 1.课程介绍 本教程将使用Laravel完成一个多用户的博客系统,大概会包含如下内容: 路由管理. 用户管理,如用户注册.修改信息.锁定用户等. 文 ...
- Laravel大型项目系列教程(四)显示文章列表和用户修改文章
小编心语:不知不觉已经第四部分了,非常感谢很多人给小编提的意见,改了很多bug,希望以后能继续帮小编找找茬~小编也不希望误导大家~这一节,主要讲的 是如何显示文章列表和让用户修改文章,小编预告一下(一 ...
- Laravel大型项目系列教程(五)之文章和标签管理
一.前言 本节教程将大概完成文章和标签管理以及标签关联. 二.Let's go 1.文章管理 首先创建管理后台文章列表视图: $ php artisan generate:view admin.art ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级)
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级) 企业库加密应用程序模块提供了2种方 ...
- 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...
- ABP框架搭建项目系列教程基础版完结篇
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...
- C#微信公众号开发系列教程二(新手接入指南)
http://www.cnblogs.com/zskbll/p/4093954.html 此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可 ...
- Android Studio系列教程二--基本设置与运行
Android Studio系列教程二--基本设置与运行 2014 年 11 月 28 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处! 上面一篇博客,介绍了Studio的 ...
随机推荐
- .NET - 基于事件的异步模型
注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...
- UML类图(上):类、继承和实现
面向对象设计 对于一个程序员来说,在工作的开始阶段通常都是别人把东西设计好,你来做.伴随着个人的成长,这个过程将慢慢变成自己设计一部分功能来实现,自己实现.如果要自己设计,无论是给自己看,还是给别人看 ...
- ABP(现代ASP.NET样板开发框架)系列之11、ABP领域层——仓储(Repositories)
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之11.ABP领域层——仓储(Repositories) ABP是“ASP.NET Boilerplate Proj ...
- Eclipse安装SVN教程
第1种安装方法 下载SVN安装包.地址:subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240. 根据Eclipse版本进行下载 ...
- 【译】Unity3D Shader 新手教程(4/6) —— 卡通shader(入门版)
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 暗黑系 动机 如果你满足以下条件,我建议你阅读这篇教程: 你想了解更多有关表面着色器的细节知识. 你想实现一个入门 ...
- 从零开始编写自己的C#框架(19)——Web层后端权限模块
不知不觉本系统写了快三个月了,最近写页面的具体功能时感觉到有点吃力,很多地方如果张嘴来讲的话可以说得很细,很全面,可写成文字的话,就不太会写了,有些地方想讲得清晰的话,得用多几倍的文字+实例+变化中的 ...
- react+redux教程(七)自定义redux中间件
今天,我们要讲解的是自定义redux中间件这个知识点.本节内容非常抽象,特别是中间件的定义原理,那多层的函数嵌套和串联,需要极强逻辑思维能力才能完全消化吸收.不过我会多罗嗦几句,所以不用担心. 例子 ...
- 详细分析Android viewpager 无限循环滚动图片
由于最近在忙于项目,就没时间更新博客了,于是趁着周日在房间把最近的在项目中遇到的技术总结下.最近在项目中要做一个在viewpager无限滚动图片的需求,其实百度一下有好多的例子,但是大部分虽然实现了, ...
- Java jacob调用打印机打印word文档
前面说了Java如何生成复杂的Word文档,今年记录下Java如何调用打印机打印word文档. 起初用的是自带的PrintJob,但是系统提供的打印机制并不成熟完整.网上的代码也是千篇一律,在我的打印 ...
- 【基于WinForm+Access局域网共享数据库的项目总结】之篇三:Access远程连接数据库和窗体打包部署
篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...