Download the PHP package rotexsoft/file-renderer without Composer
On this page you can find all versions of the php package rotexsoft/file-renderer. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download rotexsoft/file-renderer
More information about rotexsoft/file-renderer
Files in rotexsoft/file-renderer
Package file-renderer
Short Description A tool for rendering PHP files that are meant to generate output. Easy to use as a view component in an MVC framework.
License BSD-3-Clause
Homepage https://github.com/rotexsoft/file-renderer
Informations about the package file-renderer
PHP File Renderer
- PHP File Renderer
- Introduction
- Main Features
- Acknowledgement
- Changelog
- Contribution
- Running Tests
- Requirements
- Installation
- Usage
- Basic Usage
- Getting, Setting and Unsetting View Data
- Setting View Data
- Getting View Data
- Unsetting View Data
- File paths
- Escaping Data to be Passed to Views
- Using Wild Cards in Escape Specification
- Advanced Usage
- Implementing a Two-Step View Templating System
- Sharing Data between Layout and Page Content Views
- Nesting Renderers
- Implementing a Two-Step View Templating System
- Introduction
Introduction
This is a simple, elegant and flexible tool that can be used to render php files (also referred to as Views
within this documentation)
that emit valid html output to a web-browser. It is designed to be unobtrusive; your view files can easily be used with a different
rendering or templating library. You do not need to learn any new syntax (or markup / templating language) in order to compose your
views; simply write your views in plain old php. This package also provides escaping functionality for data passed to the view file(s).
This package can easily be used by framework developers to implement the View layer of an MVC (Model-View-Controller) framework. It can also be easily incorporated into existing frameworks.
100% Unit Test Coverage.
Users of this package are still responsible for making sure that they validate or sanitize data coming into their application(s) via user input (eg. via html forms) with tools like Respect\Validation, Valitron, Upload, Volan, Sirius Validation, Filterus, etc.
Main Features
- No new templating language or syntax to learn, just good old PHP is required to compose view files to be rendered.
- View file(s) in existing projects can easily be adapted for rendering via this package with very little effort.
- This package can be easily used to implement a Two-Step-View system where all your site's pages share a common layout file and the content for each page gets injected into the layout file.
- Data (variables) can be injected into the files to be rendered via an associative array whose keys will be converted to variables when rendering occurs.
- Escaping is performed on the values in the data array based on specified escape rules.
- Auto-Escaping is possible on a per instance basis of the Renderer class (escaping rules must be specified when instantiating a Renderer object for this feature to work).
Acknowledgement
The escaping functionality in this package is implemented using the laminas-escaper package.
Changelog
Here.
Contribution
Since the goal of this package is to be lean and flexible, pull requests for significant new features will not be accepted. Users are encouraged to extend the package with new feature(s) in their own projects. However, bug fix and documentation enhancement related pull requests are greatly welcomed.
Running Tests
./vendor/bin/phpunit --coverage-text
Branching
These are the branches in this repository:
- master: contains code for the latest major version of this package
- 1.X: contains code for the 1.x version of this package
- 2.X: contains code for the 2.x version of this package
- 5.x: contains code for the 5.x version of this package
- 6.x: contains code for the 6.x version of this package
Requirements
- PHP 8.1+
- Not currently certified for use with HHVM (unit tests failing when run in an HHVM environment).
Installation
composer require rotexsoft/file-renderer
Usage
Basic Usage
Your main php script may look like below (let's call it test.php
and assume it's located at the root directory of your project's folder):
/some/path/my-project/test.php
/some/path/my-project/views/view.php
NOTE: the file name, if any, supplied to the render() methods will be considered first for rendering if the file exists. The file name supplied to the constructor during object creation will be considered last for rendering if the file name supplied to the render() method can't be found.
NOTE: you can access the Renderer object inside your view via the $this
variable.
There are five escape methods you can use within your view:
$this->escapeHtml(string $some_string_variable):
an alias for PHP's htmlspecialchars() for escaping data which may contain html markup.$this->escapeHtmlAttr(string $some_string_variable):
for escaping data which is meant to be rendered as an attribute value within an html element in a view.$this->escapeCss(string $some_string_variable):
for escaping data which is meant to be rendered within<style>
tags or inside the style attribute of any html element.$this->escapeJs(string $some_string_variable):
for escaping data which is meant to be rendered as string literals or digits within Javascript code in a view.$this->escapeUrl(string $some_string_variable):
an alias for PHP's rawurlencode() for escaping data being inserted into a URL and not to the whole URL itself.
See the Escaping Data to be Passed to Views section for more info about escaping.
Getting, Setting and Unsetting View Data
Setting View Data
View data can be supplied when the Renderer object is created / instantiated
View data can also be set or updated after the Renderer object has been created / instantiated
Getting View Data
View data values can be accessed after the Renderer object is created / instantiated
Unsetting View Data
View data values can be deleted after the Renderer object is created / instantiated
File paths
These are paths that will be searched for the file to be rendered via the *render()** methods.
If a path is prepended to the name of the file to be rendered (which can be supplied either during the creation of the renderer object or during a call to any of the *render()** methods) and the file with the prepnded path exists, that file will be rendered and the renderer will not bother searching the file paths supplied during construction or via call(s) to appendPath($path) and / or prependPath($path).
For example, assuming view.php
exists in ./views
, ./views/controller1
and
./views/base-controller
the code below will lead to ./views/view.php
being
rendered without even trying to search ./views/controller1
or
./views/base-controller
for view.php
:
If a path is not prepended to the name of the file to be rendered, then the search for a file to be rendered starts from the first element (i.e file path value) inside the registered array of file paths to the last element inside the array. It is up to the user of this package to register file paths in a way that seems sensible to their use-case.
Given the following file paths:
If view.php
exists in both ./views/controller1
and ./views/base-controller
, then the
search will lead to ./views/controller1/view.php
being selected and rendered when any of
the *render()** methods is called. This is because ./views/controller1
comes before
./views/base-controller
in the file paths array.
If you want to give ./views/base-controller
a higher precedence in the file paths
array, you can do the following:
You can also accomplish the same thing with the following:
Escaping Data to be Passed to Views
Escaping functionality is provided via the laminas-escaper package. It is STRONGLY RECOMMENDED that you read this article to understand the principles behind properly escaping data.
Escaping is possible in four contexts:
- Html: this type of escaping should be used for view data variables which may contain html markup. For example:
./views/view-with-escapable-html.php
Given $var_that_should_be_html_escaped
with an initial value of:
'<script>alert("zf2");</script>'
it will be transformed to
'<script>alert("zf2");</script>'
after html escaping is applied to it.
- Html Attribute: this type of escaping should be used for view data variables which are meant to be rendered as attribute values within html elements in a view. For example:
./views/view-with-escapable-html-attrs.php
Given $var_that_should_be_html_attr_escaped
has an initial value of:
'faketitle" onmouseover="alert(/ZF2!/);'
it will be transformed to
'faketitle" onmouseover="alert(/ZF2!/);'
after html attribute escaping is applied to it.
- Css: this type of escaping should be used for view data variables which are meant to be rendered
within
<style>
tags or inside thestyle
attribute of any html tag. For example:
./views/view-with-escapable-css.php
Given $var_that_should_be_css_escaped
has an initial value of:
"body { background-image: url('http://example.com/foo.jpg?'); }</style><script>alert('You\\'ve been XSSed!')</script><style>"
it will be transformed to
"body\20 \7B \20 background\2D image\3A \20 url\28 \27 http\3A \2F \2F example\2E com\2F foo\2E jpg\3F \27 \29 \3B \20 \7D \3C \2F style\3E \3C script\3E alert\28 \27 You\5C \27 ve\20 been\20 XSSed\21 \27 \29 \3C \2F script\3E \3C style\3E"
after css escaping is applied to it.
Given $another_var_that_should_be_css_escaped
has an initial value of:
' display: block; " onclick="alert(\'You\\\'ve been XSSed!\'); '
it will be transformed to
'\20 display\3A \20 block\3B \20 \22 \20 onclick\3D \22 alert\28 \27 You\5C \27 ve\20 been\20 XSSed\21 \27 \29 \3B \20 '
after css escaping is applied to it.
- Javascript: this type of escaping can be safely used for view data variables which are meant to be rendered as string literals or digits within Javascript code inside the view to be rendered. Other Javascript code that would be injected from view data variables can also be Javascript escaped, but it is possible that escaping them may lead to Javascript syntax error(s) when the view is rendered in a browser. For example:
./views/view-with-escapable-js.php
Given $var_that_can_be_safely_js_escaped
has an initial value of:
"javascript's cool"
it will be transformed to
'javascript\x27s\x20cool'
after Javascript escaping is applied to it.
Given $a_var_that_can_be_safely_js_escaped
has an initial value of:
'563'
it will be left unchanged with the same value of
'563'
after Javascript escaping is applied to it.
Given $a_var_that_cant_be_guaranteed_to_be_safely_js_escaped
has an initial value of:
' var x = \'Yo!\'; alert(x); '
it will be transformed to
'\x20var\x20x\x20\x3D\x20\x27Yo\x21\x27\x3B\x20alert\x28x\x29\x3B\x20'
after Javascript escaping is applied to it.
You can enable escaping
-
during the creation of the Renderer object.
-
during a call to any of the *render()** methods.
- manually within your view file by calling any of the public escape methods available in Renderer Class:
$this->escapeHtml(string $some_string_variable)
$this->escapeHtmlAttr(string $some_string_variable)
$this->escapeCss(string $some_string_variable)
$this->escapeJs(string $some_string_variable)
$this->escapeUrl(string $some_string_variable)
- To enable escaping during the creation of a Renderer object:
Using Wild Cards in Escape Specification
To specify that all fields in the data array be HTML escaped, set the
$data_vars_2_be_html_escaped
array in the example above with a value of['*']
To specify that all fields in the data array be HTML attribute escaped, set the
$data_vars_2_be_html_attr_escaped
array in the example above with a value of['*']
To specify that all fields in the data array be CSS escaped, set the
$data_vars_2_be_css_escaped
array in the example above with a value of['*']
To specify that all fields in the data array be Javascript escaped, set the
$data_vars_2_be_js_escaped
array in the example above with a value of['*']
- To enable escaping during a call to any of the *render()** methods:
Enabling escaping via the constructor, is a neat way to enforce escaping of specified view data variables in subsequent calls to the render() methods without having to pass the escape paremeters each subsequent time any of the render() methods is called. This is how to enable auto-escaping on an instance of the Renderer class. You just have to make sure that the escaping parameters are set in a way that makes the most sense for the view(s) you are trying to render.
Only string values in the data array and its sub-arrays (if any) will be escaped if escaping is enabled.
More on escaping from the laminas-escaper website:
HTML escaping is accomplished via Laminas\Escaper\Escaper's escapeHtml method. Internally it uses PHP's htmlspecialchars, and additionally correctly sets the flags and encoding. One thing a developer needs to pay special attention too, is the encoding in which the document is served to the client; it must be the same as the encoding used for escaping! Go here for more details.
HTML Attribute escaping is accomplished via Laminas\Escaper\Escaper's escapeHtmlAttr method. Internally it will convert the data to UTF-8, check for it's validity, and use an extended set of characters to escape that are not covered by htmlspecialchars to cover the cases where an attribute might be unquoted or quoted illegally. Go here for more details.
CSS escaping is accomplished via Laminas\Escaper\Escaper's escapeCss method. CSS escaping excludes only basic alphanumeric characters and escapes all other characters into valid CSS hexadecimal escapes. Go here for more details.
Javascript escaping is accomplished via Laminas\Escaper\Escaper's escapeJs method. Javascript string literals in HTML are subject to significant restrictions particularly due to the potential for unquoted attributes and any uncertainty as to whether Javascript will be viewed as being CDATA or PCDATA by the browser. To eliminate any possible XSS vulnerabilities, Javascript escaping for HTML extends the escaping rules of both ECMAScript and JSON to include any potentially dangerous character. Very similar to HTML attribute value escaping, this means escaping everything except basic alphanumeric characters and the comma, period and underscore characters as hexadecimal or unicode escapes. Javascript escaping applies to all literal strings and digits. It is not possible to safely escape other Javascript markup. An extended set of characters are escaped beyond ECMAScript's rules for Javascript literal string escaping in order to prevent misinterpretation of Javascript as HTML leading to the injection of special characters and entities. Go here for more details.
Advanced Usage
Implementing a Two-Step View Templating System
The simplest way to implement a Two-Step View Templating System is to create two instances of the Renderer class. One instance will be used to render the layout view file and the other will be used to render the page content that will be passed as a data field to the first renderer (ie. the layout renderer). A single instance of the Renderer class could also be used to accomplish the same result. It's up to you to decide how data should be passed to the views.
Implementation: Assuming layout.php
, sample-content-page.php
,
two-step-view-implemetation-two-renderers.php
and two-step-view-implemetation-one-renderer.php
are all in the same folder.
layout.php
sample-content-page.php
two-step-view-implemetation-two-renderers.php
two-step-view-implemetation-one-renderer.php
Running two-step-view-implemetation-two-renderers.php
or two-step-view-implemetation-one-renderer.php
will lead to the output below:
Sharing Data between Layout and Page Content Views
two-step-view-implemetation-one-renderer-share-data.php
The example above can be extended for use-cases where more than one renderer is being used.
Nesting Renderers
You can actually pass instances of \Rotexsoft\FileRenderer\Renderer to php functions and statements that accept string arguments like echo, sprintf & the likes.
The instance of \Rotexsoft\FileRenderer\Renderer passed to such a function or statement will be automatically converted to a string by php automatically calling the \Rotexsoft\FileRenderer\Renderer::__toString() method of the instance.
\Rotexsoft\FileRenderer\Renderer::__toString() tries to render the file associated with the instance and passes the string result returned from rendering the file back to the function or statement that expects a string argument.
This behavior can be taken advantage of when a renderer has one or more renderers added to it as data via any of the following methods:
- an array containing one or more renderers is passed as the second argument passed to \Rotexsoft\FileRenderer\Renderer::__construct(...)
- calling \Rotexsoft\FileRenderer\Renderer::setVar($key, $value) with a second argument that is a renderer or an array of renderers
- object property assignment via the magic setter \Rotexsoft\FileRenderer\Renderer::__set($key, $value) builtin php mechanism
Now let's see how we can leverage this automatic conversion of renderer objects to strings in an application.
Assume you have the four php files below in your application:
layout.php
layout_content.php
layout_content_1.php
layout_content_2.php
We can render them via nesting like so in a file that is in the same folder with the four php files above (they could be in any folder, just make sure the correct path is prepended to the file name passed as the first argument to the constructor of the renderer class):
nesting_tester.php
Which results in the output below:
Now let's walk through what just happened.
We created four renderer objects assigned to $layout_renderer, $page_renderer, $page_renderer2 and $page_renderer3 to render layout.php, layout_content.php, layout_content_1.php and layout_content_2.php respectively.
We then did the following assignments:
-
The renderer $page_renderer is assigned to the renderer $layout_renderer as a property named layout_content which will be accessible via the variable $layout_content inside the layout.php file to be rendered by $layout_renderer
-
The renderer $page_renderer2 is assigned to the renderer $page_renderer as a property named layout_content_1 which will be accessible via the variable $layout_content_1 inside the layout_content.php file to be rendered by $page_renderer
- The renderer $page_renderer3 is assigned to the renderer $page_renderer2 as a property named layout_content_2 which will be accessible via the variable $layout_content_2 inside the layout_content_1.php file to be rendered by $page_renderer2
We finally execute the echo statement with $layout_renderer as its argument:
This leads to php automatically executing $layout_renderer->__toString(), which leads to the rendering of layout.php which has the echo statement below inside it
$layout_content in layout.php shown in the echo statement snippet above is actually referencing the renderer assigned to $page_renderer in nesting_tester.php earlier above.
This echo statement in layout.php leads to php automatically executing $layout_content->__toString(), which leads to the rendering of layout_content.php which has the echo statement below inside it
$layout_content_1 in layout_content.php shown in the echo statement snippet above is actually referencing the renderer assigned to $page_renderer2 in nesting_tester.php earlier above.
This echo statement in layout_content.php leads to php automatically executing $layout_content_1->__toString(), which leads to the rendering of layout_content_1.php which has the echo statement below inside it
$layout_content_2 in layout_content_1.php shown in the echo statement snippet above is actually referencing the renderer assigned to $page_renderer3 in nesting_tester.php earlier above.
This echo statement in layout_content_1.php leads to php automatically executing $layout_content_2->__toString(), which leads to the rendering of layout_content_2.php which has just html and no php in it and is the last file rendered in this chain of renderers. Below is the content of layout_content_2.php again.
This all leads to
- the output of rendering layout_content_2.php being returned back to the echo statement in layout_content_1.php,
- the output of rendering layout_content_1.php is in turn returned back to the echo statement in layout_content.php,
- the output of rendering layout_content.php is in turn returned back to the echo statement in layout.php
- and finally all these outputs get combined inside in layout.php and printed out to the screen as the output below (earlier shown above):
That's how you nest renderers and render their combined output.
Note: with nesting, you have to supply all the information needed to render each file to the constructor of the renderer class when creating each renderer object. See \Rotexsoft\FileRenderer\Renderer::__construct(...) for more details.