至此,我们完成了数据库的建立和初始填充工作,也建立的三个主要对象的模型User, Picture, Comment,接下来要实现控制器部分了。
与其把所有路由逻辑写在一个 routes.php 文件中,你也许更希望用控制器类来组织它们。控制器可以把相关的路由逻辑组织在一个类中,而且可以使用由框架提供的更为强大的功能,比如自动依赖注入。关于控制器方面的文档参看。
一.创建控制器
在Laravel中,我们通过扩展 app/controllers 目录的BaseController类来创建控制器,我们所有的控制器都存在app/controllers目录中。文件管理方面这一点类似MODEL,使用一个文件当作入口来管理所有的同类文件。
1#......BaseController.php
这是基控制器,$layout指定了初始布局,指向views目录下的master.blade.php。
调用setupLayout方法在控制器有非空布局时实现这个布局。其他的控制器基本都可以继承该控制器。
<?php
class BaseController extends \Controller {
/**
* layout to use
* @var View
*/
protected $layout = 'master';
/**
* Setup the layout used by the controller.
*
* @return void
*/
protected function setupLayout()
{
if ( ! is_null($this->layout) )
{
$this->layout = View::make($this->layout);
}
}
}
2#......BlogController.php
__construct使我们能够在控制器内部指定过滤器,过滤器的定义在app/filters.php。
getIndex()获取主页显示的元素,每页显示20张图片,调用布局home,在home.blade.php中的{{content}}部分填充布局index,布局由构造出的20张图片的键值对数组生成,这一步相当于显示了主页。
getLogin()获取验证状态并转移页面到管理员控制面板
getLogout()登出用户
postRegister()注册验证,需要验证未使用用户名和未使用的邮箱地址
postLogin()登陆验证
<?php
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Schema;
class BlogController extends BaseController
{
public function __construct()
{
//updated: prevents re-login.
$this->beforeFilter('guest', ['only' => ['getLogin']]);
$this->beforeFilter('auth', ['only' => ['getLogout']]);
}
public function getIndex()
{
$pictures = Picture::orderBy('id', 'desc')->paginate(10);
$pictures->getFactory()->setViewName('pagination::slider');
$this->layout->title = 'Home Page | Picture Wall Blog';
$this->layout->main = View::make('home')->nest('content', 'index', compact('pictures'));
}
public function getSearch()
{
$searchTerm = Input::get('s');
$pictures = Picture::whereRaw('match(title,description) against(? in boolean mode)', [$searchTerm])
->paginate(10);
$pictures->getFactory()->setViewName('pagination::slider');
$pictures->appends(['s' => $searchTerm]);
$this->layout->with('title', 'Search: ' . $searchTerm);
$this->layout->main = View::make('home')
->nest('content', 'index', ($pictures->isEmpty()) ? ['notFound' => true] : compact('pictures'));
}
public function getLiking()
{
$pic_id = Input::get('pic_id');
if (Auth::check()){
$user_id = Auth::user()->id;
} else return 'not logined';
$like = DB::connection('mongodb')->table('likes')->where('picture_id', '=', $pic_id)->where('user_id', '=', $user_id)->get();
if (!empty($like)) return 'voted';
DB::connection('mongodb')->table('likes')->insert(array('user_id' => $user_id, 'picture_id' => $pic_id));
$count = DB::connection('mongodb')->table('count')->where('picture_id', '=', $pic_id)->lists('count');
if (empty($count)){
DB::connection('mongodb')->table('count')->insert(array('picture_id'=>$pic_id, 'count'=>'1'));
} else{
$up = $count[0]+1;
DB::connection('mongodb')->table('count')->where('picture_id',$pic_id)->
update(array('count'=>$up));
}
return "ok";
}
public function getLikes()
{
$pic_id = Input::get('pic_id');
$likecount = DB::connection('mongodb')->table('count')->where('picture_id', $pic_id)->lists('count');
if (empty($likecount)) return 0;
return $likecount[0];
}
public function getLogin()
{
$this->layout->title = 'login';
$this->layout->main = View::make('login');
}
public function getRegister()
{
$this->layout->title = 'register';
$this->layout->main = View::make('register');
}
public function postRegister()
{
$credentials = [
'username' => Input::get('username'),
'password' => Input::get('password'),
'email' => Input::get('email')
];
$rules = [
'username' => 'required',
'password' => 'required',
'email' => 'required|email'
];
$validator = Validator::make($credentials, $rules);
if ($validator->passes()) {
$userCheck = DB::table('users')->where('username',$credentials['username'])->get();
if (!empty($userCheck)){
return Redirect::back()->withInput()->with('failure', 'username already exists!');
}
$emailCheck = DB::table('users')->where('email',$credentials['email'])->get();
if (!empty($emailCheck)){
return Redirect::back()->withInput()->with('failure', 'mail address already exists!');
}
$user = array(
'username' => $credentials['username'],
'password' => Hash::make($credentials['password']),
'email' => $credentials['email'],
'created_at' => DB::raw('NOW()'),
'updated_at' => DB::raw('NOW()'),
);
DB::table('users')->insert($user);
Auth::attempt($credentials);
return Redirect::to('admin/dash-board')->withInput()->with('success', 'register succeed!!!');
} else {
return Redirect::back()->withErrors($validator)->withInput();
}
}
public function postLogin()
{
if (strcmp($_POST['operation'],"Register") == 0) return Redirect::to('register');
$credentials = [
'username' => Input::get('username'),
'password' => Input::get('password')
];
$rules = [
'username' => 'required',
'password' => 'required'
];
$validator = Validator::make($credentials, $rules);
if ($validator->passes()) {
if (Auth::attempt($credentials))
return Redirect::to('admin/dash-board');
return Redirect::back()->withInput()->with('failure', 'username or password is invalid!');
} else {
return Redirect::back()->withErrors($validator)->withInput();
}
}
public function getLogout()
{
Auth::logout();
return Redirect::to('/');
}
}
3#......PictureController.php
该文件定义了Picture的控制器,包括列举Picture,显示Picture,新建、编辑的界面,删除、保存、更新的操作等。这些方法会在app/routes.php中被引用。
其中用到了验证器的相关知识(请注意正则匹配的格式),参考
<?php
class PictureController extends BaseController
{
/* get functions */
public function listPicture()
{
$pictures = Picture::orderBy('id', 'desc')->paginate(10);
$this->layout->title = 'Picture listings';
$this->layout->main = View::make('dash')->nest('content', 'pictures.list', compact('pictures'));
}
public function showPicture(Picture $picture)
{
$comments = $picture->comments()->get();
$this->layout->title = $picture->title;
$this->layout->main = View::make('home')->nest('content', 'pictures.single', compact('picture', 'comments'));
}
public function newPicture()
{
$this->layout->title = 'New Picture';
$this->layout->main = View::make('dash')->nest('content', 'pictures.new');
}
public function editPicture(Picture $picture)
{
$this->layout->title = 'Edit Picture';
$this->layout->main = View::make('dash')->nest('content', 'pictures.edit', compact('picture'));
}
public function deletePicture(Picture $picture)
{
DB::connection('mongodb')->table('likes')->where('picture_id',$picture->id)->delete();
DB::connection('mongodb')->table('count')->where('picture_id',$picture->id)->delete();
$picture->delete();
return Redirect::route('picture.list')->with('success', 'Picture is deleted!');
}
/* picture functions */
public function savePicture()
{
$pre = "images/".date("YmdHis",time());
$picture = [
'title' => Input::get('title'),
'description' => Input::get('description'),
'image' => $_FILES['picture']['name'],
];
$rules = [
'title' => 'required',
'description' => 'required',
'image' => array('regex:/^[^&%]*\\.(jpg|gif|jpeg|png|bmp)$/u'),
];
$messages = array(
'regex' => 'Please check there is no & and % character in the file path and is an image file!!'
);
$valid = Validator::make($picture, $rules, $messages);
if ($valid->passes()) {
$file_path = $_FILES['picture']['tmp_name'];
$image_path = "F:/mxampp/htdocs/piclist/public/".$pre.'/'.$_FILES['picture']['name'];
mkdir("F:/mxampp/htdocs/piclist/public/".$pre);
if (!move_uploaded_file($file_path, $image_path)){
return Redirect::to('admin/dash-board')->with('failure', 'wooops!!! failed on saving~');
//return Redirect::to('admin/dash_board')->with('failure', 'not valid picture');
} else{
$picture['image'] = $pre.'/'.$_FILES['picture']['name'];
$picture = new Picture($picture);
$picture->comment_count = 0;
$picture->save();
return Redirect::to('admin/dash-board')->with('success', 'Picture is saved!');
}
} else
return Redirect::back()->withErrors($valid)->withInput();
}
public function updatePicture(Picture $picture)
{
$data = [
'title' => Input::get('title'),
'description' => Input::get('description'),
];
$rules = [
'title' => 'required',
'description' => 'required',
];
$valid = Validator::make($data, $rules);
if ($valid->passes()) {
$picture->title = $data['title'];
$picture->description = $data['description'];
if (count($picture->getDirty()) > 0) /* avoiding resubmission of same content */ {
$picture->save();
return Redirect::back()->with('success', 'Picture is updated!');
} else
return Redirect::back()->with('success', 'Nothing to update!');
} else
return Redirect::back()->withErrors($valid)->withInput();
}
}
4#......Comment.php
评论(Comment)的控制器,定义了所有评论相关的方法,注意picture->comment_count的改变,每次更新时也要更新这个计数器。
<?php
class CommentController extends BaseController
{
/* get functions */
public function listComment()
{
$comments = Comment::orderBy('id', 'desc')->paginate(20);
$this->layout->title = 'Comment Listings';
$this->layout->main = View::make('dash')->nest('content', 'comments.list', compact('comments'));
}
public function newComment(Picture $picture)
{
$comment = [
'commenter' => Input::get('commenter'),
'email' => Input::get('email'),
'comment' => Input::get('comment'),
];
$rules = [
'commenter' => 'required',
'email' => 'required | email',
'comment' => 'required',
];
$valid = Validator::make($comment, $rules);
if ($valid->passes()) {
$comment = new Comment($comment);
$picture->comments()->save($comment);
$picture->increment('comment_count');
/* redirect back to the form portion of the page */
return Redirect::to(URL::previous() . '#reply')
->with('success', 'Comment has been submitted!');
} else {
return Redirect::to(URL::previous() . '#reply')->withErrors($valid)->withInput();
}
}
public function showComment(Comment $comment)
{
if (Request::ajax())
return View::make('comments.show', compact('comment'));
// handle non-ajax calls here
//else{}
}
public function deleteComment(Comment $comment)
{
$picture = $comment->picture;
$comment->delete();
$picture->decrement('comment_count');
return Redirect::back()->with('success', 'Comment deleted!');
}
/* picture functions */
public function updateComment(Comment $comment)
{
$comment->save();
$comment->picture->comment_count = Comment::where('picture_id', '=', $comment->picture->id)->count();
$comment->picture->save();
return Redirect::back();
}
}
二.模型与路由的绑定
在app/routes.php中实现:
/* Model Bindings */
Route::model('picture', 'Picture');
Route::model('comment', 'Comment');
下一节将介绍路由和过滤器的相关设计
__________________________________________________________________________________________________
下一章将介绍路由和过滤器的实现,实现的路由和过滤器之后,我们整个博客的逻辑部分就算全部完成了~
对每个模型有对应的数据表,对模型的变化定义在控制器,通过路由的行为来调用控制器的方法,实现了用户与服务端交互的目的。
完成路由和过滤器之后,只要把所有页面的UI补充补充就能完成了,有点小激动呢~