当前位置: 首页 > 文档资料 > FuelPHP 中文文档 >

控制器 - 一般

优质
小牛编辑
132浏览
2023-12-01

控制器是什幺?

控制器是可透过 URL 到达,并打理处理请求的类别。 控制器呼叫模型和其他类别来取回资讯。最后, 它将传递所有东西到检视来输出。如果像 www.yoursite.com/example/index 的 URL 被请求, 第一分段 ("example") 将会是被呼叫的控制器, 而第二分段 ("index") 将会是控制器被呼叫的方法。

建立控制器

在 FuelPHP,控制器被置于 fuel/app/classes/controller 目录, 并以 "Controller_" 前缀。(选择性)它们应该为了完整的功能集扩充 Controller 类别。 下面是一个控制器 "example" 的範例:

class Controller_Example extends Controller
{

	public function action_index()
	{
		$data['css'] = Asset::css(array('reset.css','960.css','main.css'));
		return Response::forge(View::forge('welcome/index'));
	}
}

可以透过 URL 被请求的方法有 "action_" 前缀。This means 这意味着你可能使用的名称(例如:方法 "list" 不被允许,"action_list" 就没问题) 不会被 PHP 的结构限制。但这也意味着, 你可以让你的控制器公开方法能从其他类别被使用但不能路由。

HTTP 方法前缀动作。

路由到 HTTP 方法前缀的动作是可能的,这里有个範例:

class Controller_Example extends Controller
{
	public function get_index()
	{
		// 当 HTTP 方法是 GET 时将被呼叫。
	}

	public function post_index()
	{
		// 当 HTTP 方法是 POST 时将被呼叫。
	}
}

在子目录的控制器

你也可以将控制器放进子目录中,像 fuel/app/classes/controller/subdir/test.php。在该情况, 控制器必须在类别名称中包含目录名称,像这样:Controller_Subdir_Test

支援无限巢状的子目录,所以 fuel/app/classes/controller/subdir1/subdir2/subdir3/test.php 会有一个 Controller_Subdir1_Subdir2_Subdir3_Test 的类别名称。

控制器的命名空间方式

参阅 命名空间 页面来了解你能如何给你控制器的命名空间

从 URL 使用更多参数

现在,我们在我们的 Controller_Example 也有以下方法:

public function action_name_to_upper($name_1, $name_2)
{
	$data['name_1'] = strtoupper($name_1);
	$data['name_2'] = strtoupper($name_2);
	return View::forge('test/name_to_upper', $data);
}

如果我们使用 www.yoursite.com/example/name_to_upper/fuel/php 呼叫此方法, 它将回传 test/name_to_upper 检视。"FUEL" 以及 "PHP" 将被传递做为 $data 阵列中的 $name_1$name_2 的值。

回传结果

理想情况下,一个控制器动作必须回传一个 Response 物件。你可以选择性的指定特别的 HTTP 表头, 或一个自订的 HTTP 状态码("200 OK" 以外的)。如果你没回传一个 Response 物件,预设 after() 方法会为你包裹动作的回传值在一个 Response 物件中。

如果你的控制器扩充了基础控制器,你的动作也可以回传任何可被转换为字串的任何值, 例如像一个 View 物件。基础控制器的 after() 方法将为你把它转换为一个 Response 物件。

如果你的控制器不扩充基础控制器,而且你想要使用此功能, 你的控制器必须包含它自己的 after() 方法,该方法将接受动作回传的值, 并把它包成一个必须回传的 Reponse 物件。

特殊控制器方法

不要覆写类别建构式 __construct(),使用 before() 替代。 除非你已经先从 Core 研究基础控制器, 并了解它应该如何被扩充而不破坏 Fuel。

action_index()

这个方法将在呼叫控制器如果没带第二参数的时候被呼叫。 在以上範例 www.yoursite.com/example/index 将与 www.yoursite.com/example 一样。

before()

before() 方法被用来当作一个通用方法的前预备方法,来执行在每个控制器方法呼叫时所须的程式码。 这个方法将在来自 URL 的方法在你控制器呼叫之前被执行。 它将不会被呼叫如果该方法不存在。 你不应该使用这方法来作路由决策,如果需要的话,使用 router 方法替代。

after($response)

这个方法将在来自 URL 的方法成功呼叫之后被执行, 这将不会被呼叫如果该方法不存在。$response 参数是必要的。 after() 方法必须回传一个 Response 物件。

如果 after() 方法必须建构一个 Response 物件,它可以使用控制器的 response_status 特性来设定回传的 HTTP 状态码。 预设情况下,此特性包含 "200" (OK)。

router($method, $params)

这个方法将接管内部的控制器路由。一旦控制器被载入, router() 方法将被呼叫并且使用被传入的 $method, 代替预设的方法。它也会传入 $params,以一个阵列, 到该 $method。before() 和 after() 方法仍会如预期运作。

扩充其他控制器

幸好有自动载入器,你可以扩充其他控制器,除了该类别所定义的名称, 不用写更多:

class Controller_Example extends Controller_Welcome
{

	// 你的方法

}

这刚开始听起来可能很奇怪, 但扩充控制器能让你分享方法并很轻鬆地建立基础控制器。

建立基础控制器

基础控制器是一个共享控制器,像 Controller_PublicController_Admin 是用来分享控制器群组之间的逻辑。 例如,Controller_Admin 控制器可能包含你的 login/logout 动作也许还有一个仪表板,但它也可能包含一个检查使用者是否登入做为一个管理者的 before() 方法。 那幺所有在你的管理控制台中其他的控制器将扩充它并且自动被保护。

class Controller_Admin extends Controller
{

	public function before()
	{
		// 检查管理者
	}

	// 你的方法

	public function action_index()
	{
		// 载入仪表板
	}

	public function action_login()
	{
		// 登入使用者
	}
}

该程式码将会在 fuel/app/classes/controller/admin.php, 并且你所有其他的控制器应该在 fuel/app/classes/controller/admin/,像这样:

class Controller_Admin_User extends Controller_Admin
{

	public function action_index()
	{
		// 以使用者 index 列表覆盖仪表板
	}

	public function action_edit($id)
	{
		// 编辑使用者
	}
}