はしがき
前のセクションでは、記事とタグの間の多対多の関係をコードに実装しました。このセクションでは、前のセクションの続きとして、UI でタグ選択を実装する方法を見てみましょう。
手順
開発環境: Windows 7
Laravel バージョン: 5+
IDE: Phpstorm
前回のレッスンでは、記事のタグを例として、記事とタグを使用しました多対多の例を使用して説明し、記事とタグのバインドを実装します。このレッスンでは、ページ上、つまり UI 上でタグを選択する方法を見ていきます。
セレクトコントロールとは何ですか?私は知らない?分からない場合は、以下の効果を見てください。
form.blade.php を開き、publiced_at の下に form タグを追加します。
{!! Form::label('tags','Tags:') !!}{!! Form::select('tags',['default'],null,['class'=>'form-control']) !!}
実際、これらは多かれ少なかれサブセットでした。各パラメータを詳しく調べる必要はありません。という意味で。このクラスはブートストラップによって定義された型です。次に、サーバーを開いて、localhost:8888/articles/create にアクセスします。ご覧のとおり、[公開] の下に追加のタグと選択可能なコントロールがあります。
それは選択であるため、複数のオプションが必要です。私たちにとって、それは複数のタグです。コードを変更してキーワードを追加します:
{!! Form::label('tags','Tags:') !!}{!! Form::select('tags',['default'],null,['class'=>'form-control','multiple']) !!}
現在は変更が加えられていますが、タグは静的でハードコーディングされています。最初の $tagList か $tags (以下、まとめて $tags) を身につけられたらいいですね。
この $tags を取得したいので、この $tags が作成されたページにいつ渡されたかを想像してください。つまり、localhost:8888/articles/create にアクセスすると、$tag も一緒に持ち込むことになります。このようにして、$tag をこの Form に渡すことができますよね。
その方法は以下をご覧ください。
ArticlesController.php を開いて、create() メソッドを見つけます。localhost:8888/articles/create にアクセスする方法は次のとおりです。
次のコードを create() メソッドに追加します:
public function create(){ $tags=\App\Tag::lists('name'); return view('articles.create',compact('tags'));}
はい、その文を通じてタグの名前を取得します。ただし、タグ リストには前のセクションで作成したタグが 1 つだけあり、効果を確認するにはさらにいくつかのタグを作成する必要があります。
Tag.php を開き、次の配列を Tag クラスに追加します:
protected $fillable = [ 'name'];
MassAssignmentException を防ぐために $fillable 配列に名前を追加します。 次に、いじくり回しモードに切り替えます: php 職人いじり:
>>> \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", ],}
はあ、AppTag::lists(‘name’); を通じてタグ名のリストを確認できます。現在、list は添え字を通じて値を取得します。例: $tags[2] で取得される値は「coding」です。タグ名からタグを取得したい場合はどうすればよいでしょうか?例: $tags[‘coding’] で取得される値は「coding」です。続きを読む:
すごい
悪くない、変えましょう。 ArticlesController.php を開き、create() メソッドを次のように変更します:
>>> \App\Tag::lists('name','name');=> Illuminate\Support\Collection {#664 all: [ "personal" => "personal", "work" => "work", "coding" => "coding", "life" => "life", ],}
Done。効果を見てみましょう。 localhost:8888/articles/create にアクセスします。悪くありません。Shift キーを使用して複数選択できます。
選択後、記事を作成したい場合、タグの数はどのように確認できますか?
ArticlesController.php を開いて、store() メソッドを見つけます。このメソッドは記事を保存するために使用されます。見つけたら、メソッドに文を追加します:
public function create(){ $tags=\App\Tag::lists('name','name'); return view('articles.create',compact('tags'));}
文を追加 dd() シフトですべてのタグを選択し、記事の作成を送信すると、タグの値が 1 つしかないことがわかります。良い? 4つ選ばなかったっけ? form.blade.php に戻り、問題を解決するためにここを変更します。
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]);}
タグを tags[] に変更した後、渡すのは最初の値ではなく配列です。
それでは、ArticlesControllerphp の store() メソッドに戻り、dd をコメントアウトします。現在の状況では、選択したタグをすべて取得しました。次のステップは、これらのタグを記事にバインドすることです。このアクションは、前のセクションのバインド アクションに似ています。
しかし、前のセクションで記事をタグにバインドしたとき、タグの名前の代わりにタグの ID を使用しました。では、そもそもなぜ名前を取得したのでしょうか (結果として...)、ID を直接取得すれば終わりではないでしょうか?はい。
ArticlesController.php で create() メソッドを見つけて、次のように変更します:
{!! Form::select('tags[]',$tags,null,['class'=>'form-control','multiple']) !!}
それだけです。試さないでください。実際に機能します。
store() メソッドに戻り、次のコードを記述して記事をタグ ID でバインドします:
public function create(){ $tags=\App\Tag::lists('name','id'); return view('articles.create',compact('tags'));}
最初の文では記事フォームの値を取得し、2 番目の文では記事フォームのタグを取得します。フォーム ID の場合、最も重要なのは 3 番目の文で、タグの 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 下面再创建一个标签:
<h5>Tags:</h5><ul> @foreach ($article->tagsas $tag) <li> {{ $tag->name }} </li> @endforeach</ul>
刷新页面看一下效果吧,有点丑,别嫌丑啊,献丑下节不教你怎么点击了。
继续,有的文章有标签,有的文章无标签,那就做一个逻辑判断吧:
@unless ($article->tags->isEmpty()) <h5>Tags:</h5> <ul> @foreach ($article->tagsas $tag) <li> {{ $tag->name }} </li> @endforeach </ul>@endunless
打开 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]);}
好了,试着整个流程跑一遍,其实看似顺利,还是有瑕疵的。这个瑕疵留给你,或者下节课解决。