创建新闻项目
您现在知道如何使用 CodeIgniter 从数据库读取数据,但您还没有向数据库写入任何信息。在本节中,您将扩展之前创建的新闻控制器和模型以包含此功能。
启用 CSRF 过滤器
在创建表单之前,让我们启用 CSRF 保护。
打开 **app/Config/Filters.php** 文件并更新 $methods
属性,如下所示
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
class Filters extends BaseConfig
{
// ...
public $methods = [
'post' => ['csrf'],
];
// ...
}
它配置 CSRF 过滤器以对所有 **POST** 请求启用。您可以在 安全 库中阅读有关 CSRF 保护的更多信息。
警告
通常,如果您使用 $methods
过滤器,您应该 禁用自动路由(旧版),因为 自动路由(旧版) 允许任何 HTTP 方法访问控制器。使用您不期望的方法访问控制器可能会绕过过滤器。
添加路由规则
在您开始将新闻项目添加到 CodeIgniter 应用程序之前,您需要在 **app/Config/Routes.php** 文件中添加一条额外的规则。确保您的文件包含以下内容
<?php
// ...
use App\Controllers\News;
use App\Controllers\Pages;
$routes->get('news', [News::class, 'index']);
$routes->get('news/new', [News::class, 'new']); // Add this line
$routes->post('news', [News::class, 'create']); // Add this line
$routes->get('news/(:segment)', [News::class, 'show']);
$routes->get('pages', [Pages::class, 'index']);
$routes->get('(:segment)', [Pages::class, 'view']);
用于 'news/new'
的路由指令位于用于 'news/(:segment)'
的指令之前,以确保显示创建新闻项目的表单。
$routes->post()
行定义了 POST 请求的路由器。它只匹配到 URI 路径 **/news** 的 POST 请求,并映射到 News
类的 create()
方法。
您可以在 设置路由规则 中了解更多关于不同路由类型的知识。
创建表单
创建 news/create 视图文件
要将数据输入数据库,您需要创建一个表单,您可以在其中输入要存储的信息。这意味着您将需要一个包含两个字段的表单,一个用于标题,一个用于文本。您将在模型中从我们的标题中推导出 slug。
在 **app/Views/news/create.php** 中创建一个新的视图
<h2><?= esc($title) ?></h2>
<?= session()->getFlashdata('error') ?>
<?= validation_list_errors() ?>
<form action="/news" method="post">
<?= csrf_field() ?>
<label for="title">Title</label>
<input type="input" name="title" value="<?= set_value('title') ?>">
<br>
<label for="body">Text</label>
<textarea name="body" cols="45" rows="4"><?= set_value('body') ?></textarea>
<br>
<input type="submit" name="submit" value="Create news item">
</form>
这里可能只有四件事看起来不熟悉。
session()
函数用于获取 Session 对象,而 session()->getFlashdata('error')
用于向用户显示与 CSRF 保护相关的错误。但是,默认情况下,如果 CSRF 验证检查失败,将抛出异常,因此它尚不可用。有关更多信息,请参见 失败时的重定向。
由 表单助手 提供的 validation_list_errors()
函数用于报告与表单验证相关的错误。
该 csrf_field()
函数创建一个包含 CSRF 令牌的隐藏输入,有助于防止一些常见的攻击。
由 表单助手 提供的 set_value()
函数用于在发生错误时显示旧的输入数据。
新闻控制器
返回您的 News
控制器。
添加 News::new() 以显示表单
首先,创建一个方法来显示您创建的 HTML 表单。
<?php
namespace App\Controllers;
use App\Models\NewsModel;
use CodeIgniter\Exceptions\PageNotFoundException;
class News extends BaseController
{
// ...
public function new()
{
helper('form');
return view('templates/header', ['title' => 'Create a news item'])
. view('news/create')
. view('templates/footer');
}
}
我们使用 helper()
函数加载 表单助手。大多数助手函数需要在使用前加载助手。
然后它返回创建的表单视图。
添加 News::create() 以创建新闻项目
接下来,创建一个方法来从提交的数据中创建新闻项目。
您将在这里做三件事
检查提交的数据是否通过了验证规则。
将新闻项目保存到数据库。
返回成功页面。
<?php
namespace App\Controllers;
use App\Models\NewsModel;
use CodeIgniter\Exceptions\PageNotFoundException;
class News extends BaseController
{
// ...
public function create()
{
helper('form');
$data = $this->request->getPost(['title', 'body']);
// Checks whether the submitted data passed the validation rules.
if (! $this->validateData($data, [
'title' => 'required|max_length[255]|min_length[3]',
'body' => 'required|max_length[5000]|min_length[10]',
])) {
// The validation fails, so returns the form.
return $this->new();
}
// Gets the validated data.
$post = $this->validator->getValidated();
$model = model(NewsModel::class);
$model->save([
'title' => $post['title'],
'slug' => url_title($post['title'], '-', true),
'body' => $post['body'],
]);
return view('templates/header', ['title' => 'Create a news item'])
. view('news/success')
. view('templates/footer');
}
}
上面的代码添加了许多功能。
检索数据
首先,我们使用 IncomingRequest 对象 $this->request
,它由框架在控制器中设置。
我们从用户提交的 POST 数据中获取必要的项目,并将它们设置在 $data
变量中。
验证数据
接下来,您将使用控制器提供的助手函数 validateData() 来验证提交的数据。在这种情况下,标题和正文字段是必需的,并且在特定长度内。
CodeIgniter 拥有一个强大的验证库,如上所示。您可以阅读有关 验证库 的更多信息。
如果验证失败,我们将调用您刚刚创建的 new()
方法并返回 HTML 表单。
保存新闻项目
如果验证通过了所有规则,我们将通过 $this->validator->getValidated() 获取验证后的数据,并将它们设置在 $post
变量中。
加载并调用 NewsModel
。这负责将新闻项目传递到模型中。 save() 方法根据它是否找到与主键匹配的数组键,自动处理插入或更新记录。
这包含一个新函数 url_title()
。此函数由 URL 助手 提供,它会剥离您传递给它的字符串,将所有空格替换为连字符 (-
),并确保所有内容都为小写字符。这会为您提供一个不错的 slug,非常适合创建 URI。
返回成功页面
在此之后,加载视图文件并返回以显示成功消息。在 app/Views/news/success.php 中创建一个视图,并编写一条成功消息。
这可能很简单,例如
<p>News item created successfully.</p>
NewsModel 更新
唯一剩下的就是确保您的模型已设置好,以便能够正确保存数据。所使用的 save()
方法将根据主键的存在来确定是插入信息还是更新已存在的行。在本例中,没有传递 id
字段,因此它将在其表 news
中插入新行。
但是,默认情况下,模型中的插入和更新方法实际上不会保存任何数据,因为它不知道哪些字段可以安全更新。编辑 NewsModel
以在 $allowedFields
属性中提供可更新字段的列表。
<?php
namespace App\Models;
use CodeIgniter\Model;
class NewsModel extends Model
{
protected $table = 'news';
protected $allowedFields = ['title', 'slug', 'body'];
}
此新属性现在包含我们允许保存到数据库的字段。请注意,我们省略了 id
?这是因为您几乎不需要这样做,因为它是在数据库中自动递增的字段。这有助于防止大规模赋值漏洞。如果您的模型正在处理您的时间戳,您也应该将它们省略。
创建新闻项目
现在将您的浏览器指向您安装 CodeIgniter 的本地开发环境,并在 URL 中添加 ** /news/new **。添加一些新闻并查看您创建的不同页面。
恭喜
您刚刚完成了您的第一个 CodeIgniter4 应用程序!
下面的图表显示了您的项目的 **app** 文件夹,其中包含您创建或修改的所有文件。
app/
├── Config
│ ├── Filters.php (Modified)
│ └── Routes.php (Modified)
├── Controllers
│ ├── News.php
│ └── Pages.php
├── Models
│ └── NewsModel.php
└── Views
├── news
│ ├── create.php
│ ├── index.php
│ ├── success.php
│ └── view.php
├── pages
│ ├── about.php
│ └── home.php
└── templates
├── footer.php
└── header.php