欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

[Laravel 5 教程学习笔记] 二十、从界面中选择标签 有大用

shiping1 的头像

前一节学习了多对多关系模型,已经如何在Eloquent模型中表述它,现在我们来介绍通过界面选择来完成。

 

一、显示与创建标签

首先打开 /resources/views/articles/_form.blade.php 文件,在提交按钮的前面添加下面代码:


  1. <div class="form-group">

  2. {!! Form::label('tags', 'Tags:') !!}

  3. {!! Form::select('tags', $tags, null, ['class' => 'form-control', 'multiple']) !!}

  4. </div>

然后修改 ArticlesController.php 文件中的 create() 方法:


  1. public function create(){

  2. $tags = \App\Tag::lists('name');

  3. return view('articles.create', compact('tags'));

  4. }

现在打开 http://laravel.dev/articles/create ,可以看到,多出了一个列出所有标签的多选框。

laravel-select-tags-1

由于上一节我们只添加了一个标签,所以这里只列出了一个。下面我们通过 tinker 命令行继续创建几个标签:


  1. D:\wamp\www\laravel5>php artisan tinker

  2. Psy Shell v0.4.1 (PHP 5.5.12 鈥?cli) by Justin Hileman

  3. >>> \App\Tag::create(['name' => 'Java']);

  4. Illuminate\Database\Eloquent\MassAssignmentException with message 'name'

使用上面的命令发现,添加失败了,这个其实之前就介绍过,是Laravel的一种保护机制。我们打开Tag.php 文件,添加下面的代码:


  1. protected $fillable = [

  2. 'name',

  3. ];

然后退出 tinker 并重新打开:


  1. D:\wamp\www\laravel5>php artisan tinker

  2. Psy Shell v0.4.1 (PHP 5.5.12 鈥?cli) by Justin Hileman

  3. >>> \App\Tag::create(['name' => 'Java']);

  4. => <App\Tag #000000000e99479a00000000057c0183> {

  5. name: "Java",

  6. updated_at: "2015-08-02 00:34:40",

  7. created_at: "2015-08-02 00:34:40",

  8. id: 2

  9. }

  10. >>> \App\Tag::create(['name' => 'C##']);

  11. => <App\Tag #000000000e99479000000000057c0183> {

  12. name: "C##",

  13. updated_at: "2015-08-02 00:35:44",

  14. created_at: "2015-08-02 00:35:44",

  15. id: 3

  16. }

  17. >>> \App\Tag::create(['name' => 'Python']);

  18. => <App\Tag #000000000e99478c00000000057c0183> {

  19. name: "Python",

  20. updated_at: "2015-08-02 00:35:53",

  21. created_at: "2015-08-02 00:35:53",

  22. id: 4

  23. }

  24. >>> \App\Tag::create(['name' => 'Go']);

  25. => <App\Tag #000000000e99478800000000057c0183> {

  26. name: "Go",

  27. updated_at: "2015-08-02 00:36:01",

  28. created_at: "2015-08-02 00:36:01",

  29. id: 5

  30. }

默认情况下,使用 lists('name') 所得到的 key 值是以 0 开始的,而我们需要的是 key 值就是 value 的值,所以需要按这么那种写法:


  1. >>> \App\Tag::lists('name');

  2. => [

  3. "PHP",

  4. "Java",

  5. "C##",

  6. "Python",

  7. "Go"

  8. ]

  9. >>> \App\Tag::lists('name', 'name');

  10. => [

  11. "PHP" => "PHP",

  12. "Java" => "Java",

  13. "C##" => "C##",

  14. "Python" => "Python",

  15. "Go" => "Go"

  16. ]

现在修改 ArticlesController.php 中 create() 方法:


  1. public function create(){

  2. $tags = \App\Tag::lists('name', 'name');

  3. return view('articles.create', compact('tags'));

  4. }

这时刷新页面,查看源代码,可以看到已经得到了我们想要的结果。

二、添加结果处理

