视图

视图本质上是网页或页面片段(如页眉、页脚、侧边栏等)。实际上,视图支持灵活嵌套;如有层级需求,可将视图嵌入其他视图,甚至实现多层嵌套。

视图无法直接调用,必须通过控制器或 视图路由 加载。

在 MVC 架构中,控制器承担着“交通指挥”的角色,负责调取特定视图。如尚未阅读 控制器 章节,建议在继续前先行阅读。

下面以此前创建的示例控制器为例,演示如何添加视图。

创建视图

使用文本编辑器创建名为 blog_view.php 的文件,内容如下:

<html>
    <head>
        <title>My Blog</title>
    </head>
    <body>
        <h1>Welcome to my Blog!</h1>
    </body>
</html>

然后将文件保存到 app/Views 目录。

显示视图

要加载并显示特定视图文件,在控制器中使用 view() 函数,代码如下:

return view('name');

其中 name 为视图文件名。

重要

省略文件扩展名时,视图文件默认以 .php 为扩展名。

备注

view() 函数内部使用 视图渲染器

app/Controllers 目录中创建名为 Blog.php 的文件,内容如下:

<?php

namespace App\Controllers;

class Blog extends BaseController
{
    public function index()
    {
        return view('blog_view');
    }
}

打开位于 app/Config/Routes.php 的路由文件,找到”Route Definitions”部分, 添加以下代码:

use App\Controllers\Blog;

$routes->get('blog', [Blog::class, 'index']);

访问站点即可看到新视图。URL 大致如下:

example.com/index.php/blog/

加载多个视图

CodeIgniter 会智能处理控制器中对 view() 的多次调用。如果发生多次调用,结果会拼接在一起。

例如,可能需要一个页眉视图、一个菜单视图、一个内容视图和一个页脚视图。大致如下:

<?php

namespace App\Controllers;

use CodeIgniter\Controller;

class Page extends Controller
{
    public function index()
    {
        $data = [
            'page_title' => 'Your title',
        ];

        return view('header')
            . view('menu')
            . view('content', $data)
            . view('footer');
    }
}

上例中使用了”动态添加的数据”,见下文说明。

将视图存储在子目录中

如果希望更有条理,视图文件也可以存储在子目录中。 此时加载视图时需要在文件名中包含目录路径。示例:

return view('directory_name/file_name');

命名空间视图

可以将视图存储在命名空间下的 View 目录中,然后像使用命名空间一样加载该视图。 虽然 PHP 不支持从命名空间加载非类文件,CodeIgniter 提供了此功能, 使视图可以像模块一样打包,便于复用或分发。

如果 example/blog 目录在 自动加载器 中配置了 PSR-4 映射, 命名空间为 Example\Blog,则可以像使用命名空间一样加载视图文件。

按照此示例,可以在 example/blog/Views 中加载 blog_view.php 文件, 只需在视图名前加上命名空间前缀:

<?php

return view('Example\Blog\Views\blog_view');

缓存视图

使用 view() 函数可以缓存视图,在第三个参数中传入 cache 选项, 指定缓存秒数:

// Cache the view for 60 seconds
return view('file_name', $data, ['cache' => 60]);

默认情况下,视图以视图文件名作为缓存名。可通过传入 cache_name 和期望的缓存 ID 来自定义:

// Cache the view for 60 seconds
return view('file_name', $data, ['cache' => 60, 'cache_name' => 'my_cached_view']);

向视图添加动态数据

数据通过 view() 函数的第二个参数(数组形式)从控制器传递给视图。

示例如下:

$data = [
    'title'   => 'My title',
    'heading' => 'My Heading',
    'message' => 'My Message',
];

return view('blog_view', $data);

在控制器文件中试试。打开控制器并添加以下代码:

<?php

namespace App\Controllers;

class Blog extends BaseController
{
    public function index()
    {
        $data['title']   = 'My Real Title';
        $data['heading'] = 'My Real Heading';

        return view('blog_view', $data);
    }
}

然后打开视图文件,将文本替换为与数据数组键对应的变量:

<html>
    <head>
        <title><?= esc($title) ?></title>
    </head>
    <body>
        <h1><?= esc($heading) ?></h1>
    </body>
</html>

通过之前使用的 URL 加载页面,即可看到变量被替换为对应值。

saveData 选项

传入的数据会在后续 view() 调用中保留。如果 在同一次请求中多次调用该函数,无需在每次 view() 时重复传入数据。

但这可能导致数据”渗透”到其他视图中,潜在引发问题。如果希望在每次调用后清理数据, 可在第三个参数的 $option 数组中传入 saveData 选项。

$data = [
    'title'   => 'My title',
    'heading' => 'My Heading',
    'message' => 'My Message',
];

return view('blog_view', $data, ['saveData' => false]);

此外,如果希望 view() 函数的默认行为就是每次调用后清除数据, 可以在 app/Config/Views.php 中将 $saveData 设置为 false

创建循环

传递给视图文件的数组不限于简单变量,还可以传递多维数组, 通过循环生成多行数据。例如,从数据库获取的数据通常是多维数组格式。

简单示例如下。在控制器中添加以下代码:

<?php

namespace App\Controllers;

class Blog extends BaseController
{
    public function index()
    {
        $data = [
            'todo_list' => ['Clean House', 'Call Mom', 'Run Errands'],
            'title'     => 'My Real Title',
            'heading'   => 'My Real Heading',
        ];

        return view('blog_view', $data);
    }
}

然后打开视图文件,创建循环:

<html>
<head>
    <title><?= esc($title) ?></title>
</head>
<body>
    <h1><?= esc($heading) ?></h1>

    <h2>My Todo List</h2>

    <ul>
    <?php foreach ($todo_list as $item): ?>

        <li><?= esc($item) ?></li>

    <?php endforeach ?>
    </ul>

</body>
</html>