Laravel最为最优雅的PHP框架,很多学习PHP的小伙伴造就对Laravel垂涎欲滴。今天就来实现你的愿望,让我们一起从零开始,利用Laravel实现Web应用最常见的注册和登录功能!所有的课程源码已放在Github上:https://github.com/JellyBool/laravel-start Race Start !
首先我们来明确一下我们这个课程需要的东西:
Laravel 4.2
Bootstrap 3.3
Laravel
就是我们关心的核心部分,Bootstrap
用来快速设置一些前端的CSS样式。
1.安装Laravel
简单说明之后我们来进入下一步,安装Laravel,在这我们是通过Composer来安装,打开命令行终端,执行:
cd Sites
Sites
就是web应用的根目录,你可以根据需要换成你自己的根目录,然后再执行:
composer create-project laravel/laravel laravel
laravel
就是你的应用目录名,你可以取一个你喜欢的名字。执行上面的命令之后,等一段时间(毕竟在国内,网速是个大坑),安装完以后你会得到这一堆目录:
我们主要操作models
和 controllers
和 views
这三个目录:这就是MVC的构成啊!
2.安装Bootstrap
然后再命令行执行:
cd laravel/public/packages
这里的laravel
与上面的应用目录对应,如果你在安装的时候用了其他的名字,请对应换上。来到packages
这个目录后安装Bootstrap
,直接在命令行执行:
bower install bootstrap
这个比较快,然后等这个下载完之后你就会得到最新的稳定版Bootstrap。在目录packages
目录下的 bower_components/bootstrap/dist/
这里就包含了Bootstrap的css,js,fonts这三个我们在开发过程中经常用到的样式文件,js和字体文件。成功后你将看到这个:
注:这里使用的bower这个工具,它负责管理一些前端的包。
到这里,我们的前期工作已经准备好了。不过在进入下一步之前,我们得先确保我们的laravel/app/storage
目录有相应的写入权限,所以回到 laravel
目录,如果你在安装完bower之后没动过命令行,可以直接通过:
cd ../../
回到 laravel
目录,然后在执行:
chmod -R 755 app/storage
这一步搞定之后我们就可以进入真正的开发阶段了。
3.配置数据库并建表:
在开始配置之前,我们要为我们的laravel应用创建一个数据库,我将它命名为laravel-start
,
然后在编辑器中打开app/config/database.php
文件,对相应的数据库配置项填入,如:
'default' => 'mysql',
// 数据库连接
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => '127.0.0.1',
'database' => 'laravel-start',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
连接完数据库之后,还得创建一个Users表,你可以直接在数据库中创建Users表,也可以利用Laravel的artisan来创建,这里我们使用Laravel的artisan来建表,顺道了解一点点关于Laravel migrate的知识。执行下面语句:
php artisan migrate:make create-users-table
以上命令会创建一个migrate文件(文件位于app/database/migrations
目录下),这个文件的名字就是create-users-table
,然后我们可以通过编辑刚刚生成的migrate文件来创建Users表。
public function up() {
Schema::create('users', function($table){
$table->increments('id');
$table->string('username', 20);
$table->string('email', 100)->unique();
$table->string('password', 64);
$table->string('remember_token',62)->default('default');
$table->timestamps();
});
}
上面的方法使用了laravel的Schema Builder类,上面这段代码使用up()
方法的创建一个users表,这个表里有5个字段:id
自增 ,username
长度20以内 ,email
长度100以内并且是唯一的 ,password
长度64以内 ,remember_token
是为了在登录的时候更方便实用,Laravel会自动将token值填充进来,但在最开始你必须设一个默认值,timestamp
当前的时间戳。在这我们需要注意的一点是:最好在down()
加上下面的代码,以防某天我们需要删除Users这个表。
public function down()
{
Schema::drop('users');
}
上面的都做好以后,执行一下下面这一句神奇的命令:
php artisan migrate
有图有真相:
终于,我们的前奏搞完了,可以正式来鲁Laravel了。
4.启动服务来试试
直接在laravel
目录执行:
php artisan serve
打开浏览器,输入localhost:8000
,回车,Bingo!
OK,先给自己三十秒的掌声时间,如果你顺利地走到了这一步的话。恭喜你,你已经进入Laravel的大门,更多惊喜我们再一一道来.....
5.创建公用视图
好了,我们现在开始了,首先在app/views/
文件夹下创建一个layouts
文件夹,再再这个文件夹下新建一个php文件,命名为main.blade.php
,在这个文件里写上下面这些代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>发现Laravel 4之美</title>
</head>
<body>
</body>
</html>
PS:
layouts
文件夹通常用来存放视图文件的功用部分,比如一些网页的头部<header>
和尾部<footer>
,这里就是存放了头部<header>
部分
感觉main.blade.php
的名字很奇怪?不用担心,Laravel的视图文件命名遵循filename.blade.php
的规则,因为Laravel是用Blade这个模板引擎解析的,你不用深究,就照着上面的名字规则来命名视图文件就OK
为视图文件添加CSS样式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>发现Laravel 4之美</title>
{{HTML::style('packages/bower_components/bootstrap/dist/css/bootstrap.min.css') }}
{{ HTML::style('css/main.css')}}
</head>
<body>
</body>
</html>
没错,就是在原来的main.blade.php
的基础上添加两行代码;然后我们来创建我们的main.css
,这个主要是用来放我们自己定义的样式。在public
文件夹下创建css
文件夹,在css
文件夹创建main.css
文件,大功告成。
添加导航栏。在main.blade.php
文件的<body>
标签中加上以下代码:
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand hidden-sm" href="/">Laravel新手上路</a>
</div>
<ul class="nav navbar-nav navbar-right hidden-sm">
<li>{{ HTML::link('users/register', '注册') }}</li>
<li>{{ HTML::link('users/login', '登陆') }}</li>
</ul>
</div>
</div>
</body>
上面只是引用了一些简单的Bootstrap的class,也没什么难的,不用伤心。
到这里基本的功用部分就结束了,但是我们的追求从不会这么low,所以为了更好地与用户交互,我们希望在用户进行某个操作之后给出一些反馈,比如注册成功的时候说:少年,你已成功注册本站,恭喜恭喜。等,于是乎,我们再为main.blade.php
添加一点点代码:
<div class="container">
@if(Session::has('message'))
<p class="alert">{{ Session::get('message') }}</p>
@endif
</div>
为了现实这些反馈信息给用户,我们得使用Session::get('message')
方法,当然,我们得首先从逻辑上判断一下这个message
是否存在,所以这里用了一个简单的if
判断。
在blade引擎的视图中
if
的使用格式是
@if(conditions)
#code...
@endif
到这里就结束了么?NO,如果到这里就结束的话,其他的视图文件是怎么插入main.blade.php
的<body></body>
之间的呢?所以,不要忘了还有一个重要的事: {{ $content }}
,于是乎,上面的代码就变成了这样:
<div class="container">
@if(Session::has('message'))
<p class="alert">{{ Session::get('message') }}</p>
@endif
{{ $content }}
</div>
{{ $content }}
在这里就是表示其他的视图文件内容,你可以在理解上将其他的视图当作一个字符串来理解,只不过这个字符串很长,而且恰好包含了HTML标签而已。下面你将体会到这种想法。
创建完我们的公用视图main.blade.php
后,我们先来为main.css
添加我们的CSS样式:
body {
padding-top: 60px;
}
.form-signup, .form-signin {
margin: 0 auto;
}
因为我们在main.blade.php
文件中使用了<div class="navbar navbar-inverse navbar-fixed-top">
,Bootstrap的navbar
高为40px
,所以我将body
样式设为padding-top: 60px;
避免下面的注册表单被navbar
覆盖。
终于要进入正题
我擦,前面搞这么久才进入正题?对的,我说的是从这里开始我们就开始进入Laravel的Controller世界了,别高潮那么快,更好的事情还在后头。
6.创建UsersController
来到app/controllers
文件夹,并在这里创建UsersController.php
文件并加入下面的代码:
<?php
class UsersController extends BaseController {
}
?>
然后告诉我们的UsersController
我们要使用main.blade.php
作为我们的layouts,所以:
<?php
class UsersController extends BaseController {
protected $layout = "layouts.main";
}
?>
这里使用了路径别名,你不用layouts/main.blade.php
,你只需要layouts.main
,Laravel会自动帮你找到layouts
下相应的文件。
7.实现注册
接着为我们的UsersController
添加用户注册时访问到的方法:
public function getRegister() {
$this->layout->content = View::make('users.register');
}
这里我们将content
制定为users/register.blade.php
文件(我们等下会创建这个文件),如果你够细心的话,你可能就注意到了:这里的content
就是上面我们在main.blade.php
写的{{ $content }}
,也就是说等下渲染视图的时候,我们的users/register.blade.php
文件会替换掉main.blade.php
的{{ $content }}
进行显示。现在,清晰了没?还不清晰?随时联系我....如果你不嫌我长得丑的话。
自然而然的,我们现在要做的就是创建users/register.blade.php
这个文件了,来到views
文件夹 ,创建一个新的文件夹users/
,再在里面新建register.blade.php
,写上下面这些内容:
{{ Form::open(array('url'=>'users/create', 'class'=>'form-signup')) }}
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">欢迎注册</h3>
</div>
<div class="panel-body">
{{ Form::open(array('url'=>'users/create', 'class'=>'form-signup')) }}
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<fieldset>
<div class="form-group">
{{ Form::text('username', null, array('class'=>'form-control', 'placeholder'=>'用户名')) }}
</div>
<div class="form-group">
{{ Form::text('email', null, array('class'=>'form-control', 'placeholder'=>'邮箱')) }}
</div>
<div class="form-group">
{{ Form::text('password', array('class'=>'form-control', 'placeholder'=>'密码')) }}
</div>
<div class="form-group">
{{ Form::text('password_confirmation', array('class'=>'form-control', 'placeholder'=>'确认密码')) }}
</div>
{{ Form::submit('马上注册',array('class'=>'btn btn-large btn-success btn-block')) }}
</fieldset>
{{ Form::close() }}
</div>
</div>
</div>
</div>
</div>
这里我们使用了Laravel的Form类来创建我们的注册表单,首先调用open()方法,表示创建表单的开始,并且我们也为其通过数组的形式传人一些参数,url表示表到提交的地址,class就是表示CSS样式的类。接下来我们使用了:
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
@foreach循环将每个表单的错误信息输出。因为我们在让用户注册的时候总是要验证一下用户输入的数据是否满足我们设定的规则,比如邮箱这一栏我们规定它必须为正确的邮箱形式,而如果用户没有输入正确的邮箱格式,我们就会返回错误信息给用户看。That's it.
再下来需要说明的就是几个Form输入框的创建方式了:
{{ Form::text() }} //创建type=text 输入框
{{ Form::password() }}//创建type=password 输入框
{{ Form::submit() }}//创建type=submit 输入框
各个输入框的值我们都设为null,因为我们用placeholder来更好的替代了,第三个参数是你可以通过一个数组来传人相应的HTML选项来实现我们的布局,比如上面的array('class'=>'form-control', 'placeholder'=>'确认密码')
等。
最后别忘我们要用{{ Form::close() }}
来结束表单。
到这里我们就把注册页面搞定了,紧接下来就是正确地设置好我们的路由以使我们能正确访问到我们的getRegister()
方法。于是,带着神圣的使命感,我们打开app/routes.php
这个文件,首先可以将里面的:
Route::get('/', function()
{
return View::make('hello');
});
这几行代码干掉(你可以注视掉或者直接删了,建议是注释),然后再添上下面这一行代码;
Route::controller('users', 'UsersController');
注意到第一个参数users
没,这个告诉就是说我们在访问UsersController
的方法的时候我们遵循下面这个格式:
/users/actionName
比如我们想访问UsersController
的getRegister()
,我们可以在浏览器地址栏输入的格式是:
/users/register
于是,打开你的浏览器,在地址栏输入:
http://localhost:8000/users/register
见证奇迹吧。是不是很爽!哈哈哈。
如果现在你在这个注册表单添上相应的注册信息,然后点击注册的话,你会得到一个意外的错误:NotFoundHttpException
!那是因为我们还没有为注册表单写提交地址:users/create
。所以我们自然要来到UsersController
中,为其添上postCreate()
:
public function postCreate() {
}
这样我们就把地址users/create
正确地搞定了,只是我们还没有为其添加相应的条件判断语句,因为我们首先要在这里说明一点就是:getRegister()
和postCreate()
的不同,没错前面的get
或post
就是代表http的提交方式,我们在注册表单中使用的是post
方法,所以这里要使用postCreate()
。
说明上面的细节之后,我们还要做一件非常重要的事:表单验证。即是先在用户提交表单的时候验证其输入数据的合法性,以便于我们在数据库中能存储正确的数据,这里就联系到前面的:
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
这里的$error
就是我们在用户输入数据不合法的时候返回给用户的错误提示信息。所以,我们现在app/models/User.php
中添加我们的表单验证规则(我一般将验证规则放在模型modal中):
public static $rules = array(
'username'=>'required|alpha|min:2',
'email'=>'required|email|unique:users',
'password'=>'required|alpha_num|between:6,12|confirmed',
'password_confirmation'=>'required|alpha_num|between:6,12'
);
说明一下上面的一些规则表示什么意思:
required:必填的,不能为空
alpha:字母
email:邮件格式
unique:users:唯一,参考users表的设置
alpha_num:字母或数字
between:长度位于哪两个数字之间
confirmed:需要确认的
在我们有了验证规则,我们再来完善我们的postCreate()
,即为其添加一些条件判断使用户在注册时可以保存用户的注册信息和进一步引导用户到登陆页面:
我们来一步一步地理清思路:首先判断用户提交的数据是否通过了验证
public function postCreate() {
$validator = Validator::make(Input::all(), User::$rules);
if ($validator->passes()) {
// 验证通过就存储用户数据
} else {
// 验证没通过就显示错误提示信息
}
}
}
上面我们通过Input::all()
来获取表单传过来的值,又调用User::$rules
来获得验证规则,最后通过把这两个以参数的形式传入Validator::make()
实现验证,下面的判断语句就很清晰了,验证通过后干嘛,没通过又该干嘛。思路清晰就OK。
接着我们再来完善我们的postCreate()
代码:
if ($validator->passes()) {
$user = new User;//实例化User对象
$user->username = Input::get('username');
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->save();
return Redirect::to('users/login')->with('message', '欢迎注册,好好玩耍!');
} else {
// 验证没通过就显示错误提示信息
}
上面的我们通过Input::get('fieldName')
来获得相应的表单输入框的值,这里需要注意的是我们对密码进行了加密,因为我们都是棒棒的工程师,不会像之前的CSDN一样保存明文密码的,所以在密码这一栏我们使用Hash::make()
来加密传入的密码。然后我们通过 $user->save()
来将我们的数据保存到数据库中。数据保存之后,我们用Redirect::to()
将页面跳转到users/login
,并通过width将注册成功的信息返回给用户。
Redirect::to()
的参数规则是:controller/action
。前面是控制起,后面就是具体的方法名。
上面是验证通过的情况,现在我们看看验证没有通过的情况:
if ($validator->passes()) {
$user = new User;//实例化User对象
$user->username = Input::get('username');
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->save();
return Redirect::to('users/login')->with('message', '欢迎注册,好好玩耍!');
} else {
return Redirect::to('users/register')->with('message', '请您正确填写下列数据')->withErrors($validator)->withInput();
}
这里如果用户没有通过验证,我让其重定向到注册页,并通过withErrors($validator)
将错误信息传到注册页面,通过withInput()
将没有输错的数据也传给注册页面(正确来说是传给register方法,不过你可以根据上面那样理解,个人觉得也还OK),这样一来,我们就有了错误信息和一些正确的表单信息(不用用户多次输入),以提高整个过程的用户体验。
再进一步,我们在开发的时候永远不要忘记一件很重要的事:安全。那么在这里我们需要POST提交表单,我们就要保证它不会被CSRF攻击,解决这个问题我们需要在UsersController
里添加下面的代码:
public function __construct() {
$this->beforeFilter('csrf', array('on'=>'post'));
}
构造方法请放在其他方法前面。
8.实现登录
接下来的一步就是创建login的视图文件了,我们依旧来到我们最熟悉的views/users/
下,新建文件名为login.blade.php
的文件,在里面放上以下的代码:
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">欢迎登录</h3>
</div>
<div class="panel-body">
{{ Form::open(array('url'=>'users/signin', 'class'=>'form-signin')) }}
<fieldset>
<div class="form-group">
{{ Form::text('email', null, array('class'=>'form-control', 'placeholder'=>'邮箱')) }}
</div>
<div class="form-group">
{{ Form::password('password', array('class'=>'form-control', 'placeholder'=>'密码')) }}
</div>
{{ Form::submit('马上登录',array('class'=>'btn btn-large btn-success btn-block')) }}
</fieldset>
{{ Form::close() }}
<hr/>
</div>
</div>
</div>
</div>
</div>
这里的一些要点跟register.blade.php
一样,你不明白的话可以看看前面的。然后我们需要在UsersController
里面定义getLogin()
方法:
public function getLogin() {
$this->layout->content = View::make('users.login');
}
这里也是指定了content
的模版为users/login.blade.php
,道理跟前面一样。
这时候我们就可以注册新用户了,如果你的浏览器还保留在http://localhost:8000/users/register
你可以试着输入你的用户名,邮箱,密码来注册一个,当然你也可以故意输错,看看会有什么信息返回给你。enjoy!
正常情况下,你注册完之后就吼跳到登录界面(已经写好了),但是我们在登录的时候也需要验证,如果你仔细看上面的login.blade.php
的话,你会发现我们在这里将用户的登录表单提交地址设置为'url'=>'users/signin'
,所以接下来的一步就是为UsersController
补充postSignin()
方法:
public function postSignin() {
if (Auth::attempt(array('email'=>Input::get('email'), 'password'=>Input::get('password')))) {
return Redirect::to('users/dashboard')->with('message', '欢迎登录');
} else {
return Redirect::to('users/login')->with('message', '用户名或密码错误')->withInput();
}
}
这里我们使用Auth
类来验证用户输入的信息是否和数据库的信息一致,如果验证通过,那么我们就将用户重定向到users/dashboard
,如果没通过,就重新跳回登录页,情况跟注册时候几乎一模一样,我相信你看得懂。
既然是重定向到users/dashboard
那么我们就来写写getDashboard()
方法,到这里可能不用我说你都知道应该在UsersController
添加下面的代码:
public function getDashboard() {
$this->layout->content = View::make('users.dashboard');
}
这里再多说一句,这个Dashboard的页面一般是在登录后才能看到的,为了限制一些没登录的人到处乱逛,我们只需要在UsersController
中的构造函数加一行代码,变成这样的:
public function __construct() {
$this->beforeFilter('csrf', array('on'=>'post'));
$this->beforeFilter('auth', array('only'=>array('getDashboard')));
}
现在逻辑是不是很清晰,我们接下来的一步自然是创建dashboard.blade.php
文件了,这个从getDashboard()
看出我们依然是将这个视图文件存在views/users/
目录下,我们就简单地在dashboard.blade.php
写上几行入门级的HTML:
<div class="welcome">
<center>
<a href="http://www.jellybool.com" target="_blank">
<img src="https://o0dpls1ru.qnssl.com/7680dd9d-c0e4-42ea-86b8-ddd63d07faa6.png" >
</a>
</center>
<center><h1>欢迎来到管理面板!</h1></center>
</div>
写到这里我们还不能登录,因为在Laravel中auth
过滤(filter)会默认将没登录的用户重定向到/login
,但我们需要的是重定向到users/login
,所以我们需要自定义我们的filter
规则,打开app/filter.php
,在代码的开始加上下面的代码:
Route::filter('auth', function()
{
if (Auth::guest()) return Redirect::guest('users/login');
});
到这里就大功告成了,如果你之前注册了一个用户,请用你的邮箱和密码到
http://localhost:8000/users/login
尝试登录一下,你会发现:Bingo!!!登录进去了!
9.实现退出
但是细心的你发现了没,我们还有一个需要完善的地方.....没错!就是我们的导航,我们已经登录进去了,它还是显示登录
和注册
,不科学啊!所以回到最初我们的main.blade.php
在链接部分我们将它改为:
<ul class="nav navbar-nav navbar-right hidden-sm">
@if(!Auth::check())
<li>{{ HTML::link('users/register', '注册') }}</li>
<li>{{ HTML::link('users/login', '登陆') }}</li>
@else
<li>{{ HTML::link('users/logout', '退出') }}</li>
@endif
</ul>
没错,我们为导航这里加入了条件判断语句,如果用户没有通过Auth::check()
,也就是没有登录的话,我们显示登录
和注册
,如果登录了就显示退出
,
既然有了users/logout
这个链接,那么我们就会想到在UsersController
写这个getLogout()
方法,而且这个方法是负责清理用户的登录信息的,所以:
public function getLogout() {
if(Auth::check())
{
Auth::logout();
}
return Redirect::to('users/login')->with('message','你现在已经退出登录了!');
}
这里我们Auth::logout()
将用户的登录信息(主要就是session信息)清除掉,然后再将用户重定向到登录界面。
10.最后的最后
这个小教程写到这里就基本结束了,希望各位玩的愉快。最后多说一句:编程是我们最容易学习的超能力,永远要相信自己可以改变世界!
Thank You all.