修改 ArticlesController.php 中的 store() 方法,打印出选择的标签:


  1. public function store(ArticleRequest $request){

  2. dd($request->input('tags'));

  3. Auth::user()->articles()->create($request->all());

  4. flash()->overlay('文章发布成功', 'Good Job');

  5. return redirect('articles');

  6. }

然后添加博客内容,选中所有的标签并点击添加按钮,却发现只打印出了一个标签,这是因为我们需要把标签作为数组才可以。修改模版文件:


  1. <div class="form-group">

  2. {!! Form::label('tags', 'Tags:') !!}

  3. {!! Form::select('tags[]', $tags, null, ['class' => 'form-control', 'multiple']) !!}

  4. </div>

这次刷新页面,添加内容选择标签后再次提交,可以看到成功打印出了所有我们选择的标签,这正是我们需要的。

现在假设我们提交了表单,得到了标签数组,并且想把它们与这篇文章关联起来,前一节我们学习了使用 attach() 方法来实现该功能,看起来我们已经获得了所有我们需要的方法及数据,下面看看怎么做。

还有一点需要注意,我们使用 attach() 方法的时候,我们传递的参数是一个标签ID的数组,而上面我们得到的是标签名称的数组,所以还需要再次修改一下 create() 方法:


  1. public function create(){

  2. $tags = \App\Tag::lists('name', 'id');

  3. return view('articles.create', compact('tags'));

  4. }

然后刷新页面,添加内容选择标签后提交,可以看到打印出来的已经是标签对应的ID了。

接着,修改 store() 方法:


  1. public function store(ArticleRequest $request){

  2. $article = Auth::user()->articles()->create($request->all());

  3. $article->tags()->attach($request->input('tags'));

  4. flash()->overlay('文章发布成功', 'Good Job');

  5. return redirect('articles');

  6. }

这时,再次刷新页面,添加内容选择标签后发布,可以看到发布成功了,那么我们的标签是否添加成功了呢?可以使用数据库管理工具或者命令行工具 tinker 命令查看:


  1. //下面的 2 为刚刚发布的博客的ID

  2. >>> $article = \App\Article::find(2);

  3. => <App\Article #000000002ae45438000000003dea11ab> {

  4. id: 2,

  5. user_id: 1,

  6. title: "标题",

  7. body: "内容",

  8. created_at: "2015-08-02 01:02:03",

  9. updated_at: "2015-08-02 01:02:03",

  10. published_at: "2015-08-02 00:00:00",

  11. excerpt: null

  12. }

  13. >>> $article->tags->toArray();

  14. => [

  15. [

  16. "id" => 1,

  17. "name" => "PHP",

  18. "created_at" => "2015-07-25 21:29:45",

  19. "updated_at" => "2015-07-25 21:29:45",

  20. "pivot" => [

  21. "article_id" => 2,

  22. "tag_id" => 1,

  23. "created_at" => "2015-08-02 01:02:03",

  24. "updated_at" => "2015-08-02 01:02:03"

  25. ]

  26. ],

  27. [

  28. "id" => 4,

  29. "name" => "Python",

  30. "created_at" => "2015-08-02 00:35:53",

  31. "updated_at" => "2015-08-02 00:35:53",

  32. "pivot" => [

  33. "article_id" => 2,

  34. "tag_id" => 4,

  35. "created_at" => "2015-08-02 01:02:03",

  36. "updated_at" => "2015-08-02 01:02:03"

  37. ]

  38. ],

  39. [

  40. "id" => 5,

  41. "name" => "Go",

  42. "created_at" => "2015-08-02 00:36:01",

  43. "updated_at" => "2015-08-02 00:36:01",

  44. "pivot" => [

  45. "article_id" => 2,

  46. "tag_id" => 5,

  47. "created_at" => "2015-08-02 01:02:03",

  48. "updated_at" => "2015-08-02 01:02:03"

  49. ]

  50. ]

  51. ]

可以看到标签已经添加成功了。

三、在页面显示标签

