Extend Extensions

I want to be able to extend extensions and override any method within any extension. That way I can customize extensions without having to modify the actual code and worry about applying my patches directly to an extension in the future when the extension is updated.

The proper way of doing it is contacting extension author and either providing code for extension or asking for it to be extendable. There is no way framework can deal with it.

Right, in Yii 1.1 there is no way to do it. That’s why this is a feature request for Yii 2.0 :). Symfony allows for extending bundles to be overridden in the way I described. I’m sure it could be implemented in Yii 2.0 with some redesign, right?

On the first thought it looks like a good idea, but when you take your time and try imagining the use cases and the abuse people tend to achieve via extending classes - it get’s messy.

Just picture this:

A person makes an extension - fairly simple, not much functionality, but it works and has it’s major use cases covered.

Time goes by and someone has a need to extend it. No problem, extend the damn thing and add desired functionality. Fairly simple.

Some time goes by and other person has a big chunk of functionality written over the second extended version and changes some inner working by overriding methods a little because the base does not handle the increased complexity. The thing gets heavy and now is 3 layers deep (not counting inner layers of extending there may be).

Eventually some one will extend it even further, but I would like to believe that there will be no such foolish enough person to do that (still the believer to the end, yes).

So in the end we end up with multiple versions of stuff that is layered on each other. One day the original author just rewrites the damn thing and all other have to do it all over again. That’s why I think it’s a bad idea in general.

On the bright note, if there is an official repository with solid stable extensions, that guarantee that they do not change their API at least until framework changes it’s minor versions (2.0, 2.1, …, 2.n) - it will give people a solid platform. But this should be closely monitored and extensions should go in only after some extended period of existence and development to make them stable.

I agree with Psih. This is a bad idea unless the extensions are as well maintained as the core. Also I don’t get how Yii should help when extending 3rd party code. If the extension is well designed you can extend it anyway. (Although you shouldn’t: the scenario painted by Psih is just one of the many disadvantages.)

What I do is modify any extensions that I use which doesn’t meet my requirements…

That is of course not recommended: if I can merge my modifications upstream, it would be better. But it’s not always desirable.

Why not just make the on site extension repo use git as a backend? That way it’s easy to fork the repo to make your changes, and if an extension doesn’t meet your requirements, you can change it and pull request upstream. If extensions are abandoned by their author and they stop accepting pull requests, a voting system could be introduced to replace the main extension repo with one of the forks.

+1

Github integration is a good idea. There are some extensions on yiiframework that have valueable forks or quasi-patches that are hidden in comments, in forums, or in github repos, and mostly you find them only by chance. Forcing development on github would not only make it more easily extendable, there is also the possibility that more people get into developing and forking.

Agree. The extensions page is horrible, sorry guys ;)

I stopped providing downloadable files for my extensions because it was a hassle to keep all the files and repos in sync, so I always provide a Github link. Makes life easier for both sides. I think this should be the general approach. Not uploading files but providing repo links enabling people to use bug tracking tools etc.

Actually I’m doing it as well. Just leaving a link to github. Probably we should use the same generation approach as http://yiiext.github.com/.

Hi,

what about making widget extension more as behavior instead of class inheritance?

For example if where are 3 gridview extensions: AGridView, BGridView and EGridView and I want functionality of all in one grid?

I need edit extension’s code somehow like this:




class BGridView extends AGridview {...}

class EGridView extends BGridview {..}

It would be more efficient to attach/deattach extension as behavior. but i do not see such approach for widgets.

Suggestion:

To make classes easily extendable, the public methods should not be implemented as real methods, but all require to go through ‘_call’. In some cases, this may not be preferable for performance reasons, but that may just be exceptions.

So a public (library) method should be for instance



[php]


public function _run() {


   blabla();


}


Then, when calling ‘run’, the ‘__call’ method would be checked to lookup the actual method because it is missing initially. At that time the ‘__call’ method could look it up in the behaviors and also call ‘_run()’.

Maybe it could be allowed for behaviors a flag should be set for the duration of ‘__call’ to indicate that the original ‘_run’ method should or should not be run after all the behaviors have been called (because one of the behaviors could replace or run the original method following the naming rule’).

May I suggest that you (Yii Team) rewrite the extensions ‘module’ to make use of Bitbucket or Github (preferably both).

Github and Bitbucket has APIs and it could help provide the following:

  1. Download link for latest tagged release.

  2. Download link for default/master (development version)

  3. Changelog maybe?

  4. Link to issue tracker

  5. Link to repository

  6. Perhaps show the 5 latest entries in the tracker?

Using the Bitbucket/Github APIs, the connection would be transparent.

And, importantly: fully automated. :)

IMO, both Bitbucket and Github should be supported - fairly easy to do.

@jacmoe: suppose you was going to post into another topic)

concerning widgets we can talk about widget behaviors that can be easily attached on the fly when creating widget:




$this->widget('CGridView', array(

    'dataProvider'=>$model->search(),

    'selectableRows'=>2,  

    'behaviors' => array(

         'SelGridView' => array(

             'class' => 'ext.selgridview.SelBehavior'

          ),

         'GroupGridView' => array(

             'class' => 'ext.groupgridview.GroupBehavior'

          ),

     ),

Behaviors are good, but the issue with ‘behaviors’ is that they can only ‘extend’ those methods / events that are already added ‘by design’ in the ‘component’.

So a method to be able to extend almost any method is more flexible.

Vitalets

I think GridView isn’t a good example here. Most of the things we need to customize in a grid are columns, formatting and filters. And these are already customizable via supplying own column classes or custom views.