Yii是重量级框架,类似于同ruby on rails,django是同一类型的框架,所以其有的特点在其他框架上都存在,但吸引我研究它的是官方文档凭什么说"Yii 是一个基于组件的高性能 PHP 框架,用于快速开发大型 Web 应用”。以后我也将继续用实践证明他这句话的对错。要知道,django的文档介绍里说的"使用Django,花极少时间即可构建和维护质量上乘的Web应用。"就是说django只适合快速原型,并且原型出来的东西不错,或者说用来做内部管理系统什么的很适合,但外部大型应用不好,而yii说自己是高性能的框架,快速,大型等关键字,很唬人。
说明:
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类。