Yii2系列教程二:MVC,Forms和Layouts
上一篇文章我们简单地实现了Yii2
框架安装和Hello World
,而在这一篇文章当中,我们会带着好奇之心去探索一下在Yii2中的几个重要的元素组成:MVC
,Forms
和Layouts
。
本文的目标是创建一个小小的表单应用,就是实现一个简单的类似发微博的功能,但是我还不想牵扯到数据库那一块,因为其实数据库和表在Yii2框架之中其实还是有很多东西可以讲的,打算在下一篇的文章中会详细讲到。
MVC
模型(Model)
对于我个人的简单理解就是一个概念集合,在这个集合里面包含该概念集合的多种数据,比如一个User
会有姓名,性别等多个属性,这个概念集合通常就是对于数据库的一张表(如果还没有对应的数据表,则可以看作是一个集合的属性);而每一个具体的实例概念就对应一条数据记录。比如在这一篇文章之中我们会创建一个Status
模型,代表状态(来源于生活:发一条状态),这个Status会有两个重要的属性,text
和permissions
,text
就是状态本身,permissions
是状态的权限。
视图(Views)
通过控制器想模型请求数据,并将数据以某种特定的版式展示给用户。
控制器(Controller)
可以向Model
和Views
发送不同的指令,一般是向Model取数据,然后读取视图文件来渲染输出数据。
在Yii2的应用中,一般是这样的:某个URL指向某个控制器的特定action
,然后控制器负责向特定的模型取数据,然后将数据分配给视图渲染输出。
在这里说一下我个人的观点,我觉得其实在MVC
当中,可能应该做事最多的应该是Model
,与之相迎合的是,Controller
和Views
则相对要轻一些,Controller
负责协调Model
和Views
,Views负责展示数据。
在Yii2的项目当中,我们将models
文件放在/models/
目录之下,所以我们在这个文件夹之下创建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';
}
}
}
这里需要注意的是rules()
这个方法,它会触发Yii自带的表单验证规则,比如这里就是text
和permissions
这两个表单输入框都不能为空,至于getPermissions()
这个方法是为了在使用dropdown
输入框的时候使用的。
Status
模型创建好之后,我们就可以接着创建对应的控制器和方法。在平时的开发中我习惯是为每一个模型都创建一个对应的控制器,里面一般都是包含几个最常见的方法:index
, create
, store
, update
, delete
等。这里我创建一个StatusController.php
,这个文件应该是位于/controllers/
文件夹当中,而我们希望实现一个发表状态的功能,我们必须需要一个create
操作方法,比如我们的目的是:在用户访问http://localhost:8999/status/create
的时候,我们可以展示创建一条状态的页面给用户。
<?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()) {
// $model 有post数据时直接展示
return $this->render('view', ['model' => $model]);
} else {
// 没有数据的时候,直接渲染create视图
return $this->render('create', ['model' => $model]);
}
}
}
首先,根据URL的规则,我们创建了一个actionCreate()
方法,在这个方法里,我们通过条件判断来确定展示某个特定的视图。
创建好控制器和方法之后,我们就可以走到下一步了:创建视图。在Yii2中,视图文件的存放位置跟控制器的名字是息息相关的,比如上面我们创建了一个StatusController
,我们现在首先需要在views/
创建一个status/
文件夹,然后在这个文件夹里创建各个跟StatusController
相关的视图文件,比如上面actionCreate()
中return $this->render()
两个视图:view.php
和create.php
Forms
首先,我们需要一个Create
视图来展示我们创建Status
的表单(create.php)
:
<?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(); ?>
在我们平时开发web应用的时候,表单几乎总是每时每刻都得存在,只要是需要收集信息的地方就需要表单。而Yii2在对表单支持这方面做得非常不错,就如你看到的一样,上面的Yii2 ActiveForm就是Yii2内置的用来帮助我们生成表单的小组件,这里需要注意的是dropDownList
这个输入框式怎么实现的,它直接使用了getPermissions()
,这个方法正好返回了一个我们需要的数组。
这时候访问:http://localhost:8999/status/create
就可以看到上面创建的表单了:
至于为什么就自动排版好了,不用我们写css,那是因为Yii2默认会给我们加载Bootstrap的css文件,所以我们在使用的时候直接指定类名就OK了。而且很明显地,我们可以看到,一旦输入框在失去焦点的时候,如果里面没有输入任何内容,每个输入框就会有相应的错误提示,用户体验很不错。这个其实是得益于我们在Status模型中声明的rules()
方法,Yii2会根据指定的规则通过js在前端给出相应的验证。
然后我们尝试填入一些内容,你就会看到输入框的变化了:
点击Submit
按钮,表单会提交到StatusController
的actionCreate()
方法,一旦有post
数据传过来,就会渲染view.php
视图:
到这里,其实我们就走通整个MVC的过程,并且在这个过程中,我们顺带说了一下Forms的知识点。
Layouts
为什么要说Layouts呢?因为Layouts在Yii中其实可以看作是视图中经常重复用到的部分,比如一个HTML文件的header
,navigation bar
和footer
等,这些都是几乎是在每一个视图文件中都会用到,所以Yii采取了一种一劳永逸的方法来管理这些共用的部分:Layouts就应运而生。这样你就不用在每一个view
文件中重复不必要的代码了,而且又特别好管理。
Yii允许你创建多个Layouts,不过我貌似还没遇到那样的使用场景,所以还是无法给出有实证的说法,不管怎么说,一个Layouts就基本够用了。
最后,我们借着Layouts的东风来看看我们怎么修改一下Yii2的默认导航栏:添加一个新的导航。
在上一节我就提到过views\layouts\main.php
这个文件,里面的具体结构你可以直打开来看看,我们这里改动的是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']],
],
]);
我们在本来的基础之上添加了下面这个内容:
[
'label' => 'Status',
'items' => [
['label' => 'Create', 'url' => ['/status/create']],
],
],
这样之后,刷新一下页面,你就可以看到我们的导航变化了。而且很神奇的是:这里还实现了dropdown menu
的功能,这个其实就是使用Bootstrap
的dropdown menu
来实现的。
嗯,这篇文章貌似讲得差不多了,至少我不知道还改讲些什么了,接下来的文章我会尝试讲讲Yii2的数据库相关的内容,先睡觉。
源码会放在 Github:https://github.com/JellyBool/helloYii
Yii2系列教程二:MVC,Forms和Layouts的更多相关文章
- CRL快速开发框架系列教程二(基于Lambda表达式查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- C#微信公众号开发系列教程二(新手接入指南)
http://www.cnblogs.com/zskbll/p/4093954.html 此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可 ...
- Android Studio系列教程二--基本设置与运行
Android Studio系列教程二--基本设置与运行 2014 年 11 月 28 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处! 上面一篇博客,介绍了Studio的 ...
- NGUI系列教程二
接下来我们创建一个Label,NGUI->Open the Widget Wizard,打开widgetTool对话框,在Template中选择Label,确定AddTo右侧选项为panel,点 ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级)
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级) 本章介绍的是企业库加密应用程序模块 ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级)
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (初级) 企业库加密应用程序模块提供了2种方 ...
- Fastify 系列教程二 (中间件、钩子函数和装饰器)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) 中间件 Fastify 提供了与 Express 和 Restify ...
- webpack4 系列教程(二): 编译 ES6
今天介绍webpack怎么编译ES6的各种函数和语法.敲黑板:这是webpack4版本哦, 有一些不同于webpack3的地方. >>> 本节课源码 >>> 所有课 ...
- Fastify 系列教程二 (中间件、钩子函数和装饰器)
Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...
随机推荐
- mac air 装ubuntu16.04
前言 我的mac air购于14年,128GB款.最开始我只是在OS X系统里留出了70GB给ubuntu,然后通过u盘装了ubuntu 14.04,后来又陆续将系统升级到15.04.16.04.各方 ...
- (七)计算G711语音的打包长度和RTP里timestamp的增长量
如何计算G711语音等的打包长度和RTP里timestamp的增长量 一般对于不同的语音有不同的打包周期,而不同的打包周期又对应着不同的timestamp in RTP 那么是如何计算的呢,我们通过G ...
- 汉字hash问题(转)
一.汉字编码的种类 汉字编码中现在主要用到的有三类,包括GBK,GB2312和Big5. 1.GB2312又称国标码,由国家标准总局发布,1981年5月1日实施,通行于大陆.新加坡等地也使用此编码.它 ...
- 查看Linux上的CPU核心数、线程数
grep "physical id" /proc/cpuinfo|sort -u grep "cpu cores" /proc/cpuinfo|uniq gre ...
- 存储过程 ----- navicat 创建存储过程
以下为navicat 创建存储过程步骤图解: 1. 2. 3. 4. 在存储过程正文中是输入一行语句测试用,点击保存 5.输入存储过程名称,点击确定 6.到这来那么问题来了,会提示错误 7.切记存储过 ...
- 【C++】多重继承
1. 多重继承时的二义性 当使用多重继承时,如果多个父类都定义了相同名字的变量,则会出现二义性.解决方法:使用 :: 声明作用域 #include <iostream> using nam ...
- Spring ClassPathXmlApplicationContext和FileSystemXmlApplicationContext读取配置文件的方法
先说:ClassPathXmlApplicationContext 这个类,默认获取的是WEB-INF/classes/下的路径,也就是在myeclipse的src下的路径,所以用这个是获取不到WEB ...
- AC日记——逃离僵尸岛 洛谷 P3393
逃离僵尸岛 思路: spfa: 代码: #include <cstdio> #include <cstring> #include <iostream> #incl ...
- 训练指南 UVA - 11354(最小生成树 + 倍增LCA)
layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...
- 网页截图工具CutyCapt
网页截图工具CutyCapt CuteCapt是Kali Linux提供的一款网页截图工具.该工具运行在命令行中,可以将WebKit引擎解析的网页保存为图片.它保存的文件支持矢量图和位图两大类型, ...