至此,我们完成了数据库的建立和初始填充工作,也建立的三个主要对象的模型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('/'); } }
该文件定义了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(); } }
评论(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补充补充就能完成了,有点小激动呢~