Laravel大型项目系列教程(五)之文章和标签管理

本节教程将大概完成文章和标签管理。

1.文章管理

首先创建管理后台文章列表视图:

$ php artisan generate:view admin.articles.list

修改views/admin/articles/list.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><th>Author</th><th>Managment</th></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><td><a href="{{ URL::to('user/' . $article->user->id . '/articles') }}">{{{ $article->user->nickname }}}</a></td><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></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

nav.blade.php中增加一个Articles的超链接:

<li class="{{ (isset($page) and ($page == 'articles')) ? 'am-active' : '' }}"><a href="{{ URL::to('admin/articles') }}">Articles</a></li>

创建一个管理员控制器,在app/controllers下创建一个名为AdminController.php的文件,修改:

class AdminController extends \BaseController {public function articles(){return View::make('admin.articles.list')->with('articles', Article::with('user', 'tags')->orderBy('created_at', 'desc')->get())->with('page', 'articles');}
}

Route::group(array('prefix' => 'admin')中增加:

Route::get('articles', 'AdminController@articles');

管理文章可以重用上节教程写的业务逻辑,修改下ArticleController.php,把destroy()中最后的Redirect::to('home')改成Redirect::back(), 再修改一下home.blade.php,加一个是否是管理员的判断,这样当点击作者跳转到用户主页时,除了作者自己管理员也能操作文章:

@if ($user->id == Auth::id() or Auth::user()->is_admin)

现在点击导航栏的Articles,就会出现所有的文章:

这样管理员就可以操作所有的文章了。

我们还可以再修改下admin/users/list.blade.php,当点击用户列表的昵称时也会跳转到用户主页:

<a href="{{ URL::to('user/' . $user->id . '/articles') }}">{{{ $user->nickname }}}</a>

现在访问用户列表页面:

2.显示标签列表

创建一个标签列表视图:

$ php artisan generate:view admin.tags.list

修改admin/tags/list.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>TagName</th><th>ArticleCount</th><th>CreateDateTime</th><th>Managment</th></tr></thead><tbody>@foreach ($tags as $tag)<tr><td>{{{ $tag->name }}}</td><td>{{ $tag->count }}</td><td>{{ $tag->created_at->format('Y-m-d H:i') }}</td><td><a href="{{ URL::to('tag/'. $tag->id . '/edit') }}" class="am-btn am-btn-xs am-btn-primary"><span class="am-icon-pencil"></span> Edit</a>{{ Form::open(array('url' => 'tag/' . $tag->id, 'method' => 'DELETE', 'style' => 'display: inline;')) }}<button type="button" class="am-btn am-btn-xs am-btn-danger" id="delete{{ $tag->id }}"><span class="am-icon-remove"></span> Delete</button>{{ Form::close() }}</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^=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

再在nav.blade.php中增加Tags选项:

<li class="{{ (isset($page) and ($page == 'tags')) ? 'am-active' : '' }}"><a href="{{ URL::to('admin/tags') }}">Tags</a></li>

Route::group(array('prefix' => 'admin')中增加:

Route::get('tags', 'AdminController@tags');

AdminController.php中增加:

public function tags() {return View::make('admin.tags.list')->with('tags', Tag::all()->orderBy('count', 'desc'));
}

现在点击导航栏上方的Tags超链接:

3.修改标签

创建修改标签的视图:

$ php artisan generate:view tags.edit

修改views/tags/edit.blade.php

@extends('_layouts.default')@section('main')
<div class="am-g am-g-fixed"><div class="am-u-sm-12"><h1>Edit Tag</h1><hr/>@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($tag, array('url' => URL::route('tag.update', $tag->id), 'method' => 'PUT', 'class' => "am-form")) }}<div class="am-form-group">{{ Form::label('name', 'TagName') }}{{ Form::text('name', Input::old('name')) }}</div><p><button type="submit" class="am-btn am-btn-success"><span class="am-icon-pencil"></span> Modify</button></p>{{ Form::close() }}</div>
</div>
@stop

创建标签控制器:

$ php artisan generate:controller TagsController

修改TagsController.php

