欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

[Laravel 5 Fundamentals] 22 – Selecting Tags From the UI

程序员文章站 2024-01-01 09:47:34
...

标签选择

前言

上一节,我们对 article 和 tag 的多对多关系进行了代码上的实现。本节,继续上节,让我们如何在 UI 上实现对 tag 的选择。

说明

开发环境:Windows 7

Laravel 版本: 5+

IDE: Phpstorm

上节课,我们以文章的 tag 为例子,将 article 和 tag 作为多对多的事例进行讲解,并且实现了文章和标签的绑定。这节课,我们看看在页面上,也就是 UI 上怎么实现对 tag 的选取。

select 控件

什么是 select 控件?不知道啊?不知道的话看一下下面的效果就知道了。

打开 form.blade.php ,在 published_at 下面添加一个 form 标签:

{!! Form::label('tags','Tags:') !!}{!! Form::select('tags',['default'],null,['class'=>'form-control']) !!} 

其实这些东西,以前都多少有些子集,具体不需要怎么多讲,你可以看看效果就明白每个参数的意义。这个 class 是 bootstrap 定义的类型。然后打开服务器,访问一下 localhost:8888/articles/create ,看到了嘛,在 publish on 下面多了一个 tags 和一个可以选择的控件。

既然是选择,那就需要多个选项。对于我们来说,就是多个 tag 。改一下代码,添加一个关键字:

{!! Form::label('tags','Tags:') !!}{!! Form::select('tags',['default'],null,['class'=>'form-control','multiple']) !!} 

现在虽然有了变化,但是我们的 tag 是静态的,写死的。要是能穿第一个 $tagList 或者 $tags(下面统称为 $tags) 就好了。

那既然想获取这个 $tags ,想象这个逻辑,这个 $tags 是什么时候被传递到这个创建的页面的?那也就是当我们访问 localhost:8888/articles/create 的时候,会把 $tags 一同携带过来,如此,我们才能把 $tags 传递到这个 Form 中,对吧?

下面看怎么搞。

打开 ArticlesController.php ,找到 create() 方法,这里就是我们如何访问 localhost:8888/articles/create 的。

在 create() 方法里加入如下代码:

public function create(){    $tags=\App\Tag::lists('name');    return view('articles.create',compact('tags'));} 

是的,我们就是通过那一句来获取 tag 的 name (名称)的。不过现在,我们的 tag 列表里只有一个 tag ,就是上节创建的,我们需要再创建几个 tag 才能看出效果。

打开 Tag.php,在 Tag 类中添加如下数组:

protected $fillable = [    'name']; 

把 name 添加到 $fillable 数组中,防止 MassAssignmentException 。 接下来切换到 tinker 模式: php artisan tinker :

