Currently rendering PHP files is an exception with respect to other files in the View
class:
if (isset($this->renderers[$ext])) {
if (is_array($this->renderers[$ext]) || is_string($this->renderers[$ext])) {
$this->renderers[$ext] = Yii::createObject($this->renderers[$ext]);
}
/* @var $renderer ViewRenderer */
$renderer = $this->renderers[$ext];
$output = $renderer->render($this, $viewFile, $params);
} else {
$output = $this->renderPhpFile($viewFile, $params);
}
PhpRenderer
and having a default renderer in the View
class.Currently rendering of PHP files happens inside the object context, this means that the View
object itself is available via $this
. This makes several tools unhappy, since you're calling $this
outside of an objects' context, as far as they can tell.
Since you need to use something like assertions or PHPDoc to type hint the parameters anyway, I feel there could be better ways to make the View
object available, for example by naming it $view
instead of $this
.
$renderer = function() use ($file, $params) {
extract($params, EXTR_OVERWRITE);
require $file;
};
$_obInitialLevel_ = ob_get_level();
ob_start();
ob_implicit_flush(false);
try {
$renderer->bindTo(null)()
return ob_get_clean();
} catch (\Throwable $e) {
while (ob_get_level() > $_obInitialLevel_) {
if (!@ob_end_clean()) {
ob_clean();
}
}
throw $e;
}
Output buffering is used by the framework to render views widgets among others. Currently PHP file rendering properly checks for output buffer states in error handling, but not in happy flows.
Sounds great. Would you like to help with it?
Would it change current behavior of View for end user?
Sounds great. Would you like to help with it?
Of course, if I make a proposal you may assume I'm willing to implement / help with it :-D
Would it change current behavior of View for end user?
Number 2 would, since the view is accessible via $view
instead of $this
(or whatever name we choose).
Note that these are 3 small proposals so we can do 1 and 3 but not 2 if you prefer.
Number 3 could create errors for users that do not properly use output buffering. But in those cases they are now probably rendering half their view content outside the layout... So we're helping them not hurting them by showing the error of their ways.
1 and 3 are fine. 2 sounds very logical and, I think, it's possible to still use $this
via bindTo or something like that.
It definitely is, but then might as well skip it. The whole reason for using the approach is to not have a $this
inside the view file.
If we want to have $this
the current approach is just fine.
Why not having $this
is a good idea? How would you access $title, $metaTags, beginBody(), registerCsrfMetaTags() etc.?
Via $view
. There are several arguments for this, but none are very strong.
$this
used outside an object.$view
does.I realize these are not not particularly strong arguments for changing a known convention, but I thought I'd throw it out there.
$this
is a reserved keyword and the way we're including it causes it to be available. Technically one could argue that this violates PSR-1. PSR-1 requires that each class must be in a file by itself.
But our views are included in our class and they use $this
, so the View
class is not in a file by itself...
That makes sense actually, but:
$this
is a convention we have for a long time and it works.$view
is very general as a variable in a template and could stand for database view, boolean flag, action etc. Could be confusing if we'll reserve that name.Fair enough, so we do not do 2, just and 1 and 3?
Yes.
This issue was moved by samdark to yiisoft/yii-web#4.
Most helpful comment
That makes sense actually, but:
$this
is a convention we have for a long time and it works.$view
is very general as a variable in a template and could stand for database view, boolean flag, action etc. Could be confusing if we'll reserve that name.