public function __construct()
{$this->beforeFilter('auth', array('only' => array('create', 'store', 'edit', 'update', 'destroy')));$this->beforeFilter('csrf', array('only' => array('store', 'update', 'destroy')));
}public function edit($id)
{return View::make('tags.edit')->with('tag', Tag::find($id));
}public function update($id)
{$rules = array('name' => array('required', 'regex:/^\w+$/'),);$validator = Validator::make(Input::only('name'), $rules);if ($validator->passes()) {Tag::find($id)->update(Input::only('name'));return Redirect::back()->with('message', array('type' => 'success', 'content' => 'Modify tag successfully'));} else {return Redirect::back()->withInput()->withErrors($validator);}
}

把这个控制器加到routes.php中:

Route::resource('tag', 'TagController');

现在就能修改标签了:

4.删除标签

修改TagsController.php

public function destroy($id)
{$tag = Tag::find($id);$tag->count = 0;$tag->save();foreach ($tag->articles as $article) {$tag->articles()->detach($article->id);}return Redirect::back();
}

我这里删除标签只是把它的文章数置为0,然后清除与相关文章的关联,你可以自己试下删除一个标签,再看看文章的标签是否去除了。

5.关联标签

当我们点击首页文章、标签栏和显示文章内容的标签的时候应该跳转到显示相应标签下所有文章的页面:

我们对上述地方加上超链接地址:

<a href="{{ URL::to('tag/' . $tag->id . '/articles') }}">{{ $tag->name }}</a>

创建指定标签的文章列表视图:

$ php artisan generate:view articles.specificTag

修改views/articles/specificTag.blade.php

@extends('_layouts.default')@section('main')
<div class="am-g am-g-fixed"><div class="am-u-sm-12"><br/><blockquote>Tag: <span class="am-badge am-badge-success am-radius">{{{ $tag->name }}}</span></blockquote>@foreach ($articles as $article)<article class="blog-main"><h3 class="am-article-title blog-title"><a href="{{ URL::route('article.show', $article->id) }}">{{{ $article->title }}}</a></h3><h4 class="am-article-meta blog-meta">by <a href="{{ URL::to('user/' . $article->user->id . '/articles') }}">{{{ $article->user->nickname }}}</a> posted on {{ $article->created_at->format('Y/m/d H:i') }} under @foreach ($article->tags as $tag)<a href="{{ URL::to('tag/' . $tag->id . '/articles') }}" style="color: #fff;" class="am-badge am-badge-success am-radius">{{ $tag->name }}</a>@endforeach</h4><div class="am-g"><div class="am-u-sm-12">@if ($article->summary)<p>{{ $article->summary }}</p>@endif<hr class="am-article-divider"/></div></div></article>@endforeach{{ $articles->links() }}</div>
</div>
@stop

TagController.php增加:

public function articles($id)
{$tag = Tag::find($id);$articles = $tag->articles()->orderBy('created_at', 'desc')->paginate(10);return View::make('articles.specificTag')->with('tag', $tag)->with('articles', $articles);
}

routes.phpRoute::resource('tag', 'TagController');的上方增加:

Route::get('tag/{id}/articles', 'TagController@articles');

现在当我们点击页面上的标签时,就会显示该标签下的所有文章了:

6.显示所有标签

我们还需要一个显示所有标签的页面,先创建视图:

$ php artisan generate:view tags.list

修改views/tags/list.blade.php

@extends('_layouts.default')@section('main')
<div class="am-g am-g-fixed"><div class="am-u-sm-12"><h1>All Tags</h1><hr/>@foreach ($tags as $tag)<a href="{{ URL::to('tag/' . $tag->id . '/articles') }}" class="am-badge am-radius {{ array('', 'am-badge-primary', 'am-badge-secondary', 'am-badge-success', 'am-badge-warning', 'am-badge-danger')[rand(0, 5)] }}">{{{ $tag->name }}} {{ $tag->count }}</a>@endforeach<br/><br/></div>
</div>
@stop

现在点击首页的Tags链接时就会跳转到显示所有标签的页面了:

7.小结

本节教程就到此结束了,这个博客系统想要实现的功能也基本完成了,下节开始将讲解优化、单元测试、部署和扩展开发等内容,你可以继续完善,例如在管理文章和标签的时候提供一个搜索功能,给它们都加上分页,在首页加上一个搜索文章的功能,给文章加上评论功能等等,在评论功能方面现在有很多第三方评论插件,可以快速帮你实现。

最后的代码下载:

$ git clone https://github.com/shiyanlou/laravel-blog-5.git

laravel学习网站相关资料:
- Laravel官网
- 中文文档1、中文文档2
- 实验楼论坛
- Laravel中文网问答社区
- PHPHub中文社区
- API文档
- laravel.io
- LARACASTS

