Component life cycles

In 1.x, several classes have a method named init() which is called after constructor and property initialization.

In 2.0, I am thinking to put this into the base Component class and by default init() will call behaviors() to register declared behaviors.

Accordingly, Yii::createComponent() will be modified to call init() after creating a new component.

What do you feel about this change?

Pros:

  • more unified than 1.x: every component will have init(), not just app components, models.

  • behavior registration is more standardized. In 1.x, some components may not attach behaviors unless you explicitly attach them.

Cons:

  • performance degradation: now every component instantiation will have an additional call to init(). This may not be a big issue, however.

  • every component will have a method named ‘init()’, which is probably too common and may conflict with the similar needs in child classes. Perhaps this is not a real issue either, though.

What’s currently done via component?

  1. getter/setter as property. That’s a good and a bad feature of the framework at the same time. Produces short good looking syntax but adds some confusion. Personally I like it but can live with explicit getters/setters.

  2. Events. If not requiring describing events explicitly, events support can be done in a separate class. We’ll be able to use it for anything, not only components.

  3. Behaviors. PHP 5.4 will support this feature natively (traits are actually implemented as state-aware) but we’re building Yii2 with 5.3 in mind. Feature is both good and bad again: gives a good amount of flexibility but also adds magic-like features. The only popular place where behaviors are currently used is models (am I wrong about models-only?).

So there are pros and cons. Should we use base component class at all?

Our general rule for Yii 2.0 is that we will not make significant changes to proven designs. Otherwise, we are throwing ourselves into unknown space. For this reason, we will keep most of the features in our current foundational classes, and we will have a base component class like in Yii 1.x.

  1. getter/setter: can’t think of what’s wrong with it. IMO, this should be natively supported by PHP.

  2. We have discussed about this. I think we should limit our scope for now, not trying to support everything unless we see real needs for that.

  3. As you can see behavior is another feature that should be supported at language level. Since Yii 2.0 will be based on 5.3 instead of 5.4, I think we should support it at the base component level. Personally, I never like behaviors as I prefer to explicit programming.

There’s no perfect code. Making a good compromise is the key.

Got your point. Generally I agree. There’s no harm using component as a base or at least I don’t see it. Now about actual questions asked…

Moving init() to Component looks like a good idea. Except http://www.yiiframework.com/doc/api/1.1/CGoogleApi/ everything that uses init currently extends CComponent. Cons aren’t looking critical to me.

Agreed

I have needed component initialization many times, and had to implement it myself.

I vote yes.

I propose passing in an Application object in the init. e.g.

function init($app)

{

$db = $app->getComponent($this->db);

}

wei

What’s the benefit? We can’t have two application instances at the same time.

To avoid Yii::app() calls in component classes. This is essentially a global variable.

OK, but what’s practical benefit, not theoretical one? We do have application instance in unit tests, we aren’t going to use Yii components outside of Yii itself.

But it isn’t a variable, it’s a static method that gives you the currently running Yii application.

We’re getting into another discussion, but I don’t like that either - anything static makes me cringe.

The only way around it though, is probably dependency injection - which is what you’re suggesting, but that would mean that every class that has a dependency on an application component would need to extend CComponent. That would probably result in a lot overhead, and it raises more questions - like, if we’re going to introduce dependency injection, why not introduce “real” dependency injection, that actually injects the application components you need, rather than injecting the dependency registry itself? (which is essentially what a Yii application object is)