I’ve argued against the static helper classes before, and I know from building several large projects with Yii that attempting to extend or override functionality of the helpers is a pain. Static helpers, in my opinion, need to be eliminated - helpers need to be concrete classes so we can extend/override as needed.
So the question is where/how to configure the helpers.
I’m with the school of not introducing a bunch of new concepts - but rather use what Yii already provides. So adding your helpers as application components gets my vote - it’s the simplest approach, and it’s already supported and well-understood by anyone using Yii.
The question then is how to access the helpers most conveniently. We should benchmark the proposed solution by comparing to the existing solution.
What we have currently looks like this:
If the HTML helper was an application component, it would look like this:
Clearly, that’s ugly and cumbersome, and involves a lot of overhead in terms of resolving the clasname, static method, application component and then finally the encode() method, on every single invocation. So that’s not acceptable.
Someone pointed out that you could add the helpers to the controller, so then you’d have something like this:
That’s slightly better, but still looks cumbersome and messy compared to the static method-call.
In terms of performance, the shortest path to the html helper would be via a local variable:
This is better in terms of performance, as it’s just calling a method on an object - it’s also shorter and easier to type than any of the other options.
In my opinion, that would be the best approach.
And I’m aware of the issues with this approach - like the fact that the helpers are now occupying the same namespace as the view-data, so that view-data could collide with your helpers. I don’t see this as being a really big problem, and you can work around that, depending on how the helpers are introduced into the view-data.
The other problem is the fact that you would need to construct and initialize any required view-helper application components prior to rendering the view. Typically, that’s going to mean one or two components, which would be required by the majority of views anyway, so I don’t see that being a drastic issue either - and we’re only talking about constructing these components once during any request that renders a view, so it doesn’t seem like that’s going to cause any real performance impact.
As far as how to get the helpers into local variables in the view, I would suggest adding a CViewRenderer::$helpers property - which by default might contain something like array(‘htmlHelper’ => ‘html’), e.g. a map where application component id => view-data variable name.
Since this means that collisions between view-data and helpers could occur, I would suggest throwing an exception if controller/action code attempts to overwrite a helper with another value.
On a note of backwards compatibility - I would say, don’t worry too much about it. This being a major framework update, we should feel free to architect as needed, without worrying too much about backwards compatibility - we should favor comfort, speed and good practices of new applications and new developers, over migrations of legacy applications. What’s much more interesting is the new possibilities and improvements, paving the way for the future - building a new app should be less effort and more joy, and if that means that migrating a legacy app takes more effort, so be it. Just my personal opinion
If somebody does need to upgrade a project, this can be done quite easily by doing a replace-in-files on their view-folders, replacing "CHtml::" with "$html->".
That’s all I’ve got on this subject at the moment.