Laravel大型项目系列教程(五)之文章和标签管理相关推荐

  1. Laravel大型项目系列教程(二)之用户管理

    Laravel大型项目系列教程(二) 一.前言 本节教程将大概实现用户的注册.修改个人信息.管理用户功能 二.Let's go 1.创建用户注册视图 <span style="font ...

  2. Laravel大型项目系列教程(三)之发表文章

    Laravel大型项目系列教程(三)之发表文章 一.前言 上一节教程中完成了用户管理,这节教程将大概完成发表Markdown格式文章并展示的功能. 二.Let's go 1.数据库迁移 文章模块中我们 ...

  3. Laravel大型项目系列教程(一)

    Laravel大型项目系列教程(一) 一.课程概述 1.课程介绍 本教程将使用Laravel完成一个多用户的博客系统,大概会包含如下内容: 路由管理. 用户管理,如用户注册.修改信息.锁定用户等. 文 ...

  4. laravel大型项目系列教程(四)之显示文章列表和用户修改文章

    小编心语:不知不觉已经第四部分了,非常感谢很多人给小编提的意见,改了很多bug,希望以后能继续帮小编找找茬~小编也不希望误导大家~这一节,主要讲的是如何显示文章列表和让用户修改文章,小编预告一下(一共 ...

  5. Laravel大型项目系列教程(七)之7 扩展包和Artisan开发

    本节教程将讲解扩展包开发和Artisan扩展开发,并浏览不同分辨率下的自适应效果.本节结束后整个教程就结束了,文章最后有完整版程序代码的下载. 1.扩展包开发 在前面开发中,我们经常要用到通知,如修改 ...

  6. laravel大型项目系列教程(六)之优化、单元测试以及部署

    本节教程将讲解错误处理.配置文件的使用.单元测试以及部署到Apache服务器. 1.错误处理 如果用户访问的URL不存在或者服务器存在错误时,我们不希望返货一个错误的页面,而想返回一个友好提示的页面, ...

  7. Linux求平方脚本,Linux Shell脚本系列教程(五):数学运算

    这篇文章主要介绍了Linux Shell脚本系列教程(五):数学运算,本文讲解了使用let.(())和[]进行算术运算.使用expr进行算术运算.使用bc进行算术运算三种方法,需要的朋友可以参考下 在 ...

  8. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...

  9. SpringCloud系列教程(五)之SpringCloud Gateway 网关聚合开发文档 swagger knife4j 和登录权限统一验证【Hoxton版】

    阅读提醒: 本文面向的是有一定springboot基础者 本次教程使用的Spring Cloud Hoxton RELEASE版本 由于knife4j比swagger更加友好,所以本文集成knife4 ...

最新文章

  1. 装python对电脑有什么影响-你知道:重装系统对电脑有什么影响吗?会损坏电脑吗?...
  2. TensorFlow 资源汇集
  3. 【机器学习算法专题(蓄力计划)】八、机器学习中数据的方差分析
  4. Spring框架—体系结构
  5. Effective Java之请不要在新代码中使用原生态类型(二十三)
  6. 一个能够编写、运行SQL查询并可视化结果的Web应用:SqlPad
  7. java实验_Java实验报告(实验一)
  8. 信息学奥赛C++语言:上课的人数
  9. golang中的http server和http client
  10. 链表的基本应用二及总结
  11. node之http模块总结
  12. vue隐藏和显示元素
  13. 如何从Mac OS X连接 ×××
  14. 踏雪寻梅 —— 日志打印
  15. GitHub出现大量重复代码:JavaScript最严重
  16. zabbix所有键值
  17. 数字信号处理原理及实现一书的思维导图
  18. KODI(原XBMC)二次开发完全解析(一)
  19. FeedSky更新出现很大延时
  20. vue 项目中 npm run dev 运行98% after emitting CopyPlugin 卡死

热门文章

  1. js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用)...
  2. 学习Java 采取令牌的方式避免重复提交
  3. ecshop商城禁止修改管理员邮箱
  4. 64win7+64Oracle+32plsql
  5. flash 编程技巧应用 原创
  6. mysql四:数据操作
  7. 类库 通用变量 is和as 委托
  8. virt-v2v 使用指南
  9. 在WPF程序中使用多线程技术
  10. 剑指OFFER之字符串的排列(九度OJ1369)