View and helper

Hm, I get results between -4% and 6%, although most runs end somewhere in between 2% and 4% (PHP 5.3.4 on WAMP 2.1).

Thanks for sharing mindplay. Done your benchmark in my computer and these are the results and is very clear:

1st

Static method-calls: 75.758 msec

Instance method-calls: 59.550 msec

Static method-call overhead: 27%


2nd

Static method-calls: 70.767 msec

Instance method-calls: 67.440 msec

Static method-call overhead: 5%


3rd

Static method-calls: 69.590 msec

Instance method-calls: 63.538 msec

Static method-call overhead: 10%

Benchmark running on MacOsx Lion, apache, PHP 5.3+

There are many variables, I’m sure - hardware, operating system and perhaps certain installed modules/extensions, such as a bytecode cache, could affect the results.

I would conclude that performance is probably comparable, or perhaps slightly better, for instance-methods on most systems.

I can see only one benefit of that: Controllers would become much easier to test if action methods returned a view object (instead of outputting anything directly). The actual rendering should be done somewhere in CWebApplication.

But if you just want to factor out template rendering from controllers - which is a good idea anyway - then a simple behavior that can be attached to controllers could do the job. Even the old familiar syntax ($this->render(), etc.) can be kept in this way.

That approach has both advantages and weak points.

Suppose for example you need to render more than one view for some reason - how would you return multiple view-objects, and how would you make sure they execute in order? Even if you could manage that, suppose the result of one view needs to be inserted into another, how would you achieve that?

The decision to let the framework take over a responsibility like this, always results in more complexity than you were probably expecting.

I think the approach more commonly taken by Yii, is to provide tools, but let you drive the tools - you push, Yii moves. Frameworks that pull rather than push end up having to make decisions, and you end up one step removed from the decision-making process. So you’re trying to influence the decisions made by the framework, by providing a different response when it pulls, which is a much more difficult process to understand (and less transparent, and usually slower) than just pushing in the direction you want to go.

Explicitly rendering a view, the way Yii does now, does not prevent testing, by the way - two colleagues in my office recently created a "view renderer" which they plug in during unit testing, which passes the view-data back to the unit test before rendering the view.

Note that this is not necessarily an argument against having a view-object of some sort - there may well be other good reasons to abstract a view in the form of an object…

It is good to be with helpers but of course as a statuc function in a Class not like CodeIgniter’s helpers.

But i be not think we create view obj to render a view. If it will be created what will be benefits of it? Now there is a big benefit that in view file you can access to the controller (by $this) not like Zend framework’s view file. Hovewer Zend framework crates a view object to show view file and it is a bit complicated. It is my opinion

I like the approach used in ASP.NET MVC - every controller returns a "result", and there are different result-types, a view-result just happens to be one of them; other examples are JSON-result, file-result (for downloads) etc.

There are just a few helpers, it’s easy to “use” them in a view renderer.

This is the major drawback. Same as abnormal quantity of private variables all over the framework.

You can replace privates with protected and use static instead of self everywhere to assist in this task.

Yes.

Controllers are really the view controllers, as we don’t have event controllers in web, but the template engine should be separated from controllers.

Last project changed my mind - I think that a separate view is required.

What are the goals for changes in general? I did not find it in the texts.

View Object could be a standaonle one, Not attaching to controller only. This object can be use in other place not limited in the controller this way: Yii::app()->controller->render() … to Yii::app()->view ?

I like the way how Gustavo have outlined the helper magic methods.

But I’m against having the helpers (or its methods) in the view class as several people suggested. Helpers are also used outside the views.

Not using the helper class directly could bring a good side effect: more extensibility.

The developer will be able to just drop a new helper seamlessly. The helpers will have the same flexibility that components have today.

I vote for a View object. Why?

1.) Doing translation without setting Yii::t() everywhere:

We could do something like this:




namespace Yii;

$obj = new View;

$obj->translationPath = 'app.messages'; // default

$obj->translationScope = 'application'; // default

$obj->language = 'de'; // default would be Yii::app()->language;


return $obj->retrieve('view'); // would return the output of view 'view';


$obj->render('view'); // would render view

Now, in the view file, wo would not use Yii:t() at all:


<p> Please translate me to german </p>

And, in the translation file app.messages.application.de we have a "intelligent"

string detector that translates all found strings in the view file:


'Please translate me to german' => 'Bitte übersetze mich in Deutsch'

Of course, other Message Source like CDbMessageSource, … can be attached to the

view object, with the CPhpMessageSource as the default. The translated view then

will be cached - maybe even as a physical .php file with translated strings.

2.) Caching:

We could do something like this:




namespace Yii;


$dep = new CCacheDependency('select max(*) from users');

$obj = new View;

$obj->cache(500, $dep)->render('view');



to let yii automatically cache our view files

3.) Helpers and used templating language:

I do not vote for a "default yii templating language". It

should stay the way it is, and templating languages should

be attachable. But a minimal asset of shortcuts, without

injecting <?php ?> tags would really be helpful. Examples:

Instead of:




