原文來自https://laravist.com/article/20
Laravist是我剛剛上線的Laravel社區,有任何與Laravel相關的問題可以到這裡來問我,我會儘力去幫大家解決問題,後期會嘗試錄製一些視頻教程,形式大概是這樣的
https://laravist.com/lesson/2
我們之前的一系列文章綜合起來就實現了一個發布文章的整個流程,但是萬一我們需要修改某篇文章的內容呢?我們該如何去實現呢?其實,有了怎麼建立一篇文章之後,我們實現編輯(更新)文章的思路很類似。這裡可以值得注意的知識點就是Form::model和getAttribute了。來看看具體的步驟:
註冊路由
在routes.php中,註冊我們的編輯頁面的路由:
Route::get('article/edit/{id}','ArticleController@edit');
這個路由接受一個參數:id,意為文章的id,我們會需要根據這個id來查詢我們要修改的文章。
編寫edit方法
根據路由,我們在ArticleController添加edit()方法:
public function edit($id) { $article = Article::findOrFail($id); $tags = Tag::lists('name', 'id'); return view('articles.edit',compact('article','tags')); }
很熟悉地,我們首先根據id來查詢到我們需要編輯的文章,對於$tags,我們採取跟create()方法一樣的方法,得到我們的$tags列表。然後渲染視圖,並將查詢到的$article和$tags傳給視圖。
建立視圖
上面的edit()方法指定了渲染articles.edit(resources/views/articles/edit.blade.php)這個視圖,我們來建立之,這裡為了便利,我們可以直接將create.blade.php這個視圖檔案拷貝過來:
@extends('app')@section('content') 修改文章:{{ $article->title }}
{!! Form::model($article,['url'=>'article/update']) !!} {!! Form::hidden('id',$article->id) !!} {!! Form::label('title','標題:') !!} {!! Form::text('title',$article->title,['class'=>'form-control']) !!} {!! Form::label('content','本文:') !!} {!! Form::textarea('content',$article->content,['class'=>'form-control']) !!} {!! Form::label('published_at','發布日期') !!} {!! Form::input('date','published_at',$article->published_at->format('Y-m-d'),['class'=>'form-control']) !!} {!! Form::label('tag_list','選擇標籤') !!} {!! Form::select('tag_list[]',$tags,null,['class'=>'form-control js-example-basic-multiple','multiple'=>'multiple']) !!} {!! Form::submit('修改文章',['class'=>'btn btn-success form-control']) !!} {!! Form::close() !!} @if($errors->any())
@foreach($errors->all() as $error)
- {{ $error }}
@endforeach
@endif @endsection
這裡我們注意下面這幾點:
我們使用了Form::hidden()
這裡我們使用這個目的(因為hidden表單並不會展示給使用者看)就是為了後面在更新的時候更加便捷和暴力,因為有了id,我們一切的事情都很好辦。
我們給Form input表單設定了初始值
通過類似{!! Form::text('title',$article->title,['class'=>'form-control']) !!}中的$article->title的形式,我們給表單賦予了初始值。
我們使用了Form::model()
在聲明Form的時候,我們並不是簡單的使用Form::open(),Form::model()首先需要將你要綁定的model傳進來,這裡我們用的是$article,也就是我們在edit()方法尋找到的$article,這個有什麼好處呢?
一旦綁定Form::model(),在後面的input表單中即使你沒有設定初始值,laravel也會自動為你匹配,然後
為你賦予初始值,這也是使用Form的好處之一,就比如上面的{!! Form::text('title',$article->title,['class'=>'form-control']) !!},在Form::model()下,你完全可以像之前那樣寫:
{!! Form::text('title',null,['class'=>'form-control']) !!}
你依然會得到相同的效果,但是這裡為了更清晰,我直接賦了$article->title初始值。
我們又使用Carbon
在文章的published_at這個欄位,我們借$article->published_at->format('Y-m-d')又一次感受到了Carbon的便利。
最後來看看我們的編輯頁面有沒有好:
仔細看其實就會發現,這樣還沒有完全實現編輯,因為我們的標籤還沒有同步過來,我們看到的標籤select都是空的,但是原來的文章是有標籤的啊,這個怎麼辦呢?
getAttribute
getAttribute就可以登場了,藉助tag_list[]這個便利特性,我們可以在Article.php中為其設定一個getAttribute方法:
public function getTagListAttribute() { // laravel 5.1 needs all() return $this->tags->lists('id')->all(); // tags means tags() many-to-many relationship with tag }
這裡需要說明一下,類似getAttribute都統一使用駝峰法。然後取值的時候就統一使用底線的方法,比如這裡的tag_list就是對應TagList,如果你寫成tag_involved,方法就是getTagInvolvedAttribute()。這樣寫laravel會自動擷取這個值。
注意,laravel 5.0版本,寫成這樣return $this->tags->lists('id');
我們來看看效果:
OK,這裡我們實現完編輯頁面之後,我們根據Form::model()的url來註冊一個post路由
註冊post路由
來到routes.php中,為update方法增加post路由:
Route::post('article/update','ArticleController@update');
修改文章的表單會提交到article/update,然後觸發ArticleController的update()方法。
編寫update()
在ArticleController中增加update()方法:
public function update(Requests\StoreArticleRequest $request) { //這裡使用同樣地驗證規則 dd($request->all()); }
我們來看看有沒有拿到提交過來的資料:
OK,我們爭取拿到資料了,接下來就是實現更新了。修改我們的update()方法:
public function update(Requests\StoreArticleRequest $request) { //根據id查詢到需要更新的article $article = Article::find($request->get('id')); //使用Eloquent的update()方法來更新, //request的except()是排除某個提交過來的資料,我們這裡排除id $article->update($request->except('id')); // 跟attach()類似,我們這裡使用sync()來同步我們的標籤 $article->tags()->sync($request->get('tag_list')); return redirect('/'); }
OK,代碼邏輯實現完了之後,我們來看看是否能更新成功:
Bang,大工告成!!
總結
如果你一直都跟著教程來,這個修改文章的過程應該思路很清晰。我們在這裡再一次感受到:
註冊路由--->控制器寫方法--->載入視圖
這一個神奇的輪迴。這裡還是需要強調的是Form::model()和getAttribute這兩個知識點。
最後,到這裡,貌似我們的整個教程就可以結束了。下面我打算再開一個系列說說laravel 5.1的新特性.
Happy Hacking