新闻部分
在上一节中,我们通过编写一个引用静态页面的类,介绍了框架的一些基本概念。我们通过添加自定义路由规则清理了 URI。现在是时候引入动态内容并开始使用数据库了。
创建一个数据库来使用
CodeIgniter 安装假设您已设置了适当的数据库,如要求中所述。在本教程中,我们提供了 MySQL 数据库的 SQL 代码,并且我们还假设您拥有一个合适的客户端来发出数据库命令(mysql、MySQL Workbench 或 phpMyAdmin)。
您需要创建一个名为ci4tutorial
的数据库,该数据库可用于本教程,然后配置 CodeIgniter 以使用它。
使用您的数据库客户端,连接到您的数据库并运行以下 SQL 命令(MySQL)
CREATE TABLE news (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(128) NOT NULL,
slug VARCHAR(128) NOT NULL,
body TEXT NOT NULL,
PRIMARY KEY (id),
UNIQUE slug (slug)
);
此外,添加一些种子记录。目前,我们只向您展示创建表的 SQL 语句,但您应该知道,一旦您熟悉 CodeIgniter,就可以通过编程方式完成此操作;您可以阅读有关 迁移 和 种子 的内容,以便稍后创建更有用的数据库设置。
需要注意的是:“slug” 在网络发布的语境中,是指 URL 中用于识别和描述资源的简短文本,对用户和 SEO 友好。
种子记录可能类似于
INSERT INTO news VALUES
(1,'Elvis sighted','elvis-sighted','Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app.'),
(2,'Say it isn\'t so!','say-it-isnt-so','Scientists conclude that some programmers have a sense of humor.'),
(3,'Caffeination, Yes!','caffeination-yes','World\'s largest coffee shop open onsite nested coffee shop for staff only.');
连接到您的数据库
您在安装 CodeIgniter 时创建的本地配置文件 .env 应该将数据库属性设置取消注释并适当地设置为要使用的数据库。确保您已按照 数据库配置 中的说明正确配置了数据库。
database.default.hostname = localhost
database.default.database = ci4tutorial
database.default.username = root
database.default.password = root
database.default.DBDriver = MySQLi
设置您的模型
不要在控制器中直接编写数据库操作,而应该将查询放在模型中,以便以后可以轻松地重复使用。模型是您检索、插入和更新数据库或其他数据存储中的信息的地方。它们提供对数据的访问。您可以在 使用 CodeIgniter 的模型 中了解更多信息。
创建 NewsModel
打开 app/Models 目录并创建一个名为 NewsModel.php 的新文件,并添加以下代码。
<?php
namespace App\Models;
use CodeIgniter\Model;
class NewsModel extends Model
{
protected $table = 'news';
}
此代码与之前使用的控制器代码类似。它通过扩展 CodeIgniter\Model
并加载数据库库来创建一个新模型。这将使数据库类通过 $this->db
对象可用。
添加 NewsModel::getNews() 方法
现在数据库和模型已经设置好了,你需要一种方法来从数据库中获取所有帖子。为此,CodeIgniter 中包含的数据库抽象层 - 查询构建器 - 在 CodeIgniter\Model
中使用。这使得你能够编写一次“查询”,并使其在 所有支持的数据库系统 上运行。Model 类还允许你轻松地使用查询构建器,并提供一些额外的工具来简化数据操作。将以下代码添加到你的模型中。
public function getNews($slug = false)
{
if ($slug === false) {
return $this->findAll();
}
return $this->where(['slug' => $slug])->first();
}
使用这段代码,你可以执行两种不同的查询。你可以获取所有新闻记录,或者通过其 slug 获取新闻条目。你可能已经注意到,$slug
变量在运行查询之前没有转义;查询构建器 会为你完成这项工作。
这里使用的两种方法,findAll()
和 first()
,由 CodeIgniter\Model
类提供。它们已经知道要使用的表,基于我们在 NewsModel
类中设置的 $table
属性。它们是辅助方法,使用查询构建器在当前表上运行它们的命令,并以你选择的格式返回结果数组。在这个例子中,findAll()
返回一个数组数组。
显示新闻
现在查询已经写好了,模型应该与将向用户显示新闻条目的视图绑定。这可以在我们之前创建的 Pages
控制器中完成,但为了清晰起见,定义了一个新的 News
控制器。
添加路由规则
修改你的 app/Config/Routes.php 文件,使其看起来如下
<?php
// ...
use App\Controllers\News; // Add this line
use App\Controllers\Pages;
$routes->get('news', [News::class, 'index']); // Add this line
$routes->get('news/(:segment)', [News::class, 'show']); // Add this line
$routes->get('pages', [Pages::class, 'index']);
$routes->get('(:segment)', [Pages::class, 'view']);
这确保了请求到达 News
控制器,而不是直接到达 Pages
控制器。第二个 $routes->get()
行将带有 slug 的 URI 路由到 News
控制器中的 show()
方法。
创建 News 控制器
在 app/Controllers/News.php 中创建新的控制器。
<?php
namespace App\Controllers;
use App\Models\NewsModel;
class News extends BaseController
{
public function index()
{
$model = model(NewsModel::class);
$data['news'] = $model->getNews();
}
public function show($slug = null)
{
$model = model(NewsModel::class);
$data['news'] = $model->getNews($slug);
}
}
查看代码,你可能会发现它与我们之前创建的文件有一些相似之处。首先,它扩展了 BaseController
,后者扩展了 CodeIgniter 的核心类 Controller
,它提供了一些辅助方法,并确保你可以访问当前的 Request
和 Response
对象,以及 Logger
类,用于将信息保存到磁盘。
接下来,有两个方法,一个用于查看所有新闻项目,另一个用于查看特定新闻项目。
接下来,model()
函数用于创建 NewsModel
实例。这是一个辅助函数。你可以在 全局函数和常量 中了解更多信息。你也可以编写 $model = new NewsModel();
,如果你不使用它。
你可以看到,$slug
变量在第二个方法中传递给模型的方法。模型使用这个 slug 来识别要返回的新闻项目。
完成 News::index() 方法
现在数据通过我们的模型被控制器检索,但还没有显示任何内容。接下来要做的是,将这些数据传递给视图。修改 index()
方法使其看起来像这样
<?php
namespace App\Controllers;
use App\Models\NewsModel;
class News extends BaseController
{
public function index()
{
$model = model(NewsModel::class);
$data = [
'news' => $model->getNews(),
'title' => 'News archive',
];
return view('templates/header', $data)
. view('news/index')
. view('templates/footer');
}
// ...
}
上面的代码从模型中获取所有新闻记录并将其分配给一个变量。标题的值也被分配给 $data['title']
元素,所有数据都被传递给视图。你现在需要创建一个视图来渲染新闻项目。
创建新闻/索引视图文件
创建 **app/Views/news/index.php** 并添加以下代码。
<h2><?= esc($title) ?></h2>
<?php if (! empty($news) && is_array($news)): ?>
<?php foreach ($news as $news_item): ?>
<h3><?= esc($news_item['title']) ?></h3>
<div class="main">
<?= esc($news_item['body']) ?>
</div>
<p><a href="/news/<?= esc($news_item['slug'], 'url') ?>">View article</a></p>
<?php endforeach ?>
<?php else: ?>
<h3>No News</h3>
<p>Unable to find any news for you.</p>
<?php endif ?>
注意
我们再次使用 esc()
来帮助防止 XSS 攻击。但这次我们还传递了“url”作为第二个参数。这是因为攻击模式根据输出使用的上下文而有所不同。
在这里,每个新闻项目都被循环并显示给用户。您可以看到我们用 PHP 和 HTML 混合编写了模板。如果您更喜欢使用模板语言,您可以使用 CodeIgniter 的 视图解析器 或第三方解析器。
完成 News::show() 方法
新闻概述页面现在已经完成,但仍然缺少一个显示单个新闻项目的页面。之前创建的模型是以一种可以轻松用于此功能的方式创建的。您只需要在控制器中添加一些代码并创建一个新的视图。返回到 News
控制器并使用以下内容更新 show()
方法
<?php
namespace App\Controllers;
use App\Models\NewsModel;
use CodeIgniter\Exceptions\PageNotFoundException;
class News extends BaseController
{
// ...
public function show($slug = null)
{
$model = model(NewsModel::class);
$data['news'] = $model->getNews($slug);
if (empty($data['news'])) {
throw new PageNotFoundException('Cannot find the news item: ' . $slug);
}
$data['title'] = $data['news']['title'];
return view('templates/header', $data)
. view('news/view')
. view('templates/footer');
}
}
不要忘记添加 use CodeIgniter\Exceptions\PageNotFoundException;
来导入 PageNotFoundException
类。
而不是在没有参数的情况下调用 getNews()
方法,传递了 $slug
变量,因此它将返回特定的新闻项目。
创建新闻/视图视图文件
唯一剩下的就是创建相应的视图,位于 **app/Views/news/view.php**。将以下代码放入此文件中。
<h2><?= esc($news['title']) ?></h2>
<p><?= esc($news['body']) ?></p>
将您的浏览器指向您的“新闻”页面,即 **localhost:8080/news**,您应该会看到新闻项目的列表,每个项目都有一个链接来显示单个文章。