建立新聞¶
現在,你已經知道如何使用 CodeIgniter 從資料庫中讀取資料,但尚未將任何資訊寫入到資料庫中。在本條目,你將擴充之前創建的新聞控制器與模型以完成此功能。
開啟 CSRF 過濾器¶
在建立一個表單前,讓我們先打開 CSRF 保護。
打開 app/Config/Filters.php 檔案,並更新 $methods
屬性成下面這個樣子
public $methods = [
'post' => ['csrf'],
];
它將會對所有 POST 請求啟用 CSRF 過濾器,你可以在 安全性程式庫 中閱讀更多有關 CSRF 保護的資訊。
創建表單¶
你需要製作出一個表單,藉由表單的輸入才能將資料存入資料庫。這代表你需要製作一個包含兩個欄位的表單,一個欄位用於標題、一個欄位用於文章內容。你將從模型中的標題派生出這個 slug 。請在 app/Views/news/create.php 新建一個包含下列程式碼的視圖。
<h2><?= esc($title) ?></h2>
<?= service('validation')->listErrors() ?>
<form action="/news/create" method="post">
<?= csrf_field() ?>
<label for="title">Title</label>
<input type="input" name="title" /><br />
<label for="body">Text</label>
<textarea name="body" cols="45" rows="4"></textarea><br />
<input type="submit" name="submit" value="Create news item" />
</form>
你可能會覺得 service('validation')->listErrors()
這個函數看起來很陌生。它能用於表單驗證相關的錯誤報告。而 csrf_field()
函數創建了一個帶有 CSRF 權杖的隱藏輸入框,有助於你預防一些常見的攻擊。
回到你的 News
控制器。你將在這裡執行:檢查表單是否已經提交、提交的資料是否通過驗證,這兩項操作。我們使用 表單驗證 程式庫進行驗證。
public function create()
{
$model = model(NewsModel::class);
if ($this->request->getMethod() === 'post' && $this->validate([
'title' => 'required|min_length[3]|max_length[255]',
'body' => 'required',
])) {
$model->save([
'title' => $this->request->getPost('title'),
'slug' => url_title($this->request->getPost('title'), '-', true),
'body' => $this->request->getPost('body'),
]);
echo view('news/success');
} else {
echo view('templates/header', ['title' => 'Create a news item']);
echo view('news/create');
echo view('templates/footer');
}
}
上面的程式碼增加了很多功能。首先,我們載入了 NewsModel 。之後,我們檢查了 POST 請求是否已被處理,接著使用控制器提供的輔助函數來驗證使用者傳入的資料。在這種情況下,POST 資料,以及標題和文字欄位是必須的。
如上所述, CodeIgniter 具有強大的驗證程式庫,你可以在 這裡 閱讀更多關於這個程式庫的資訊。
繼續往下看,你可以看到一個條件式,檢查表單驗證是否成功運行。如果沒有成功,則顯示表單;如果表單提交後,也通過了所有的規則,就會呼叫模型,把新聞的資料傳遞到模型中。這裡你會看到一個新的函數 url_title()
(由 URL 輔助函數 提供),它將你傳遞給它的字串使用破折號替代所有的空格,你便可以獲得一個漂亮的 slug ,這非常適合用於創建 URL 。
在這之後,就會載入一個視圖來顯示成功訊息,新建一個 app/Views/news/success.php 檔案並且寫入一些成功訊息。
你可簡單地這麼寫:
News item created successfully.
更新模型¶
完成了上述工作,剩下的就是將模型給設定好,讓資料可以被正確保存。 save()
方法將根據主鍵來判斷是否需要插入訊息,若是這一筆資料已存在便會執行更新。在本例中,我們並沒有傳遞 id 給它,所以它將會插入一筆新的紀錄在 news 表。
但是,在預設的情形向,模型中的插入與更新方法並不會保存任何資料,因為它不知道那些欄位是可以被安全地更新。我們可以編輯模型,在 $allowedFields
屬性中宣告可更新地欄位列表。
<?php
namespace App\Models;
use CodeIgniter\Model;
class NewsModel extends Model
{
protected $table = 'news';
protected $allowedFields = ['title', 'slug', 'body'];
}
這個新的屬性現在包含了允許被更新的欄位,注意到我們省略了 id
嗎?這是因為你幾乎不需要這樣做,它在資料庫中是一個自動遞增的欄位。這有助於防止 Mass assignment vulnerability 漏洞的發生。如果你的模型正在處理你的時間戳,那麼你也應該將那些時間戳排除在外。
路由¶
在你開始在你的 CodeIgniter 應用程式中添加新聞之前,你必須到 app/Config/Routes.php 這個設定檔添加額外的規則,這將可以確保 CodeIgniter 將 create
視為一個可執行的方法,而不是新聞的 slug 。你可以在 這裡 閱讀更多有關路由的知識。
$routes->match(['get', 'post'], 'news/create', 'News::create');
$routes->get('news/(:segment)', 'News::view/$1');
$routes->get('news', 'News::index');
$routes->get('(:any)', 'Pages::view/$1');
現在將瀏覽器指向你的 CodeIgniter 開發環境,並前往 /news/create
這個URL添加一些新聞,就可以查看你所添加的不同頁面了!
恭喜你¶
你剛剛完成了你第一個 CodeIgniter4 應用程式!
下圖顯示的是專案的 app 資料夾,你所創建的所有文件顯示成綠色字體。兩個你所修改的設定檔案( Config/Routes.php
& Config/Filters.php
)並沒有改變顏色。