laravel大型项目系列教程(四)之显示文章列表和用户修改文章
小編心語:不知不覺已經第四部分了,非常感謝很多人給小編提的意見,改了很多bug,希望以后能繼續幫小編找找茬~小編也不希望誤導大家~這一節,主要講的是如何顯示文章列表和讓用戶修改文章,小編預告一下(一共有八節哦)如果有不懂得地方,或者本文呢沒有講清楚的地方,敬請期待下一章節。
一、前言
上節教程中實現了發布文章的功能,本節教程中將大概實現在首頁和用戶主頁分頁顯示文章和標簽列表、用戶能夠修改刪除文章。
二、Let's go
1.首頁顯示文章和標簽列表
我們需要在首頁顯示文章和標簽列表,修改views/index.blade.php
在custom.css中增加:
修改routes.php
上面Article::with()使用了預加載,可以減少查詢次數。
發布幾篇文章然后訪問首頁:
2.實現用戶主頁
我們在發表文章后應該能在用戶主頁看到文章列表,并能對文章進行操作,先在導航欄nav.blade.php的@else上面添加一個按鈕My Articles:
修改 home.blade.php: @extends('_layouts.default')@section('main') <div class="am-g am-g-fixed blog-g-fixed"><div class="am-u-sm-12"><table class="am-table am-table-hover am-table-striped "><thead><tr><th>Title</th><th>Tags</th>@if ($user->id == Auth::id())<th>Managment</th>@endif</tr></thead><tbody>@foreach ($articles as $article)<tr><td><a href="{{ URL::route('article.show', $article->id) }}">{{{ $article->title }}}</a></td><td>@foreach ($article->tags as $tag)<span class="am-badge am-badge-success am-radius">{{ $tag->name }}</span>@endforeach</td>@if ($user->id == Auth::id())<td><a href="{{ URL::to('article/'. $article->id . '/edit') }}" class="am-btn am-btn-xs am-btn-primary"><span class="am-icon-pencil"></span> Edit</a>{{ Form::open(array('url' => 'article/' . $article->id, 'method' => 'DELETE', 'style' => 'display: inline;')) }}<button type="button" class="am-btn am-btn-xs am-btn-danger" id="delete{{ $article->id }}"><span class="am-icon-remove"></span> Delete</button>{{ Form::close() }}</td>@endif</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^=delete]').on('click', function() {$('.am-modal-bd').text('Sure you want to delete it?');$('#my-confirm').modal({relatedTarget: this,onConfirm: function(options) {$(this.relatedTarget).parent().submit();},onCancel: function() {}});});}); </script> @stop
先添加一個UserController:
$ php artisan generate:controller UserController在UserController.php中增加:
public function articles(User $user) {return View::make('home')->with('user', $user)->with('articles', Article::with('tags')->where('user_id', '=', $user->id)->orderBy('created_at', 'desc')->get()); }在routes.php中增加:
Route::get('user/{user}/articles', 'UserController@articles');并修改原來的Route::get('home'):
Route::get('home', array('before' => 'auth', function() {return View::make('home')->with('user', Auth::user())->with('articles', Article::with('tags')->where('user_id', '=', Auth::id())->orderBy('created_at', 'desc')->get()); }));現在當用戶登錄或點擊My Articles按鈕后會跳轉到用戶主頁顯示文章列表,并且點擊標題時能跳轉到顯示文章內容頁面:
用戶主頁完成了,另外當在首頁和文章內容頁面點擊作者時也能跳轉到相應用戶的主頁,但是如果不是本用戶是沒有操作權限的,給views/index.blade.php中的作者增加鏈接地址:
<a href="{{ URL::to('user/' . $article->user->id . '/articles') }}">{{{ $article->user->nickname }}}</a>給articles/show.blade.php中的作者增加鏈接地址:
<a href="{{ URL::to('user/' . $article->user->id . '/articles') }}" style="cursor: pointer;">{{{ $article->user->nickname }}}</a>現在點擊這兩個超鏈接的時候就能跳轉到相應用戶的主頁了,但是沒有操作權限:
3.首頁分頁顯示文章
當文章很多時,我們就要分頁顯示了,Laravel已經為我們實現好了分頁邏輯,但它默認的是Bootstrap的樣式,由于我們使用AmazeUI,所以需要自定義表示器。先在app目錄創建一個名為Blog的文件夾,這個文件夾中主要放置我們自己寫的擴展類,在其中新建一個名為PaginationPresenter.php的文件,修改:
class PaginationPresenter extends Illuminate\Pagination\Presenter {public function getActivePageWrapper($text){return '<li class="am-active"><a href="">'.$text.'</a></li>';}public function getDisabledTextWrapper($text){return '<li class="am-disabled"><a href="">'.$text.'</a></li>';}public function getPageLinkWrapper($url, $page, $rel = null){return '<li><a href="'.$url.'">'.$page.'</a></li>';} }完成之后這個類還不能被找到,需要在composer.josn中的autoload classmap中增加"app/Blog",然后執行:
$ composer dump-autoload這樣這個類就能被找到了,現在創建分頁鏈接的視圖:
$ php artisan generate:view pagination修改pagination.blade.php:
<ul class="am-pagination am-pagination-centered">{{ with(new PaginationPresenter($paginator))->render() }} </ul>完成后修改app/config/view.php中的pagination的值為pagination,在routes.php中Route::get('/')內paginate()的參數就是指定每頁顯示的數量,由于我文章比較少,暫時把它設為2,最后在views/index.blade.php中文章顯示之后添加{{ $articles->links() }},現在訪問首頁就會看到如下分頁鏈接了:
4.修改文章的視圖
這步要實現在用戶主頁能夠修改文章了,自己的文章只能自己或者管理員修改,在ArticleController.php中增加一個過濾器:
public function canOperation($route, $request) {if (!(Auth::user()->is_admin or Auth::id() == Article::find(Route::input('article'))->user_id)){return Redirect::to('/');} }上面的Route::input('article')可以獲得路由參數,這里就是文章的id值,然后在構造函數中添加使用過濾器,再添加一個csrf過濾器:
$this->beforeFilter('csrf', array('only' => array('store', 'update', 'destroy'))); $this->beforeFilter('@canOperation', array('only' => array('edit', 'update', 'destroy')));創建修改文章的視圖:
$ php artisan generate:view articles.edit修改articles/edit.blade.php:
@extends('_layouts.default')@section('main') <div class="am-g am-g-fixed"><div class="am-u-sm-12"><h1>Edit Article</h1><hr/>@if ($errors->has())<div class="am-alert am-alert-danger" data-am-alert><p>{{ $errors->first() }}</p></div>@endif{{ Form::model($article, array('url' => URL::route('article.update', $article->id), 'method' => 'PUT', 'class' => "am-form")) }}<div class="am-form-group">{{ Form::label('title', 'Title') }}{{ Form::text('title', Input::old('title')) }}</div><div class="am-form-group">{{ Form::label('content', 'Content') }}{{ Form::textarea('content', Input::old('content'), array('rows' => '20')) }}<p class="am-form-help"><button id="preview" type="button" class="am-btn am-btn-xs am-btn-primary"><span class="am-icon-eye"></span> Preview</button></p></div><div class="am-form-group">{{ Form::label('tags', 'Tags') }}{{ Form::text('tags', Input::old('tags')) }}<p class="am-form-help">Separate multiple tags with a comma ","</p></div><p><button type="submit" class="am-btn am-btn-success"><span class="am-icon-pencil"></span> Modify</button></p>{{ Form::close() }}</div> </div><div class="am-popup" id="preview-popup"><div class="am-popup-inner"><div class="am-popup-hd"><h4 class="am-popup-title"></h4><span data-am-modal-closeclass="am-close">×</span></div><div class="am-popup-bd"></div></div> </div> <script>$(function() {$('#preview').on('click', function() {$('.am-popup-title').text($('#title').val());$.post('preview', {'content': $('#content').val()}, function(data, status) {$('.am-popup-bd').html(data);});$('#preview-popup').modal();});}); </script> @stop在routes.php中增加
Route::post('article/{id}/preview', array('before' => 'auth', 'uses' => 'ArticleController@preview'));這是為了修改文章時能夠預覽文章。
在ArticleController.php中修改:
public function edit($id) {$article = Article::with('tags')->find($id);$tags = '';for ($i = 0, $len = count($article->tags); $i < $len; $i++) {$tags .= $article->tags[$i]->name . ($i == $len - 1 ? '' : ',');}$article->tags = $tags;return View::make('articles.edit')->with('article', $article); }現在在用戶主頁點擊修改文章時會跳轉到修改頁面:
5.修改文章
在ArticleController.php添加修改文章的業務邏輯:
public function update($id) {$rules = ['title' => 'required|max:100','content' => 'required','tags' => array('required', 'regex:/^\w+$|^(\w+,)+\w+$/'),];$validator = Validator::make(Input::all(), $rules);if ($validator->passes()) {$article = Article::with('tags')->find($id);$article->update(Input::only('title', 'content'));$resolved_content = Markdown::parse(Input::get('content'));$article->resolved_content = $resolved_content;$tags = array_unique(explode(',', Input::get('tags')));if (str_contains($resolved_content, '<p>')) {$start = strpos($resolved_content, '<p>');$length = strpos($resolved_content, '</p>') - $start - 3;$article->summary = substr($resolved_content, $start + 3, $length);} elseif (str_contains($resolved_content, '</h')) {$start = strpos($resolved_content, '<h');$length = strpos($resolved_content, '</h') - $start - 4;$article->summary = substr($resolved_content, $start + 4, $length);}$article->save();foreach ($article->tags as $tag) {if (($index = array_search($tag->name, $tags)) !== false) {unset($tags[$index]);} else {$tag->count--;$tag->save();$article->tags()->detach($tag->id);}}foreach ($tags as $tagName) {$tag = Tag::whereName($tagName)->first();if (!$tag) {$tag = Tag::create(array('name' => $tagName));}$tag->count++;$article->tags()->save($tag);}return Redirect::route('article.show', $article->id);} else {return Redirect::route('article.edit', $id)->withInput()->withErrors($validator);} }這部分較難的是對Tag的處理,可能我的方法不是最好的。
這樣就能真正的實現修改了:
6.刪除文章
在ArticleController.php中增加:
public function destroy($id) {$article = Article::find($id);foreach ($article->tags as $tag) {$tag->count--;$tag->save();$article->tags()->detach($tag->id);}$article->delete();return Redirect::to('home'); }我們這里刪除文章其實是軟刪除,它在數據庫中還是存在的。
當點擊Yes后會發現文章被刪除了。
7.小結
本節教程完成了在首頁和用戶主頁顯示文章和標簽列表,用戶能夠管理自己的文章,但只在首頁實現了分頁顯示文章,你可以自己實現在用戶主頁也分頁顯示,在刪除文章確認提示的時候,你可以加上要刪除文章的標題,這樣用戶體驗會更好,你完全可以按你的想法進行實現。這節就到此結束了,我們已經實現了管理員用戶管理,下節就將完善管理員模塊,實現文章和標簽管理。
別忘記還有最后的代碼下載:
$ git clone https://github.com/shiyanlou/laravel-blog-4.git關于laravel的相關學習網站:
- Laravel官網
- 中文文檔1、中文文檔2
- 實驗樓論壇
- Laravel中文網問答社區
- PHPHub中文社區
- API文檔
- laravel.io
- LARACASTS
總結
以上是生活随笔為你收集整理的laravel大型项目系列教程(四)之显示文章列表和用户修改文章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java和WebSocket开发网页聊天
- 下一篇: Laravel大型项目系列教程(五)之文