手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜Qcloud , 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP Framework

YII中的CComponent,CEvent与Behavior及CActiveRecordBehavior

上一篇文章我介绍的是官方的event和behavior的文章,这一篇是来自个人博客。
嗯,本来只是放在read it later做备份的,不料今天打开的时候发现,这篇文章已经不见了。该博客重新创建,原来的数据都没有了。所幸,我曾用read it later处理过纯文本模式,因此,我将它备份下来,以防哪天read it later也崩了。
ok,上原文链接。靠,原文打不开了,还是上这家网站的地址吧。。。http://www.trailroom.com/
内容其实这样的:

YII中的CComponent,CEvent与Behavior及CActiveRecordBehavior个人理解
这一块教程少,今天个人理解了下,写了个小例子,有助于理解

完成如下功能,一个JTool类,继承CComponent,当其长度改变时,调用事件,输出”change me”.
JTool.php在protected/components 下:

PHP代码
  1. <?php  
  2. class JTool extends CComponent{  
  3. private $_width;  
  4. public function getWidth(){  
  5. return $this->_width ? $this->_width : 1;  
  6. }  
  7.   
  8. public function setWidth($width){  
  9. if($this->hasEventHandler(‘onChange’)){  
  10. $this->onChange(new CEvent());  
  11. }  
  12. $this->_width = $width;  
  13. }  
  14.   
  15. public function onChange($event){  
  16. $this->raiseEvent(‘onChange’, $event);  
  17. }  

 

OK,功能已经实现了,找个控制器,执行

现在我们想给JTool添加一个功能,返回长度的100倍,我们可以继承JTool.php写一个方法

[。。。TEXT后,这一段内容消失了]
OK,功能实现了,这个执行就简单了new JToolSub调用方法即可

上边的这两种办法,就是仅完成功能,下边演示Behavior及events来实现

如何用Behavior来实现上边的增加一个方法,返回长度的100倍的功能呢?
写类JBe
JBe.php在protected/behavior 下:

PHP代码
  1. class JBe extends CBehavior{  
  2.   
  3. public function get100width(){  
  4. return $this->Owner->width*100;  
  5. }  
  6. }  

OK,功能已经实现了,找个控制器,执行

如何用Behavior实现JTool中的长度改变时,调用一个事件的功能呢?
写类JBe:

PHP代码
  1. class JBe extends CBehavior{  
  2. public function events(){  
  3. return array_merge(parent::events(),array(  
  4. ‘onChange’=>’change’,  
  5. ));  
  6. }  
  7.   
  8. public function change(){  
  9. echo ‘changed’;  
  10. }  
  11.   
  12. public function get100width(){  
  13. return $this->Owner->width*100;  
  14. }  
  15. }  

OK,功能实现随便找个控制器,执行

这里的要点是events方法
返回的数组array(‘onChange’=>’change’)定义了事件(event)和对应的事件处理方法(event hander)

事件是是Compents(JTool中)定义的,即JTool中的onChange
处理方法同由Behavior(JBe中)类定义的,即JBe中的change

这样子再看CActiveRecordBehavior,其是绑定给CActiveRecord 这个组件的,绑定方法重写behaviors()
CActiveRecordBehavior中的events() 方法返回事件及事处理函数的对应,如:
‘onBeforeSave’=>’beforeSave’

即组件CActiveRecord中的onBeforeSave这个事件对应的处理函数是
CActiveRecordBehavior中的beforeSave方法

这样子CActiveRecord在调用save()时,触发事件onBeforeSave,调用CActiveRecordBehavior对应的处理函数beforeSave
我们只要写一个CActiveRecordBehavior的子类,重写其中的beforeSave,执行一些操作,然后给CActiveRecord绑定即可

我还有个疑问,在继承CBehavior时,是不是一定要让方法events()反回那个对应关系的数组,如果这里为空,没有默认的对应关系?

---------

虽然TEXT保留了大部分内容,但还是有一小部分不见了。真可惜

 

 

 

Tags: yii, behavior, event, readitlater

Yii 官方关于event和behaviors的文章

本文内容来自官方的wiki,一来是做备份,二来自己查询起来也会快一点,毕竟yiiframework官网经常抽风,当然它的抽风不是因为自己,而是因为GFW,说来也可怜,好象很多技术网站都被墙了。
不过想想也正常,如果一个搞技术的,连翻墙也不会,还搞个毛技术啊。
OK,上正菜:http://www.yiiframework.com/wiki/44/behaviors-events/#hh1

These features provide endless possibilities and unbelievable flexibility, but as current documentation does not give more than a few examples, it might be difficult to fully understand their internals and requirements.

It should be noted that they do mostly the same thing. You can attach behaviors and event handlers to components to modify the components' behavior.

Events

It is useful when you want to interrupt the normal application flow without extending base classes.

For example, enabling gzip compression on the output could be done via extending CWebApplication. But because there are entry points for event handlers, one can do this:

PHP代码
  1. Yii::app()->onbeginRequest = create_function('$event''return ob_start("ob_gzhandler");'),  
  2. Yii::app()->onendRequest = create_function('$event''return ob_end_flush();'),  

You can create an event handler -- which is simply a method in some class with a specific signature -- and attach it to the event of an object. You can add as many event handlers as you wish, from as many objects as you wish. If the event handler is, effectively static, then you can create the object as you assign it:

PHP代码
  1. $test_comp->onSomethingGoesOn = array(new SomeClass, 'eventHandler1');  
  2. $test_comp->onSomethingGoesOn = array(new SomeOtherClass, 'eventHandler2');  
  3. $test_comp->onSomethingGoesOn = array(new YetAnotherClass, 'eventHandler3');  

As long as you have a handle on the object, then you can add an event handler to it.

At some point, you can then raise the event with something like one of these:

PHP代码
  1. $test_comp->onSomethingGoesOn(new CEvent($this));  
  2. $test_comp->onSomethingGoesOn(new CEvent());  

So, basically, it allows you to build a list of function calls that can later be executed, in the order they were added. It can save you passing around a lot of object refs and building conditional code, since you can still raise the event, even if it doesn't do anything.

Behaviors

Behaviors are simply a way of adding methods to an object.

Take this scenario: You have 2 classes: MySuperClass1, MySuperClass2. There might be lots of methods from MySuperClass1 & 2 that you want in some new class, say MyBoringClass. Unfortunately, php does not allow for this:

PHP代码
  1. class MyBoringClass extends MySuperClass1, MySuperClass2 {  
  2. }  

This is where behaviors come in. Instead, you can go:

PHP代码
  1. class MyBoringClass extends MySuperClass1 {  
  2. }  
  3.    
  4. $classInstance = new MyBoringClass();  
  5. $classInstance->attachbehavior('uniqueName'new MySuperClass2);  

Now $classInstance has all the methods from MySuperClass1 and MySuperClass2. Since MySuperClass2 is being used as a behavior, it has to extend CBehavior. The only caveat to this is an attached behavior cannot override any class methods of the component it is being attached to. If a method already exists, if it be from the original class or already added by a previously attached behavior, it will not be overwritten.

In an OO language like Ruby, it's quite possible to start with a completely empty object and simply build its behavior as you go along. Yii provides this behavior with a little magic. The key is that the class you wish to add the behavior from must extend Cbehavior.

PHP代码
  1. class SomeClass extends CBehavior  
  2. {  
  3.     public function add($x$y) { return $x + $y; }  
  4. }  

Then use with:

PHP代码
  1. $test_comp = new TestComponent();   
  2. $test_comp->attachbehavior('blah'new SomeClass);  
  3. $test_comp->add(2, 5);  

So, in this case, you are extending the functionality of an object with functionality of another object.

After studying this cookbook page you are encouraged to reread the corresponding guide page as it contains advanced information (for example, if you are familiar with interfaces, you might find it enough to implement IBehavior before extending CBehavior).

-------------

behavior和Event在model里用的会相对较多一点,不过,其他地方也可以一用。如果你真的不明白这一块的逻辑,那还是用其他方式替代吧。

 

 

 

 

 

 

 

 

Tags: yii, behavior, event

Yii的Euploadify插件使用

Yii在自已内部已经实现了单文件上传和多文件上传的代码,只是很少会有人注意这些吧?
事实上更多时候,在多文件上传的时候,我们往往采用了swfupload来进行处理,但swfupload的参数太多了,用起来会非常复杂和痛苦。
所幸,有很多人知道这些事情,他们对swfupload重新进行了封装,并做了简化,比如这个uploadify。
官网上的例子也很简单,一个是立即上传,一个是自定义上传。其实 最主要的是uploadify的是它的回调函数很少也很方便,常用的就是onError,onCompleted,onAllCompleted,onSuccess之类的。
在Yii的Extension库中,也确实有一款插件叫做EUploadifyWidget。最面对一些变量进行了更多的封装,也就是让我们使用起来更方便。不过,在使用过程中,还是会发现,虽然它封装了很多操作,但其实有很多地方还是没有处理好,官网上的例子也没有处理好。
打开代码可以发现在run函里面有对options等的处理,根据实际需要进行调整就OK了(之所以要调整,其实也还有一个原因,是因为我在这次的项目中没有用到clientScript,而这个插件却用了它,所以我才会多进行了一些处理)
默认的路径还是需要做一些处理,路径中的baseURL是基于它自己的路径来处理的,还有需要更改的就是JS/CSS/swf等的路径需要注意,其他就Over了。

纯笔记

Tags: yii, uploadify, swfupload

Yii CDbCriteria的常用方法

这是Yii CDbCriteria的一些笔记和常用用法:

PHP代码
  1. $criteria = new CDbCriteria;      
  2. $criteria->addCondition("id=1"); //查询条件,即where id = 1  
  3. $criteria->addInCondition('id'array(1,2,3,4,5)); //代表where id IN (1,23,,4,5,);  
  4. $criteria->addNotInCondition('id'array(1,2,3,4,5));//与上面正好相法,是NOT IN  
  5. $criteria->addCondition('id=1','OR');//这是OR条件,多个条件的时候,该条件是OR而非AND  
  6. $criteria->addSearchCondition('name''分类');//搜索条件,其实代表了。。where name like '%分类%'  
  7. $criteria->addBetweenCondition('id', 1, 4);//between 1 and 4   
  8.   
  9. $criteria->compare('id', 1);    //这个方法比较特殊,他会根据你的参数自动处理成addCondition或者addInCondition,  
  10.                                 //即如果第二个参数是数组就会调用addInCondition  
  11. /** 
  12.  * 传递变量 
  13.  */  
  14. $criteria->addCondition("id = :id");  
  15. $criteria->params[':id']=1;  
  16. /** 
  17.  * 一些public vars 
  18.  */  
  19. $criteria->select = 'id,parentid,name'//代表了要查询的字段,默认select='*';  
  20. $criteria->join = 'xxx'//连接表  
  21. $criteria->with = 'xxx'//调用relations   
  22. $criteria->limit = 10;    //取1条数据,如果小于0,则不作处理  
  23. $criteria->offset = 1;   //两条合并起来,则表示 limit 10 offset 1,或者代表了。limit 1,10  
  24. $criteria->order = 'xxx DESC,XXX ASC' ;//排序条件  
  25. $criteria->group = 'group 条件';  
  26. $criteria->having = 'having 条件 ';  
  27. $criteria->distinct = FALSE; //是否唯一查询   

有需要用到的可以查看一下。。。

Tags: yii, cdbcriteria

Yii笔记

本文纯粹是笔记,记下来怕忘了
1、终止当前操作,一般情况下是用exit,但用了Exit后无法看到trace的内容。所以要采用Yii::app()->end();
2、createUrl和createAbsoluteUrl,这两个函数,如果需要宣传自己的网址和内容,还是用createAbsoluteUrl函数吧。里面带了全部路径,而CreateUrl只会显示/home/xxx这样的路径,不利于SEO
3、widget默认的render无法使用theme中的模版,于是写一个类继承自CWidget,然后所有的widget都继承这个类,比如我这样实现了。。

PHP代码
  1. class Widget extends CWidget{  
  2.     private static $_viewPaths;  
  3.     /** 
  4.      * 重写CWidget中的getViewPath 
  5.      */  
  6.     public function getViewPath($checkTheme=false)  
  7.     {  
  8.         $className=get_class($this);  
  9.         if(isset(self::$_viewPaths[$className]))  
  10.             return self::$_viewPaths[$className];  
  11.         else  
  12.         {          
  13.             if($checkTheme && ($theme=Yii::app()->getTheme())!==null){  
  14.                 return self::$_viewPaths[$className] = $theme->getBasePath().DIRECTORY_SEPARATOR."widgets";  //这是我自己的路径
  15.             }  
  16.             $class=new ReflectionClass($className);  
  17.             return self::$_viewPaths[$className]=dirname($class->getFileName()).DIRECTORY_SEPARATOR.'views';              
  18.         }  
  19.     }  
  20. }  

覆写父类方法,使得getViewPath找到我指定的目录,我目录在themes/classic/下建了一个widgets的目录。这样的好处很多。。而且对于CSS和JS等路径都可以和标准视图一致

先写这么多。。。

Tags: yii