>>> \App\Tag::create(['name'=>'work']);=> App\Tag {#656    name: "work",    updated_at: "2016-05-01 14:02:13",    created_at: "2016-05-01 14:02:13",    id: 2,}>>> \App\Tag::create(['name'=>'coding']);=> App\Tag {#655    name: "coding",    updated_at: "2016-05-01 14:03:50",    created_at: "2016-05-01 14:03:50",    id: 3,}>>> \App\Tag::create(['name'=>'life']);  => App\Tag {#645    name: "life",    updated_at: "2016-05-01 14:04:29",    created_at: "2016-05-01 14:04:29",    id: 4,}>>> \App\Tag::lists('name');=> Illuminate\Support\Collection {#653    all: [      "personal",      "work",      "coding",      "life",    ],} 

哈,通过 \App\Tag::lists(‘name’); 可以看到我们的 tag name list 。目前 list 是通过下标的方式来获取值的,比如: $tags[2] 取到的值就是 ‘coding’;如果我想通过 tag 名称来获取 tag 呢?比如: $tags[‘coding’] 取到的值就是 ‘coding’。接着看:

>>>  \App\Tag::lists('name','name');=> Illuminate\Support\Collection {#664    all: [      "personal" => "personal",      "work" => "work",      "coding" => "coding",      "life" => "life",    ],} 

不错,改一下吧。打开 ArticlesController.php 把 create() 方法改成如下:

public function create(){    $tags=\App\Tag::lists('name','name');    return view('articles.create',compact('tags'));} 

完工。看下效果吧。访问 localhost:8888/articles/create 。不错~有效果,可以选择了,可以通过 shift 键进行多选哦。

选择之后,我们要创建文章的时候,我们所提交的 tag 到底有多少,怎么查看一下?

打开 ArticlesController.php ,找到 store() 方法,因为这个方法是用来存储文章的。找到之后,我们在该方法中加入一句:

public function store(ArticleRequest $request){    dd($request->input('tags'));    $article = new Article($request->all());    Auth::user()->articles()->create($article);    return redirect('articles')->with([            'flash_message'=>'Your article has been created!',            'flash_message_important'=>true]);} 

加一句 dd(),当你通过 shift 把标签全都选中的时候,提交创建文章后,会发现只有一个 tag 值。呃?不是选了四个么。回到 form.blade.php ,修改一下这里就可以解决:

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

把 tags 改成 tags[] 后,我们传递的便是数组,而不是首位值。

好了,回到 ArticlesControllerphp 的 store() 方法中,把 dd 注释掉。目前的情况是,我们获取到了所有选中的 tags ,下一步,就该将这些 tags 与 文章进行绑定了。这一动作和上一节的绑定动作类似。

但是上一节我们将 article 与 tag 进行绑定的时候,用到的是 tag 的 id ,而不是 tag 的 name。那当初我们为什么要获取 name (为了效果。。。),直接获取 id 不就完了?是的。

在 ArticlesController.php 中找到 create() 方法,修改如下:

public function create(){    $tags=\App\Tag::lists('name','id');    return view('articles.create',compact('tags'));} 

这样就可以了,不用试了,真的可以了。

回到 store() 方法中,写下如下代码进行 article 与 tag id们进行绑定:

public function store(ArticleRequest $request){    $article = Auth::user()->articles()->create($request->all());    $article->tags()->attach($request->input('tags'));    return redirect('articles')->with([            'flash_message'=>'Your article has been created!',            'flash_message_important'=>true]);} 

第一句,获取到 article 表单中的值,第二句,获取到表单中 tags 的 id 们,重要的就是第三句,将 文章与其标签进行绑定,通过标签的 id 。

我们去试一试。文章是发表成功了,看看数据库里吧,切换到 tinker 模式:

>>> $article = App\Article::find(10);=> App\Article {#659    id: "10",    user_id: "1",    created_at: "2016-05-01 15:26:08",    updated_at: "2016-05-01 15:26:08",    title: "asd",    body: "asdasdasdasd",    published_at: "2016-05-09 00:00:00",  }>>> $article->tags->toArray();=> [    [      "id" => 2,      "name" => "work",      "created_at" => "2016-05-01 14:02:13",      "updated_at" => "2016-05-01 14:02:13",      "pivot" => [        "article_id" => "10",        "tag_id" => "2",        "created_at" => "2016-05-01 15:26:08",        "updated_at" => "2016-05-01 15:26:08",      ],    ],    [      "id" => 3,      "name" => "coding",      "created_at" => "2016-05-01 14:03:50",      "updated_at" => "2016-05-01 14:03:50",      "pivot" => [        "article_id" => "10",        "tag_id" => "3",        "created_at" => "2016-05-01 15:26:08",        "updated_at" => "2016-05-01 15:26:08",      ],    ],  ] 

嗯,还是没问题的。两个标签。

展示文章标签

文章展示的时候,一般在其下方会有文章的标签,下面我们就实现这个。打开 show.blade.php ,在 body div 下面再创建一个标签:

Tags:
    @foreach ($article->tagsas $tag)
  • {{ $tag->name }}
  • @endforeach

刷新页面看一下效果吧,有点丑,别嫌丑啊,献丑下节不教你怎么点击了。

继续,有的文章有标签,有的文章无标签,那就做一个逻辑判断吧:

@unless ($article->tags->isEmpty())    
Tags:
    @foreach ($article->tagsas $tag)
  • {{ $tag->name }}
  • @endforeach
@endunless

给编辑页面也提供 tag

打开 ArticlesController.php ,找到 edit() 方法,其实和 create() 的做法一样:

public function edit($id){    $tags=\App\Tag::lists('name','id');    $article = Article::findOrFail($id);    return view('articles.edit',compact('article','tags'));} 

访问一下 localhost:8888/articles/10/edit ,可以看到标签,但是不知道哪些已经是选过的,如何能标记一下呢?

打开 Article.php,我们新建一个方法:

public function getTagListAttribute(){        return $this->tags->lists('id')->all();} 

相应的 form.blade.php 也得修改一下:

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

细心的同学应该已经发现,为什么在 Article.php 中有一个 getTagListAttribute() 的方法,而且在 form.blade.php 中直接调用 tag_list 就能获取到被选中的 tag 的值。这是 laravel 功能,它能够通过命名方式来自动关联方法与对象。

现在访问 localhost:8888/articles/edit 你会发现可以显示之前选中的 tag 了。

最后修改 store() 方法中获取 tag 的方法:

public function store(ArticleRequest $request){    $article = Auth::user()->articles()->create($request->all());    $article->tags()->attach($request->input('tag_list'));    return redirect('articles')->with([            'flash_message'=>'Your article has been created!',            'flash_message_important'=>true]);} 

总结

好了,试着整个流程跑一遍,其实看似顺利,还是有瑕疵的。这个瑕疵留给你,或者下节课解决。

上一篇:

下一篇: