在 Yii2 编程:入门中,我们在本地设置了 Yii2,构建了一个 Hello World 应用程序,设置了一个远程服务器,并使用 Github 部署了我们的代码。本教程将涵盖一些与 MVC 框架实现相关的 Yii 更基本的概念:模型、视图和控制器。我们还将探索导航菜单和 Bootstrap 元素的布局和自定义。
对于这些示例,我们假设我们正在构建一个用于发布简单状态更新的框架,例如我们自己的迷你推特。但是,我们不会将数据存储在数据库中。我将把它留到下一个教程中,该教程将探索 Yii 的脚手架功能,称为 Gii。
Gii 自动化并简化了我们将在本教程中执行的所有操作,但了解基本概念并至少手动执行这些任务一次非常重要。
模型
什么是模型?维基百科说:“当其状态发生变化时,模型会通知其关联的视图和控制器。此通知允许视图生成更新的输出,并允许控制器更改可用的命令集。 ”
对我来说,模型通常代表我在“外部”世界中构建的任何内容的概念。因此,如果我们考虑状态更新,状态模型将包含状态更新的所有属性以及与查询或更改状态相关的所有函数或方法。
最佳实践是在模型中构建尽可能多的功能和智能。在 MVC 实践中,您构建“重型”模型,而构建轻型控制器和视图。 Yii 提供了一些优秀的功能,这些功能专门针对您在 Web 和应用程序开发中所做的事情,可以简化模型构建,尤其是在表单和数据库方面;其中大部分内容我们将在后面的教程中探讨。
让我们创建我们的状态模型。对于我们的编码示例,您可以使用 Git 存储库。我正在以我们在入门教程中创建的内容为基础进行构建 - 我已将其标记在此处以供参考。已完成教程的 Github 存储库位于此处。
我们将在 /hello/models/Status.php
中创建 Status.php。要发布状态消息,我们需要从用户收集消息文本。我们还将创建一个用于公开或私下发布的权限字段。
<?php
namespace app\models;
use yii\base\Model;
class Status extends Model
{
const PERMISSIONS_PRIVATE = 10;
const PERMISSIONS_PUBLIC = 20;
public $text;
public $permissions;
public function rules()
{
return [
[[\'text\',\'permissions\'], \'required\'],
];
}
public function getPermissions() {
return array (self::PERMISSIONS_PRIVATE=>\'Private\',self::PERMISSIONS_PUBLIC=>\'Public\');
}
public function getPermissionsLabel($permissions) {
if ($permissions==self::PERMISSIONS_PUBLIC) {
return \'Public\';
} else {
return \'Private\';
}
}
}
?>
注意规则函数——Yii 的表单验证使用它来确保用户在每个字段中输入适当的信息。 Yii 使用 JavaScript 在用户输入时验证表单。
我创建的 getPermissions()
函数将用于表单的下拉列表元素。
现在,让我们继续创建一个控制器,以允许用户创建和查看文本更新。
控制器
什么是控制器?维基百科说,“控制器可以向模型发送命令来更新模型的状态(例如,编辑文档)。它还可以向其关联的视图发送命令以更改模型的视图呈现。 ”在典型的 Yii Web 应用程序中,页面的 URL 路径调用控制器来使用模型加载页面数据并使用视图渲染页面。
最好在单个控制器中对相关功能进行逻辑分组。控制器的不同方法(称为操作)实现每个功能。这些通常对应于特定页面。例如,http://localhost:8888/hello/web/status/create 将调用我们要构建的 StatusController 的创建操作。
当您开发与 Status 相关的功能时,您可以将这些功能分组到一个 StatusController.php 中。现在,我们只构建一个创建函数。
在 /hello/controllers/
中,创建 StatusController.php:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\Status;
class StatusController extends Controller
{
public function actionCreate()
{
$model = new Status;
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// valid data received in $model
return $this->render(\'view\', [\'model\' => $model]);
} else {
// either the page is initially displayed or there is some validation error
return $this->render(\'create\', [\'model\' => $model]);
}
}
}
?>
表单创建操作通常会调用模型数据,然后根据它们是否是 POST 操作的一部分进行派生。如果没有,则显示空表单。如果他们收到发布的数据,则会对其进行验证和处理。在我们的例子中,这意味着继续渲染视图文件。
观看次数
什么是视图?维基百科说:“视图从模型中请求信息,用于为用户生成输出表示。”在 Yii 中,视图使用类似 PHP 的模板语言将页面输出渲染为 HTML,利用模型加载的数据和从控制器传递的数据。
视图通常位于与关联控制器相关的单个文件夹中,例如StatusController 视图位于 views/status
文件夹中。
在 Yii 中,表单代码通常包含在所谓的分部视图中。这些文件通常以下划线前缀命名。它们应该包含在其他视图中。这允许创建和更新页面重用实际的表单代码。
首先,我们将创建呈现表单的“创建”视图。然后,我们还将创建一个视图视图来显示我们发布的状态更新。在接下来的教程中,当我们使用实际的数据库、存储和检索数据时,这会有所不同。
这是我们的 /hello/views/status.view.php
视图文件的一个简单示例,用于呈现发布的数据:
<?php
use yii\helpers\Html;
?>
<h1>Your Status Update</strong></h1>
<p><label>Text</label>:</p>
<?= Html::encode($model->text) ?>
<br /><br />
<p><label>Permissions</label>:</p>
<?php
echo $model->getPermissionsLabel($model->permissions);
?>
请注意视图文件是 HTML 和 PHP 的混合体。当控制器接收到发布的数据时,它会渲染上面的视图,显示用户提交的数据。
但是,现在我们来谈谈表单并构建创建表单视图文件。
表格
表单是我们在网络开发中每天用来收集用户数据的工具,通常用于将用户输入提交到数据库。 Yii 提供了大量的帮助程序代码来简化构建、验证、保护和发布表单数据的过程。在 Yii 中,表单是一种视图。
以下是用于创建状态更新的示例表单:
'
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use app\models\Status;
?>
<?php $form = ActiveForm::begin();?>
<?= $form->field($model, \'text\')->textArea([\'rows\' => \'4\'])->label(\'Status Update\'); ?>
<?=
$form->field($model, \'permissions\')->dropDownList($model->getPermissions(),
[\'prompt\'=>\'- Choose Your Permissions -\']) ?>
<div class="form-group">
<?= Html::submitButton(\'Submit\', [\'class\' => \'btn btn-primary\']) ?>
</div>
<?php ActiveForm::end(); ?>
Yii2 ActiveForm 小部件用于为我们的输入字段生成 HTML。请注意下拉列表如何调用 Status 模型 getPermissions
方法。
单击“提交”按钮将返回到 StatusController 的创建操作。当接收到发布的数据时,它会呈现 view.php 文件而不是 create.php 表单文件。
以下是使用 view.php 呈现时视图文件的显示方式:
接下来,让我们更新全局导航栏以包含状态创建表单的链接。
布局
布局是网站大多数外部重复元素的模板,例如 HTML 文档包装器、页眉、导航栏和页脚。由于这些对于网站的大多数页面来说都是通用的,因此它们在布局中构建一次,并且不会在代码中的任何地方重复。
如果你查看\hello\views\layouts\main.php
,你可以看到外部布局的结构:
<?php
use yii\helpers\Html;
use yii\bootstrap\Nav;
use yii\bootstrap\NavBar;
use yii\widgets\Breadcrumbs;
use app\assets\AppAsset;
/* @var $this \yii\web\View */
/* @var $content string */
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
<head>
<meta charset="<?= Yii::$app->charset ?>"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<?= Html::csrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
<div class="wrap">
<?php
NavBar::begin([
\'brandLabel\' => \'My Company\',
\'brandUrl\' => Yii::$app->homeUrl,
\'options\' => [
\'class\' => \'navbar-inverse navbar-fixed-top\',
],
]);
echo Nav::widget([
\'options\' => [\'class\' => \'navbar-nav navbar-right\'],
\'items\' => [
[\'label\' => \'Home\', \'url\' => [\'/site/index\']],
[\'label\' => \'About\', \'url\' => [\'/site/about\']],
[\'label\' => \'Contact\', \'url\' => [\'/site/contact\']],
Yii::$app->user->isGuest ?
[\'label\' => \'Login\', \'url\' => [\'/site/login\']] :
[\'label\' => \'Logout (\' . Yii::$app->user->identity->username . \')\',
\'url\' => [\'/site/logout\'],
\'linkOptions\' => [\'data-method\' => \'post\']],
],
]);
NavBar::end();
?>
<div class="container">
<?= Breadcrumbs::widget([
\'links\' => isset($this->params[\'breadcrumbs\']) ? $this->params[\'breadcrumbs\'] : [],
]) ?>
<?= $content ?>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-left">© My Company <?= date(\'Y\') ?></p>
<p class="pull-right"><?= Yii::powered() ?></p>
</div>
</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>
视图主要代表网站的内部页面主体,即页眉和导航栏以及页脚开头之间的内容。当布局回显 $content
:
<div class="container">
<?= Breadcrumbs::widget([
\'links\' => isset($this->params[\'breadcrumbs\']) ? $this->params[\'breadcrumbs\'] : [],
]) ?>
<?= $content ?>
</div>
Yii 允许您为每个应用程序构建多个布局,尽管这并不总是必要的。这取决于您的应用程序。控制器提供默认布局,您可以针对任何给定操作覆盖此布局。如果您的控制器对相关活动进行逻辑分组,则用户界面很可能会对控制器内的所有操作使用相同的布局。
现在,让我们更新导航栏以包含带有“创建”操作的状态菜单。由于 Yii2 使用 Bootstrap 进行布局和样式,我们只需要告诉它创建一个 Bootstrap 下拉列表。
更新 Nav::widget
以拥有嵌套数组:
echo Nav::widget([
\'options\' => [\'class\' => \'navbar-nav navbar-right\'],
\'items\' => [
[\'label\' => \'Home\', \'url\' => [\'/site/index\']],
[
\'label\' => \'Status\',
\'items\' => [
[\'label\' => \'Create\', \'url\' => [\'/status/create\']],
],
],
[\'label\' => \'About\', \'url\' => [\'/site/about\']],
[\'label\' => \'Contact\', \'url\' => [\'/site/contact\']],
Yii::$app->user->isGuest ?
[\'label\' => \'Login\', \'url\' => [\'/site/login\']] :
[\'label\' => \'Logout (\' . Yii::$app->user->identity->username . \')\',
\'url\' => [\'/site/logout\'],
\'linkOptions\' => [\'data-method\' => \'post\']],
],
]);
这是您应该看到的内容:
下一步是什么?
现在您已经了解了 Yii 的 MVC 架构在实践中如何工作,包括模型、视图、控制器、表单和布局,我们将为状态创建一个数据库模式,并使用 Yii 的脚手架生成器 Gii 来构建所有这对我们来说是自动的。事情会开始进展得更快一些。
如果您想知道下一个 Yii2 教程何时发布,请在 Twitter 上关注我 @reifman 或查看我的 Tuts+ 讲师页面。我的讲师页面将立即包含本系列的所有文章。
相关链接
- Yii 框架网站
- Yii 框架简介 (Tuts+)
- 使用 Yii2 编程:入门(Tuts+)
- 作者提供的其他免费开源 Yii 开发人员示例