Laravel 學習筆記 — 專案練習 Part 5 — 文章編輯功能
此篇主要是了解如何編輯文章,基本上就是將該篇文章抓出來,並且將驗證過後的資料,透過 update() 的方法把它寫進資料庫
目前可以簡單的新增文章,也能顯示文章的列表,因此接下來要建立文章編輯的功能
我們在"分享"的後面,加上"編輯"的 <a> 後
執行 php artisan serve 查看 localhost:8000,會發現出現以下錯誤,錯誤提示說明需要某些參數
因此我們可以透過 php artisan route:list | grep articles (查詢跟 articles 相關的 route,才不會查出一大堆 **注意,如果此處出現 stdout is not a tty ,可在指令欄先輸入:bash;此處使用 git bash 可以,使用 phpstorm 的 terminal 不行)
articles/{article}/edit,要使用 edit,需要給予 {article} 一個參數,讓
我們回到 resources\views\articles\index.blade.php 加上 {article} 這個參數
我們在原本 route(‘articles.edit') 後面加上 ,['article'] => $article->id 來告訴 route:list 查到 articles/{article}/edit 中的 {article} 這個參數是 $article->id
刷新網頁後,看一下是否能帶入參數了
可以看到,滑鼠移到第二篇文章的"編輯"時(檢視原始碼也可以看到),網址 localhost:8000/articles/2/edit,有顯示出參數:2,即 route 知道接下來要針對 id 為2的文章進行編輯
而其實,此處也能簡單寫成 route('articles.edit' , $article) 直接將 $article 物件給系統,不用指定 id,一樣會自動抓到 id
繼續往下做,點下"編輯"的 <a> 時,可以預想會發生錯誤,因為我們 App\Http\Controllers\ArticlesController.php 尚未編寫 function edit()
至 App\Http\Controllers\ArticlesController.php 編寫 function edit(),並且也要製作 view 要呈現的 edit.blade.php 頁面
簡單做一下"編輯文章"的頁面;我們可以發現,我們現在需要將該篇的相關資料抓出來,因此需要回到 ArticlesController.php 編寫抓取資料的內容
我們很直覺的會認為,要針對該篇文章抓資料,可以使用 $article = Article::find($id) 來撈資料,但是其實這樣會產生一個問題,這樣的寫法是:點下該篇文章,進去進行編輯
問題是,可以編輯文章的,應該只有該文章的作者,而不是每個人都可以編輯任意一篇文章,因此不能透過 $article = Article::find($id) 來撈資料(需要避免網頁URL被改參數就能修改任意文章)
因此,應該要先把目前的使用者抓出來 auth()->user(),透過每個使用者會有很多文章 ->articles() ,請該使用者來找文章 ->find($id),並且放到變數中 $article ,也就是 $article = auth()->user()->articles()->find($id)
簡而言之,如果資料庫編號為第1號的使用者,要查找他自己在資料庫中,articles.id 是 1 號的文章,就是透過目前使用者登入的 user.id,去翻文章裡該文章 articles.id =1 且 articles.user_id =1,確保不會撈錯資料
修改後如下,撈取該使用者自己所屬的文章後,存放至變數,並將該變數傳到 view ,供前端使用
我們可以稍微看一下,傳到 view 的資料,如果沒有指定資料欄位,是一大串很像 json 格式的資料
想快速建立 edit.blade.php 的內容,其實可以複製 create.blade.php 中,包含錯誤訊息 $errors 跟整個 <form> ,再進行一些調整;需要調整的地方大致是:route('articles.update')、標題改成 {{ $article->title }},內文改成 {{ $article->content }}、"新增文章"字樣改成"更新文章"
截至目前,看來沒什麼問題,實際刷新網頁後,會發現有錯誤訊息
此處一樣要讓 <form> 知道,我們是要更新哪一篇文章,因此在 route('articles.update') 後面要加上 ,$article 參數,即 route('articles.update', $article)
改完再刷新頁面,並且檢視原始碼,看是否有將該文章的 id 帶入
確認 id 有帶入後,我們試著修改該篇文章的訊息(此處我們增加了"測試修改"的字樣),並且按下按鈕,更新這篇文章,查看發生什麼事情
結果跳出一個超乎預期的錯誤訊息!為什麼會這樣呢?我們再看一次 route:list 寫了什麼
我們發現,article.edit 是使用 GET ,而 article.update 是使用 PUT|PATCH
但是我們複製自 create.blade.php 中的 <form method="post"> 是使用 post
既然這樣的話,我們在 edit.blade.php 將 <form method="patch"> 就能用了嗎?不!你會發現,還是不能用
雖然 RESTFUL 有各式各樣的動詞:GET/HEAD/PUT/PATCH/DELETE,但在表單並不是全部都能用
因此我們需要用特定的方法,來假裝支援,我們加上 @method('patch'),並且檢視原始碼,看看發生了什麼事情
檢視原始碼,發現多了 <input type="hidden" name="_method" value="patch">,告訴表單,雖然方法是用 post ,但是在幫我處理的時候,請用 patch 來看待
目前我們再重新做一次更新文章,應該就會出現我們原本預期會出現的錯誤(提示我們 App\Http\Controllers\ArticlesController::update 不存在的訊息,因為我們還沒寫)
我們編寫 App\Http\Controllers\ArticlesController 內的 function update()
重新測試"更新文章",看起來似乎更新成功了
此篇的最後,稍微來做點簡單的排序,讓最後新增的文章可以方在最上面
因此我們來 App\Http\Controllers\ArticlesController.php 的 index() 將 $articles = Article::all();更改成 $articles = Article::orderBy('id','desc')->get();
$articles 就會是個一群 collection ,而且這群資料會根據 id 做反向的排序
重新"新增文章"做測試,發現最新的文章已經跑到最上面了
隨著文章越來越長,造成瀏覽上的困難,此時我們會想到進行分頁,而 Laravel 其實已經做好分頁功能了
在 index() 撈資料改成 $articles = Article::paginate(3); 再查看文章列表就會發現只剩3筆,paginate(3) 並不是撈出全部資料後去擷取3筆資料,而是使用 limit() 來撈資料
那你一定會想說,撈出3筆後,那其他資料呢?此時我們就要到 index.blade.php 加上點選分頁的語法 {{ $articles->links() }} ,系統就會自動幫我們做好了
系統就會自動幫我們做好了;如果想要客製化分頁功能,可以翻閱官網的文件
最後,紀錄一下 git 畫面