卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章16906本站已运行3322

CodeIgniter:探索视图和模板

视图是任何 MVC 应用程序中的关键组成部分,CodeIgniter 应用程序也不例外。今天,我们将了解什么是视图,并了解如何使用它们为您的 CodeIgniter 项目创建模板解决方案。

本教程的第一部分将向 CodeIgniter 的初学者介绍什么是视图以及如何在典型应用程序中使用它们。后半部分将讨论寻找模板解决方案的动机,并指导读者完成创建简单而有效的模板库的必要步骤。

如果您想使用 CodeIgniter 做更多事情,请查看 Envato Market 上的 CodeIgniter 插件和代码脚本范围。

CodeIgniter:探索视图和模板


什么是视图?

视图是 CodeIgniter 中用于存储应用程序输出的标记的特殊文件,通常由 HTML 和简单的 PHP 标记组成。

“视图只是一个网页,或者一个页面片段,比如页眉、页脚、侧边栏等。事实上,如果您需要的话,视图可以灵活地嵌入到其他视图中(在其他视图中,等等)等级制度的类型。”

视图从控制器方法内加载,视图内的内容随后显示在浏览器中。


如何加载视图

为了在 CodeIgniter 中加载(并显示)视图,我们使用内置的 Loader 库。

$this->load->view(\'hello_world\', $data, true/false);

这行代码将告诉 CodeIgniter 在 application/views 文件夹中查找 hello_world.php ,并在浏览器中显示该文件的内容。

请注意,CodeIgniter 允许您排除 .php 后缀,从而在键入要加载的视图文件名时节省一些击键次数。

第二个参数 $data可选,并采用关联数组或对象。该数组/对象用于将数据传递到视图文件,因此可以在视图中使用或引用它。

最后一个可选参数确定视图的内容是显示在浏览器窗口中,还是作为字符串返回。该参数默认为false,在浏览器中显示内容。我们将在本教程后面看到如何在创建模板解决方案时使用此参数。


创建并显示视图

要设置我们的第一个视图,请在 application/views 中创建一个名为 hello_world.php 的新文件,并在其中编写以下简单的 HTML:

<!DOCTYPE html>
<html>
	<head>
		<title>Hello World!</title>
	</head>
	<body>
		<p>
			Hello world!
		</p>
	</body>
</html>

现在要在浏览器中显示此视图,必须使用上述方法将其加载到控制器方法中。

因此,让我们在 application/controllers 中创建一个名为 hello_world.php 的新控制器文件,并在其中放置以下代码。从这个控制器中,我们将加载新创建的视图。

<?php if ( ! defined(\'BASEPATH\')) exit(\'No direct script access allowed\');

class Hello_world extends CI_Controller {
	
	public function index() 
	{
		$this->load->view(\'hello_world\');
	}
}

将浏览器指向 http://your-ci-install.com/index.php/ 现在将导致 application/views/hello_world.php 中的 HTML 在浏览器中输出。您已成功加载视图!

加载多个视图

将视图拆分为多个文件可以使您的网站更易于维护,并减少重复代码的可能性。

显示单个视图固然很好,但您可能希望将输出拆分为多个不同的文件,例如页眉、内容和页脚视图。

只需多次调用 $this->load->view() 方法即可加载多个视图。然后,CodeIgniter 将视图的内容连接在一起,然后再显示在浏览器中。

application/views 中创建一个名为 header.php 的新文件,并剪切并粘贴原始 hello_world.php 文件中的前几行。

<!DOCTYPE html>
<html>
	<head>
		<title>Hello World!</title>
	</head>
	<body>

同样,在 application/views 中创建另一个名为 footer.php 的文件,并将 hello_world.php 的最后两行移入。

</body>
</html>

这使得 hello_world.php 视图文件仅包含我们的页面内容。

<p>
	Hello world!
</p>

现在要再次显示页面,我们必须在控制器中按顺序加载所有三个视图(header.php、hello_world.php、footer.php)。

重新打开 application/controllers/hello_world.php 并在现有调用的上方和下方添加新的 $this->load->view() 调用。

<?php if ( ! defined(\'BASEPATH\')) exit(\'No direct script access allowed\');

class Hello_world extends CI_Controller {
	
	public function index() 
	{
		$this->load->view(\'header\');
		$this->load->view(\'hello_world\');
		$this->load->view(\'footer\');
	}
}

由于页眉和页脚视图现在与 hello_world 视图分开,这意味着它们可以与网站中的任何其他视图结合使用。这意味着页眉和页脚文件中的代码不需要复制到项目中需要此代码的任何其他视图中。

显然,这是一个巨大的好处,因为对视图中的 HTML 或内容的任何更改(例如,向标题添加新的样式表)只能对一个文件进行,而不是对每个文件进行!


在视图中使用来自控制器的数据

现在,我们将研究从控制器传递数据,以便可以在视图内使用或输出它们。

为此,我们将传递一个关联数组 $data 作为 $this->load->view() 调用中的第二个参数。

该数组的将在加载的视图中作为变量进行访问,由各自的命名。

$data = array(

	\'title\'		=>	\'Hello World!\',
	\'content\'	=>	\'This is the content\',
	\'posts\'		=>	array(\'Post 1\', \'Post 2\', \'Post 3\')

);

$this->load->view(\'hello_world\', $data);

上面的代码将为变量 $title 赋予值“Hello World!”在 hello_world 视图内。

如何在视图中使用变量

一旦我们将数据传递到视图文件,就可以按照通常的方式使用变量。

通常,视图文件将使用传递的数据来:

  • 显示变量的值
  • 循环数组或对象属性
  • 使用条件语句显示或隐藏标记

我将通过快速示例来说明如何执行每个操作。

要显示变量的内容,请使用简单且熟悉的 echo 语句:

	<h1><?php echo $title; ?></h1>

循环遍历数组或对象是视图文件中的常见任务,可以使用 foreach 循环来实现:

<ul>
<?php foreach($posts as $post) { ?>
	
	<li><?php echo $post; ?></li>
	
<?php } ?>
</ul>

可以在视图文件中使用简单的条件语句来稍微改变输出,具体取决于传递的数据。

一般来说,您希望尽量减少视图中条件语句的使用,因为过度使用可能会导致包含“业务逻辑”的复杂视图文件。将视图拆分为不同的文件,并决定在控制器中显示哪个文件是更可取的。

<?php if ( $logged_in ) { ?>

	<p><?php echo \'Welcome \'.$user_name; ?></p>
	
<?php } else { ?>

	<p>Please login</p>
	
<?php } ?>

上面的示例将显示“欢迎”消息,或要求用户登录的请求,具体取决于 $logged_in 的值(true/false)。


CodeIgniter 中的模板

我们已经了解了如何将视图拆分为单独的较小文件可以帮助组织和减少 CodeIgniter 项目中的文件数量,但现在每个显示页面的实例都需要进行多个加载视图调用。

假设您有单独的页眉和页脚视图,它们用于形成模板。项目中您希望使用此模板加载和显示页面的每个实例,都必须调用三个视图加载。这不仅会使您的控制器变得混乱,还会导致大量重复代码 - 这正是我们希望通过拆分文件来摆脱的事情。

如果您现在想向此模板添加额外的标记,例如侧边栏菜单。它可以放在标题视图中,但更适合放在自己的单独视图中。将这个新视图添加到现有模板意味着要遍历视图加载的每个实例,然后添加另一个实例。这可能会很快变得混乱。

我们需要一种方法,能够将显示单个页面内容的视图文件嵌入模板内,而无需重复代码,并且允许轻松高效地对模板进行修改。

以下步骤将指导您创建一个简单的 CodeIgniter 库来满足这些需求,以及:

  • 为您的视图实施可预测且可维护的目录结构
  • 允许使用多个不同的模板
  • 将页面视图的加载减少为一行代码

一旦库被编写并放入我们的 CodeIgniter 工具带中,我们将能够显示一个模板化页面,如下所示:

$this->template->load(\'template_name\', \'body_view\');

好多了!

我们的模板解决方案将使用包含模板完整标记的视图文件,以及要嵌入其中的另一个视图文件(包含页面内容)的占位符。

占位符实际上只是一个名为 $body 的变量。当使用我们的库加载模板化视图时,相应的正文视图文件的内容将被分配给此 $body,将视图嵌入到模板中。


第 1 步:设置目录

我们希望为要存放的视图文件强制执行一个合理且可预测的目录系统,以便我们的视图:

  • 易于定位
  • 轻松确定它们属于应用程序的哪个区域
  • 易于维护

我们的目录系统还允许库巧妙地确定在哪里查找视图文件,从而减少加载模板化视图所需的代码量。

application/views 目录中创建一个新文件夹,并将其命名为 templates。该文件夹将保存不同的模板视图。


第 2 步:创建库

CodeIgniter 中的库只是 PHP 类,并且像视图一样加载到控制器中。

$this->load->library(\'class_name\');

您在 CodeIgniter 项目中使用的自定义库存储在 application/libraries 文件夹中。要开始编写我们的模板库,请在此文件夹中创建一个名为 Template.php 的新文件,并将以下代码放入:

<?php  if ( ! defined(\'BASEPATH\')) exit(\'No direct script access allowed\');

	class Template 
	{
		var $ci;
		
		function __construct() 
		{
			$this->ci =& get_instance();
		}
	}

上面的代码定义了一个名为 Template 的新类或库,以及其中的 __construct() 方法。

此方法将 CodeIgniter 超级对象分配给 $ci 类变量,从而通过在通常的方法调用中将 $this 替换为 $this->ci 来允许使用 CodeIgniter 的所有资源。

当CodeIgniter框架加载该库时,会自动调用__construct()方法。

编写加载方法

现在我们将编写实际加载模板视图的方法。我们希望向此函数传递最多三个参数:

  • 模板名称
  • 主体视图名称(可选)
  • 要传递给视图的数据(可选)

调用此方法的结果将是在浏览器中显示模板视图,并嵌入其中的正文视图(如果提供了)。

__construct() 方法下面,放置以下代码:

function load($tpl_view, $body_view = null, $data = null) 
{
	if ( ! is_null( $body_view ) ) 
	{
		if ( file_exists( APPPATH.\'views/\'.$tpl_view.\'/\'.$body_view ) ) 
		{
			$body_view_path = $tpl_view.\'/\'.$body_view;
		}
		else if ( file_exists( APPPATH.\'views/\'.$tpl_view.\'/\'.$body_view.\'.php\' ) ) 
		{
			$body_view_path = $tpl_view.\'/\'.$body_view.\'.php\';
		}
		else if ( file_exists( APPPATH.\'views/\'.$body_view ) ) 
		{
			$body_view_path = $body_view;
		}
		else if ( file_exists( APPPATH.\'views/\'.$body_view.\'.php\' ) ) 
		{
			$body_view_path = $body_view.\'.php\';
		}
		else 
		{
			show_error(\'Unable to load the requested file: \' . $tpl_name.\'/\'.$view_name.\'.php\');
		}
		
		$body = $this->ci->load->view($body_view_path, $data, TRUE);
		
		if ( is_null($data) ) 
		{
			$data = array(\'body\' => $body);
		}
		else if ( is_array($data) )
		{
			$data[\'body\'] = $body;
		}
		else if ( is_object($data) )
		{
			$data->body = $body;
		}
	}
	
	$this->ci->load->view(\'templates/\'.$tpl_view, $data);
}

上面的代码首先检查 $body_view 参数是否已提供给该方法。该变量将保存要用作模板视图中的正文的视图的名称。

	if ( ! is_null( $body_view ) )

如果提供了该参数,则会进行一系列 file_exists 检查,以尝试在目录系统中找到视图文件。

if ( file_exists( APPPATH.\'views/\'.$tpl_view.\'/\'.$body_view ) ) 
{
	$body_view_path = $tpl_view.\'/\'.$body_view;
}
else if ( file_exists( APPPATH.\'views/\'.$tpl_view.\'/\'.$body_view.\'.php\' ) ) 
{
	$body_view_path = $tpl_view.\'/\'.$body_view.\'.php\';
}

该代码首先尝试在 application/views 文件夹中与模板同名的文件夹内找到视图文件。

如果项目的各个部分与其他部分截然不同并且使用不同的模板,这非常有用。在这些情况下,将这些视图文件分组在一起是有意义的。

例如,许多网站为不同的部分(例如博客)显示不同的模板。在我们的系统中,博客视图文件可以放置在 application/views/blog 文件夹中,将它们与主站点视图分开。

如果无法在此文件夹中找到视图文件,则将 .php 附加到文件名末尾,并再次进行检查。这只是为了像本地 $this->load->view() 调用一样排除 .php

如果仍然找不到该文件,则会进一步检查其位置。

else if ( file_exists( APPPATH.\'views/\'.$body_view ) ) 
{
	$body_view_path = $body_view;
}
else if ( file_exists( APPPATH.\'views/\'.$body_view.\'.php\' ) ) 
{
	$body_view_path = $body_view.\'.php\';
}
else 
{
	show_error(\'Unable to load the requested file: \' . $tpl_name.\'/\'.$view_name.\'.php\');
}

这次,代码检查视图文件是否位于 application/views 文件夹内,如果找不到,则追加 .php 并再次检查。

如果文件位于这些位置之一,则将路径分配给 $body_view_path,否则使用 CodeIgniter 内置的 show_error() 函数会抛出错误消息,并终止脚本。

如果成功找到正文视图文件,则内容将分配给 $body 变量。

	$body = $this->ci->load->view($body_view_path, $data, TRUE);

我们将 $data 参数(如果未提供则为 null)传递给视图加载调用,并将第三个参数设置为 true 以将视图的输出作为字符串返回。

我们现在将这个 $body 变量添加到 $data 中的数据列表中,以便在加载时可以将其嵌入到模板视图中。

if ( is_null($data) ) 
{
	$data = array(\'body\' => $body);
}
else if ( is_array($data) )
{
	$data[\'body\'] = $body;
}
else if ( is_object($data) )
{
	$data->body = $body;
}

如果 $data 未提供给 load() 调用,则 $data 会被分配到键 body 下包含 $body 的数组。如果提供了参数,则将 $body 添加到列表中,方法是将其分配给数组键或对象属性,两者也都命名为 body

$body 变量现在可以在模板视图文件中用作嵌入视图的占位符

我们方法的最后一行从 application/views/templates 文件夹加载模板视图文件,并在第二个参数中传递 $data 变量。

	$this->ci->load->view(\'templates/\'.$tpl_name, $data);

就是这样!该库现在可以投入使用了。


使用库

要开始使用我们的库,让我们在 application/views/templates 中创建一个名为 default.php 的模板视图,并将以下 HTML/PHP 放入其中:

<!DOCTYPE html>
<html>

	<head>
		<title><?php echo $title; ?></title>
	</head>

	<body>
	
		<h1>Default template</h1>
		
		<div class="wrapper">
			
			<?php echo $body; ?>
			
		</div>
		
	</body>
	
</html>

在此模板中,我们引用两个变量,$title$body

回想一下,在我们的模板文件中,$body 用作嵌入视图的占位符。

我们现在将制作另一个视图嵌入到该模板中。在 application/views/ 中创建一个名为 content.php 的新文件,并将以下简单的 HTML 放入其中:

<p>
	Hello world!
</p>

我们现在准备从控制器内加载模板化页面视图。

在任何控制器方法内,放置以下代码以在 default 模板内显示 content 视图。

$data = array(

	\'title\' => \'Title goes here\',
	
);

$this->load->library(\'template\');
$this->template->load(\'default\', \'content\', $data);

注意:必须先加载该库,然后才能调用 load 方法。为了避免每次需要显示模板视图时加载库,

通过将类添加到 application/config/autoload.php 中的库数组来自动加载该类。

如果您希望在模板中嵌入字符串而不是视图文件,只需使用键 body 将字符串分配给 $data 数组,并传递 null 作为加载调用中的第二个参数。

$data = array(

	\'title\' => \'Title goes here\',
	\'body\'	=> \'The string to be embedded here!\'
	
);

$this->template->load(\'default\', null, $data);

快速提示

我发现按控制器甚至它们所属的方法将视图文件分组到文件夹中确实有助于使我的视图井然有序且易于查找。

以这种方式组织视图会导致目录结构紧密遵循 controller/method 的 URL 架构。

例如,假设您的项目有一个名为 Members 的控制器,包含方法 list

list 视图文件的适当位置应位于 application/views/membersapplication/views/members/list(如果此方法加载多个视图)。

然后可以使用我们的库通过以下代码将该视图嵌入到模板中:

$this->template->load(\'template_name\', \'members/list\');

结论

本教程中讨论的模板解决方案只是在 CodeIgniter 中实现模板的众多不同方法之一。

希望您现在应该知道什么是视图,以及如何在您的 CodeIgniter 项目中有效且高效地使用它们。

本教程中讨论的模板解决方案只是在 CodeIgniter 中实现模板的众多不同方法之一。有多种不同的方法,我鼓励读者研究其他方法并确定哪种方法最适合您的项目。

如果您对本教程有任何意见或疑问,或者对不同模板解决方案有任何见解,请在下面发表评论!感谢您的阅读。

卓越飞翔博客
上一篇: php中设计模式有哪些
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