<row class="wide">

<?php echo CHtml::activeLabel($model, 'value'); ?>;

<?php echo CHtml::textArea($model, 'value'); ?>;

<?php echo CHtml::error($model, 'value'); ?>;

</row>



We could do (syntax needs to be discussed/voted for):


<% row model="model" value="value" divOptions="wide" type="textArea" %>

Same goes for links. How about


<% link route="//site/index" title="Click me" label="Home" %>

The view object would translate these snippets into the appropriate

<?php ?>, and of course caches these by default.

4.) Layout Handling:




namespace Yii;

$obj = new View;


$obj->layoutPath = 'views.layouts'; // default

$obj->layout = 'column2':


$obj->render('view'); // apply layout to view and render, like in Yii1


$obj->attachLayout = false;


$obj->render('view'); // do _not_ attach Layout, like renderPartial();




5.) rendering Text

instead of


$this->renderText($text);

we could do do a static function:




View::retrieveText($text);

View::renderText($text);



6.) Output processing (javascript)




namespace Yii;

$obj = new View;


$obj->outputProcessing = false; // default would be true

$obj->render('view'); // do not process output here




7.) Intelligent Ajax response

We could make the view object force to not apply the layout

when the request is a ajax request. Of course this can be

overridden by the developer if he wants it for whatever

reason?

I agree with the "__callStatic" way

Here’s a related thought that has occurred to me a lot lately.

Why don’t views compile down to classes?

Before PHP had namespaces, the answer to this was simple: what are you going to name them? They would need to have some ugly machine-generated name, e.g. "views/users/profile.php" might compile into a class named "view_users_profile", which is yucky.

With namespaces available now, it would actually make more sense to compile views down to classes - so when you compile "MyApp/Views/Users/Profile.php", it actually compiles into a class with a (configurable) namespace, e.g. "MyApp\Views\Users\Profile".

This way, when you’re looking at a module’s folder structure, the folder-names really correspond to namespaces, and filenames really correspond to class-names.

The generated class can extend whatever view-engine it happens to be using, so you might end up with a compiled view like "MyApp\Views\Users\Profile extends \VendorABC\EngineX\View" which implements a render() method.

This opens up more new possibilities - for example, we can now allow multiple view engines in the same application, since view-engines only need to load/compile once, and whatever base-class they need will automatically be autoloaded as needed. After the first request, once the compiled templates are in place, you don’t even need to run code that checks which view-engines are installed, they just autoload as needed.

Another thing that PHP developers are generally fearful of, is repeated rendering of the same view - with the traditional template engine approach (where a view compiles into a flat PHP script), rendering the same view 10 times is expensive, because you have to require/include the same flat script repeatedly.

If a view compiled into a class, you can load once and render repeatedly at no extra cost - because it’s just a method-call on a class. Which is really all your HTML helpers are - they’re mini templates that you can’t practically implement as views, mainly because they would be too slow.

I benchmarked this a while back, and found that anything that renders more than once, renders faster when wrapped in a class and method-call, rather than multiple calls to include/require. Even with a bytecode cache.

I know this is a big detour from what you’re used to, but give it some thought :slight_smile:

It’s supported in current Yii.

So your idea is to compile same flat files to classes and then running these?

Hello, i think creating view object is a very good idea.

binkabir

Why?

i think the view object should have all the helper methods (which will not be static functions)

example




  $output = new CView('path/to/view/file',array('myVar'=>$var)); 




because has all the helper method are in the CView object i should be able to do this

inside be view_file




$this->encode($myVar);


$this->ajax('ajaxName','url',array('options'));






one can also be able to do this




//this should encode all the data/variables passed to the view object

$output->encode();




this is my little concept ;)

That’s one of the bits I really didn’t like about CakePHP - please don’t duplicate that into Yii.

I really dig the simplicity of the fact that the controller is available in the view. :)

And why create yet another object?

The main doubt for me is, why would i have a view object?

Paths? I love the automated discovery on controllers, and the good thing is that if i need another one placed on different place i just pass the path and voilá…

Caching? are you sure the actual caching features do not accomplish nearly to perfection its mission?

Translation? i18n is perfect the way it is, can be improved of course, but automated tag discovery is error prone and will obviously reduce the speed of the library

Template commands? Wait a minute… templates inside HTML, just like other rendering engines out-there? I do not agree, if anybody wishes to use smarty or an engine, there are ways to do it. IMHO I opt to stick with pure HTML, is easier to work with designers. They can handle PHP tags, but template commands? forget it. Also, I think is a new step to interpret and reduce response time if not used well.

Those reasons above do not convince me to create a view object… there is one thing I have always problems with, and it is the way rendering takes place with javascript files, their order, the renderPartial process output approach that renders duplicated files again and again via AJAX, but is that part of the View object? I think not, is because our CClientScript component I believe.

So why do I need a view object? should we remove all the view rendering features from controller and create a separated object? maybe it is good for methods encapsulation, maybe in the future is better to improve it without affecting controllers code, but i do not find other good reason why do we need a view object.