修改 /resources/views/articles/show.blade.php 文件:


  1. @extends('main')

  2.  

  3. @section('content')

  4. <h1>{{ $article->title }}</h1>

  5. <article>{{ $article->body }}</article>

  6.  

  7. <h5>Tags:</h5>

  8. <ul>

  9. @foreach($article->tags as $tag)

  10. <li>{{ $tag->name }}</li>

  11. @endforeach

  12. </ul>

  13. @stop

现在到刚发布的文章的详情页,可以看到列出了所有添加的标签。但是如果打开一篇前面没有添加标签的博客详细页,可以看到下面多出了 “Tags:”,却没有标签,这不是我们想要的。我们需要当没有标签的时候,也不显示“Tags:”。

所以,接着修改刚才的 show.blade.php 文件:


  1. @extends('main')

  2.  

  3. @section('content')

  4. <h1>{{ $article->title }}</h1>

  5. <article>{{ $article->body }}</article>

  6.  

  7. @unless($article->tags->isEmpty())

  8. <h5>Tags:</h5>

  9. <ul>

  10. @foreach($article->tags as $tag)

  11. <li>{{ $tag->name }}</li>

  12. @endforeach

  13. </ul>

  14. @endunless

  15. @stop

这时打开没有标签的博客时,就不会显示出下面的“Tags:”了。

但是现在还有个问题,我们已经解决了添加标签的问题,而修改的时候却还没有做处理。这时打开一个博客的修改页会发现报错了。

修改 ArticlesController.php 中的 edit() 方法:


  1. public function edit(Article $article){

  2. $tags = \App\Tag::lists('name', 'id');

  3. return view('articles.edit', compact('article', 'tags'));

  4. }

现在刷新页面,可以看到已经列出了所有的标签,但是我们添加的标签并未选中,接着修改。

在 Article.php 中添加方法(用于获取博客中所有标签的ID):


  1. public function getTagListAttribute(){

  2. return $this->tags->lists('id');

  3. }

由于前面已经讲过了,修改页面用到了表单模型绑定,所以这里要修改 _form.blade.php 视图文件中标签的那一段:


  1. <div class="form-group">

  2. {!! Form::label('tag_list', 'Tags:') !!}

  3. {!! Form::select('tag_list[]', $tags, null, ['class' => 'form-control', 'multiple']) !!}

  4. </div>

之后刷新页面,可以看到已经把我们添加的标签选中了。

Form::select() 方法的第二个参数为所有可选项,第三个参数为默认选中项,而由于Laravel的表单模型绑定,我们这里只需要把字段名字改为特定字段即可。对于表单模型绑定不记得的可以查看《 十三、子视图与表单重用

由于上面我们改变了字段的名称,所有返回控制器文件,修改 store() 方法中相应的字段。

这时重新发布,查看,编辑一篇博客试试效果吧,但是还有一点,我们编辑文章保存的时候并没有对标签做处理,留待以后做。


 
转载请注明来源:[Laravel 5 教程学习笔记] 二十、从界面中选择标签 - Specs' Blog-就爱PHP

本文共 6 个回复


    •  

      xoolee 2016/03/07 11:24

    •  

      Specs  2015/09/17 13:14

      Tingel 你看看数据库里这个那篇文章到底有没有标签

    •  

      Tingel 2015/09/16 21:37

      在Edit画面tag_list并没有数值,空.我检查过Function cteateArticle的代码 一致,并不清楚问题出在哪里.

    •  

      Tingel 2015/09/16 21:38

      打错,应该是Function getTagListAttribute()

    •  

      xoolee 2016/03/07 10:51

      在编辑模版文件中逗能打印出文章的标签(getPostTagAttribute),可是编辑页面tag并没有选中<?php echo 'post_tag='.$post->post_tag; ?><!-- post_tags Star --><div class="form-group"> {!! Form::label('post_tag', '标签') !!} {!! Form::select('post_tag[]', $post_tags, null, ['class'=>'form-control js-example-tags', 'multiple']) !!}</div>我都不知道什么原因,值为什么没有传进来

    来自 http://9iphp.com/web/laravel/laravel-5-select-tags-from-ui.html

    普通分类: