视图文件:
create.php:
<?php
/* @var $this TagController */
/* @var $model Tag */
$this->breadcrumbs=array(
'Tags'=>array('index'),
'Create',
);
$this->menu=array(
array('label'=>'List Tag', 'url'=>array('index')),
array('label'=>'Manage Tag', 'url'=>array('admin')),
);
?>
<h1>Create Tag</h1>
<?php echo $this->renderPartial('_form', array('model'=>$model)); ?>
_form.php
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'tag-form',
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'name'); ?>
<?php echo $form->textField($model,'name',array('size'=>60,'maxlength'=>128)); ?>
<?php echo $form->error($model,'name'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->textField($model,'password',array('size'=>60,'maxlength'=>128)); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'frequency'); ?>
<?php echo $form->textField($model,'frequency',array('size'=>32,'maxlength'=>32)); ?>
<?php echo $form->error($model,'frequency'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div>
控制器文件:
class TagController extends Controller
{
……
public function actionCreate()
{
$model=new Tag;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Tag']))
{
$model->attributes=$_POST['Tag'];
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
……
模型文件:Tga.php
class Tag extends CActiveRecord
{
……
}
关于YII生成表单
Yii 中的表单生成,有几种方法,
一种是普通生成,用些辅助器(helper)类CHtml类,
<?php echo CHtml::textField(string $name, string $value='', array $htmlOptions=array ( ))?>
这种方法是没有模型的,它的值是要自己判断有无,通过第二个参数$value来预定义,第三个参数是属性。详情看framework/web/helpers/CHtml.php
另一种是生成更动态的表单方法,这个就需要有CModel 类型的$model
如:CHtml::activeLabel()
<?php echo CHtml::beginForm(); ?>
<?php echo $form->errorSummary($model); ?> //这显示全部错误信息
<li>
<?php echo CHtml::activeLabel($model,'username'); ?>
<?php echo CHtml::activeTextField($model,'username') ?>
</li>
<li>
<?php echo CHtml::activeLabel($model,'password'); ?>
<?php echo CHtml::activePasswordField($model,'password') ?>
</li>
<li>
<?php echo CHtml::submitButton('Login'); ?>
</li>
<?php echo CHtml::endForm(); ?>
还有一种YII提供的自版本 1.1.1 开始, 一个新的 widget 称为 CActiveForm 被提供用来简化表单创建. 此 widget 能够无缝和坚固
(consistent)的支持客户端和服务器端的验证.如可以用ajax异步验证。
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'theForm',
'action'=>$this->createUrl("profile/index"),
'enableAjaxValidation'=>true,//开启异步验证
'clientOptions'=>array(
'validateOnSubmit'=>true,
),
));?>
<div>
<?php echo $form->label($model,'username'); ?>
<?php echo $form->textField($model,'username') ?>
<?php echo $form->error($model, "realname"); ?> </div> //显示单个错误信息
<div class="row">
<?php echo $form->label($model,'password'); ?>
<?php echo $form->passwordField($model,'password') ?>
</div>
<div class="row rememberMe">
<?php echo $form->checkBox($model,'rememberMe'); ?>
<?php echo $form->label($model,'rememberMe'); ?>
</div>
<div class="row submit">
<?php echo CHtml::submitButton('Login'); ?>
</div>
<?php $this->endWidget(); ?>
关于$model
$model 必须是继承自CActiveRecord或是CFormModel的,它们都是继承自 CModel » CComponent,
其中前都扩展的多,后都几乎没什么扩展。
所以,在一个只有一种表单的模型中,就直接在model中设定验证规则,在此类中,不用设定每种字段属性,CActiveRecord自动从数据表中获取了。
一个数据表有多个表单,可以用CFormModel来设定不同表单有验证规则roule(),在此类中,要自己设定表单属性。
1.myController是自己定义的一个控制器,login.php是在myController中login这个action指向执行的view.
2. 虚线表示一个是另一个类的子类.所以myController含有BaseController的那几个方法。所以在login.php中可以使用baseController中的方法。
3. baseController中beginWidget和widget方法都会调用createWidget(),并且在createWidget中使用init方法得到预处理的widget,而后widget和endWidget执行widget对象的run()。
<?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'login-form', 'enableClientValidation'=>true, 'clientOptions'=>array( 'validateOnSubmit'=>true, ), )); ?> <?php echo $form->textField($model,'username'); ?> <?php echo $form->passwordField($model,'password'); ?> <div class="row buttons"> <?php echo CHtml::submitButton('Login'); ?> </div> <?php $this->endWidget(); ?>
以上面代码为例子,beginWidget里的array("id"=>"login-form")等参数实际上是类CActiveForm的属性。查看生成的源码:
<form id="login-form" action="/site/login" method="post">
即当前指定了id,method,那么查看CActiveForm还有action属性,增加该属性如:
<?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'login-form', 'action'=>"helloworld", 'enableClientValidation'=>true, 'clientOptions'=>array( 'validateOnSubmit'=>true, ), )); ?>
查看源码:
<form id="login-form" action="helloworld" method="post">
以上测试证明了beginWidget就是这样实例化出这个form的widget,但是,如何已控制器进行交互了?
控制器处理:
public function actionLogin() { $model=new LoginForm; // collect user input data if(isset($_POST['LoginForm'])) { $model->attributes=$_POST['LoginForm']; // validate user input and redirect to the previous page if valid if($model->validate() && $model->login()) $this->redirect(Yii::app()->user->returnUrl); } // display the login form $this->render('login',array('model'=>$model)); }
这段代码很让人迷惑,主要是$_POST['LoginForm']那里来的?一般PHP的post请求无外乎$_POST["username"], $_POST["password"],因为$_POST这个属性无外乎就是个array,所以,可以说在yii中,通过使用yii自己的form表单,会对一些name进行处理,然后对$_POST中的值进行修改!
验证一,原始html
<input name="LoginForm[username]" id="LoginForm_username" type="text" />
生成的表单中是这样的代码。当然主要是CHtml完成的。
public
static
function resolveNameID($model,&$attribute,&$htmlOptions)
{
if
(!isset($htmlOptions[
'name'
]))
$htmlOptions[
'name'
]=self::resolveName($model,$attribute);
if
(!isset($htmlOptions[
'id'
]))
$htmlOptions[
'id'
]=self::getIdByName($htmlOptions[
'name'
]);
else
if
($htmlOptions[
'id'
]===
false
)
unset($htmlOptions[
'id'
]);
}
|
我们的<?php echo $form->textField($model,'username'); ?>这行代码中的textField($model,$attribute,$htmlOptions=array())方法是可以指定$htmlOptions的,即可以指定name属性,但是这里没有指定,所以都各自调用了前面的2个方法
resolveName:
public static function resolveName($model,&$attribute) { if(($pos=strpos($attribute,'['))!==false) { if($pos!==0) // e.g. name[a][b] return get_class($model).'['.substr($attribute,0,$pos).']'.substr($attribute,$pos); if(($pos=strrpos($attribute,']'))!==false && $pos!==strlen($attribute)-1) // e.g. [a][b]name { $sub=substr($attribute,0,$pos+1); $attribute=substr($attribute,$pos+1); return get_class($model).$sub.'['.$attribute.']'; } if(preg_match('/\](\w+\[.*)$/',$attribute,$matches)) { $name=get_class($model).'['.str_replace(']','][',trim(strtr($attribute,array(']['=>']','['=>']')),']')).']'; $attribute=$matches[1]; return $name; } } return get_class($model).'['.$attribute.']'; }
get_class这里是返回的对象的类名,是哪个类呢?
public function actionLogin() { $model=new LoginForm;
是最早我们实例化的这个类。
所以说,要使用yii的类最好得有一个自己的form类。