{"id":36405287,"url":"https://github.com/rotexsoft/file-renderer","last_synced_at":"2026-01-23T08:11:03.409Z","repository":{"id":45119862,"uuid":"46154811","full_name":"rotexsoft/file-renderer","owner":"rotexsoft","description":"A tool for rendering PHP files that are meant to generate output.","archived":false,"fork":false,"pushed_at":"2026-01-21T18:17:21.000Z","size":256,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-22T06:24:25.031Z","etag":null,"topics":["escaper","escaping","html","php","php-escaper","php-escaping","php-html-templating","php-lightweight","php-render","php-renderer","php-template-engine","php-template-view","php-templating","php-view","php-views","php-xss","template-engine","templates","templating","views"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rotexsoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-11-14T00:48:15.000Z","updated_at":"2026-01-21T18:17:25.000Z","dependencies_parsed_at":"2024-04-26T00:31:48.741Z","dependency_job_id":"9af50b64-4767-45ee-869f-0480dcabc618","html_url":"https://github.com/rotexsoft/file-renderer","commit_stats":{"total_commits":174,"total_committers":6,"mean_commits":29.0,"dds":0.08045977011494254,"last_synced_commit":"5dd8b37873c8832c892037aa72fd7c9a81ab9e97"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/rotexsoft/file-renderer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rotexsoft%2Ffile-renderer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rotexsoft%2Ffile-renderer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rotexsoft%2Ffile-renderer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rotexsoft%2Ffile-renderer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rotexsoft","download_url":"https://codeload.github.com/rotexsoft/file-renderer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rotexsoft%2Ffile-renderer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28684019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T05:48:07.525Z","status":"ssl_error","status_checked_at":"2026-01-23T05:48:07.129Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["escaper","escaping","html","php","php-escaper","php-escaping","php-html-templating","php-lightweight","php-render","php-renderer","php-template-engine","php-template-view","php-templating","php-view","php-views","php-xss","template-engine","templates","templating","views"],"created_at":"2026-01-11T16:40:01.967Z","updated_at":"2026-01-23T08:11:03.402Z","avatar_url":"https://github.com/rotexsoft.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHP File Renderer\n\n[![PHP Tests and Code Quality Tools](https://github.com/rotexsoft/file-renderer/workflows/Run%20PHP%20Tests%20and%20Code%20Quality%20Tools/badge.svg)](https://github.com/rotexsoft/file-renderer/actions?query=workflow%3A%22Run+PHP+Tests+and+Code+Quality+Tools%22) \u0026nbsp;\n![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/rotexsoft/file-renderer) \u0026nbsp; \n![GitHub](https://img.shields.io/github/license/rotexsoft/file-renderer) \u0026nbsp; \n[![Coverage Status](https://coveralls.io/repos/github/rotexsoft/file-renderer/badge.svg?branch=master)](https://coveralls.io/github/rotexsoft/file-renderer?branch=master) \u0026nbsp; \n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/rotexsoft/file-renderer) \u0026nbsp;\n![Packagist Downloads](https://img.shields.io/packagist/dt/rotexsoft/file-renderer) \u0026nbsp;\n![GitHub top language](https://img.shields.io/github/languages/top/rotexsoft/file-renderer) \u0026nbsp; \n![Packagist PHP Version Support](https://img.shields.io/packagist/php-v/rotexsoft/file-renderer) \u0026nbsp; \n![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/rotexsoft/file-renderer/latest) \u0026nbsp; \n![GitHub last commit](https://img.shields.io/github/last-commit/rotexsoft/file-renderer) \u0026nbsp; \n![GitHub Release Date](https://img.shields.io/github/release-date/rotexsoft/file-renderer) \u0026nbsp; \n\u003ca href=\"https://libraries.io/packagist/rotexsoft%2Ffile-renderer\"\u003e\n    \u003cimg alt=\"Libraries.io dependency status for GitHub repo\" src=\"https://img.shields.io/librariesio/github/rotexsoft/file-renderer\"\u003e\n\u003c/a\u003e\n\n- [PHP File Renderer](#php-file-renderer)\n    - [Introduction](#introduction)\n        - [Main Features](#main-features)\n\t- [Acknowledgement](#acknowledgement)\n    - [Changelog](#changelog)\n\t- [Contribution](#contribution)\n\t\t- [Running Tests](#running-tests)\n\t- [Requirements](#requirements)\n\t- [Installation](#installation)\n\t- [Usage](#usage)\n\t\t- [Basic Usage](#basic-usage)\n\t\t- [Getting, Setting and Unsetting View Data](#getting-setting-and-unsetting-view-data)\n\t\t\t- [Setting View Data](#setting-view-data)\n\t\t\t- [Getting View Data](#getting-view-data)\n\t\t\t- [Unsetting View Data](#unsetting-view-data)\n\t\t- [File paths](#file-paths)\n\t\t- [Escaping Data to be Passed to Views](#escaping-data-to-be-passed-to-views)\n\t\t\t- [Using Wild Cards in Escape Specification](#using-wild-cards-in-escape-specification)\n\t\t- [Advanced Usage](#advanced-usage)\n\t\t\t- [Implementing a Two-Step View Templating System](#implementing-a-two-step-view-templating-system)\n\t\t\t\t- [Sharing Data between Layout and Page Content Views](#sharing-data-between-layout-and-page-content-views)\n\t\t\t- [Nesting Renderers](#nesting-renderers)\n\n## Introduction\n\nThis is a simple, elegant and flexible tool that can be used to render php files (also referred to as `Views` within this documentation)\nthat emit valid html output to a web-browser. It is designed to be unobtrusive; your view files can easily be used with a different\nrendering or templating library. You do not need to learn any new syntax (or markup / templating language) in order to compose your\nviews; simply write your views in plain old php. This package also provides escaping functionality for data passed to the view file(s).\n\nThis package can easily be used by framework developers to implement the View layer of an MVC (Model-View-Controller) framework.\nIt can also be easily incorporated into existing frameworks.\n\n100% Unit Test Coverage.\n\nUsers of this package are still responsible for making sure that they validate or sanitize data coming into their application(s) via user input\n(eg. via html forms) with tools like  [Respect\\Validation](https://github.com/Respect/Validation), [Valitron](https://github.com/vlucas/valitron),\n[Upload](https://github.com/brandonsavage/Upload), [Volan](https://github.com/serkin/Volan), [Sirius Validation](https://github.com/siriusphp/validation),\n[Filterus](https://github.com/ircmaxell/filterus), etc.\n\n### Main Features\n* No new templating language or syntax to learn, just good old PHP is required to compose view files to be rendered.\n    * View file(s) in existing projects can easily be adapted for rendering via this package with very little effort.\n* 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.\n* 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.\n    * Escaping is performed on the values in the data array based on specified escape rules.\n* 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).\n\n## Acknowledgement\n\nThe escaping functionality in this package is implemented using the [laminas-escaper](https://docs.laminas.dev/laminas-escaper/) package.\n\n## Changelog\n\n[Here](https://github.com/rotexsoft/file-renderer/releases).\n\n## Contribution\n\nSince the goal of this package is to be lean and flexible, pull requests for significant\nnew features will not be accepted. Users are encouraged to extend the package with new\nfeature(s) in their own projects. However, bug fix and documentation enhancement\nrelated pull requests are greatly welcomed.\n\n### Running Tests\n\n  ` ./vendor/bin/phpunit --coverage-text`\n\n### Branching\n\nThese are the branches in this repository:\n\n- **master:** contains code for the latest major version of this package\n- **1.X:** contains code for the **1.x** version of this package\n- **2.X:** contains code for the **2.x** version of this package\n- **5.x:** contains code for the **5.x** version of this package\n- **6.x:** contains code for the **6.x** version of this package\n- **7.x:** contains code for the **7.x** version of this package\n\n## Requirements\n\n* PHP 8.1+\n* Not currently certified for use with HHVM (unit tests failing when run in an HHVM environment).\n\n## Installation\n`composer require rotexsoft/file-renderer`\n\n## Usage\n\n### Basic Usage\n\nYour 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):\n\n`/some/path/my-project/test.php`\n\n```php\n\u003c?php\n    include './vendor/autoload.php';\n\n    //To render a php file named `view.php` located in the `views` sub-directory\n    //within the directory containing this php script, use the code below:\n\n    $file_paths = [ './views' ]; //you can also use absolute paths\n\n    // The keys in this data array will be converted to variables when rendering\n    // a view file. For example, a variable named `$paragraph_data_from_file_renderer`\n    // with the value `'This is a Paragraph!!'` will be available to the view during\n    // rendering.\n\n    $bad_css_with_xss = \u003c\u003c\u003cINPUT\nbody { background-image: url('http://example.com/foo.jpg?'); }\u003c/style\u003e\n\u003cscript\u003ealert('You\\\\'ve been XSSed!')\u003c/script\u003e\u003cstyle\u003e\nINPUT;\n\n    $bad_css_with_xss2 = ' display: block; \" onclick=\"alert(\\'You\\\\\\'ve been XSSed!\\'); ';\n\n    $bad_url_segment_with_xss = ' \" onmouseover=\"alert(\\'zf2\\')';\n\n    $view_data = [\n        'paragraph_data_from_file_renderer'                     =\u003e 'This is a Paragraph!!',\n        'var_that_should_be_html_escaped'                       =\u003e '\u003cscript\u003ealert(\"zf2\");\u003c/script\u003e',\n        'var_that_should_be_html_attr_escaped'                  =\u003e 'faketitle\" onmouseover=\"alert(/ZF2!/);',\n        'var_that_should_be_css_escaped'                        =\u003e $bad_css_with_xss,\n        'another_var_that_should_be_css_escaped'                =\u003e $bad_css_with_xss2,\n        'var_that_can_be_safely_js_escaped'                     =\u003e \"javascript's cool\",\n        'a_var_that_can_be_safely_js_escaped'                   =\u003e '563',\n        'a_var_that_cant_be_guaranteed_to_be_safely_js_escaped' =\u003e ' var x = \\'Yo!\\'; alert(x); ',\n        'var_that_should_be_url_escaped'                        =\u003e $bad_url_segment_with_xss,\n    ];\n\n    //You MUST include the file extension in the file name (in this case `.php`)\n    //NOTE: that the fourth argument represents the encoding that will be used\n    //      by the escaping functions in the renderer. This value should be the\n    //      same as the encoding specified in the view file being rendered\n    //      (eg. the charset value of the http-equiv meta tag in your view).\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('view.php', $view_data, $file_paths, 'utf-8');\n\n    //You could alternately create the Renderer object like below:\n    //$renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./views/view.php', $view_data);\n\n    $renderer-\u003erenderToScreen(); //Render the file immediately to the screen\n\n    // The two lines below are equivalent to $renderer-\u003erenderToScreen()\n    $output = $renderer-\u003erenderToString(); //First capture the output of rendering\n                                           //the file in a string variable.\n    echo $output;\n\n    //The render*() methods will extract the elements of the data array into\n    //variables (array keys will be used as variable names) that will be\n    //available to the view file to be rendered before rendering the view.\n\n    //You can also pass the file name and data parameters to the render*() methods.\n    //You will have to include the path in the file name if you did not supply an\n    //array of file paths when your Renderer object was created.\n    $renderer2 = new \\Rotexsoft\\FileRenderer\\Renderer();\n\n    $renderer2-\u003erenderToScreen('./views/view.php', $view_data);\n\n    //OR\n    $output = $renderer2-\u003erenderToString('./views/view.php', $view_data);\n    echo $output;\n?\u003e\n```\n\n`/some/path/my-project/views/view.php`\n\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eEscaped Entities\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n\n        \u003cstyle\u003e\n           \u003c?php // CSS escaping is being applied to the variable below ?\u003e\n            \u003c?php echo $this-\u003eescapeCss($var_that_should_be_css_escaped); ?\u003e\n        \u003c/style\u003e\n\n        \u003cscript type=\"text/javascript\"\u003e\n            // Javascript escaping is being applied to the variable below\n            var some_string = '\u003c?php echo $this-\u003eescapeJs($var_that_can_be_safely_js_escaped); ?\u003e';\n            alert(some_string);\n        \u003c/script\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003c!-- An unescaped variable --\u003e\n        \u003cp\u003e\u003c?php echo $paragraph_data_from_file_renderer; ?\u003e\u003c/p\u003e\n\n        \u003cdiv\u003e\n            \u003c!-- Html Attribute escaping is being applied to the variable below --\u003e\n            \u003cspan title=\"\u003c?php echo $this-\u003eescapeHtmlAttr($var_that_should_be_html_attr_escaped); ?\u003e\" \u003e\n                What framework are you using?\n                \u003c!-- Html escaping is being applied to the variable below --\u003e\n                \u003c?php echo $this-\u003eescapeHtml($var_that_should_be_html_escaped); ?\u003e\n            \u003c/span\u003e\n        \u003c/div\u003e\n\n        \u003c!-- CSS escaping is being applied to the variable below --\u003e\n        \u003cp style=\"\u003c?php echo $this-\u003eescapeCss($another_var_that_should_be_css_escaped); ?\u003e\"\u003e\n            User controlled CSS needs to be properly escaped!\n\n            \u003c!-- Url escaping is being applied to the variable below --\u003e\n            \u003ca href=\"http://example.com/?name=\u003c?php echo $this-\u003eescapeUrl($var_that_should_be_url_escaped); ?\u003e\"\u003eClick here!\u003c/a\u003e\n        \u003c/p\u003e\n\n        \u003c!-- Javascript escaping is being applied to the variable below --\u003e\n        \u003cp onclick=\"var a_number = \u003c?php echo $this-\u003eescapeJs($a_var_that_can_be_safely_js_escaped); ?\u003e; alert(a_number);\"\u003e\n            Javascript escaping the variable in this paragraph's onclick attribute should\n            be safe if the variable contains basic alphanumeric characters. It will definitely\n            prevent XSS attacks.\n        \u003c/p\u003e\n\n        \u003c!-- Javascript escaping is being applied to the variable below --\u003e\n        \u003cp onclick=\"\u003c?php echo $this-\u003eescapeJs($a_var_that_cant_be_guaranteed_to_be_safely_js_escaped); ?\u003e\"\u003e\n            Javascript escaping the variable in this paragraph's onclick attribute may lead\n            to Javascript syntax error(s) but will prevent XSS attacks.\n        \u003c/p\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n\n```\n\n**NOTE:** the file name, if any, supplied to the **render*()** methods will be\nconsidered first for rendering if the file exists. The file name supplied to the\nconstructor during object creation will be considered last for rendering if the\nfile name supplied to the **render*()** method can't be found.\n\n**NOTE:** you can access the Renderer object inside your view via the **`$this`** variable.\nThere are five escape methods you can use within your view:\n* **`$this-\u003eescapeHtml(string $some_string_variable):`** an alias for PHP's htmlspecialchars() for escaping data which may contain html markup.\n* **`$this-\u003eescapeHtmlAttr(string $some_string_variable):`** for escaping data which is meant to be rendered as an attribute value within an html element in a view.\n* **`$this-\u003eescapeCss(string $some_string_variable):`** for escaping data which is meant to be rendered within `\u003cstyle\u003e` tags or inside the style attribute of any html element.\n* **`$this-\u003eescapeJs(string $some_string_variable):`** for escaping data which is meant to be rendered as string literals or digits within Javascript code in a view.\n* **`$this-\u003eescapeUrl(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.\n\nSee the [Escaping Data to be Passed to Views](#escaping-data-to-be-passed-to-views) section for more info about escaping.\n\n\n### Getting, Setting and Unsetting View Data\n\n\n#### Setting View Data\n\nView data can be supplied when the Renderer object is created / instantiated\n```php\n\u003c?php\n    //data to supply when the Renderer object is created / instantiated\n    $view_data = [ 'paragraph_data_from_file_renderer' =\u003e 'This is a Paragraph!!' ];\n\n    //pass $view_data to the constructor to set view data during object creation\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./views/view.php', $view_data);\n\n    //NOTE: elements of the view data array supplied during construction time\n    //      can be updated or deleted after object creation.\n\n    //NOTE: if no view data array is supplied during object creation, the view\n    //      data for the created object will have a default value of an empty\n    //      array.\n?\u003e\n```\n\nView data can also be set or updated after the Renderer object has been created / instantiated\n```php\n\u003c?php\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer();\n\n    //Set data using object assignment syntax.\n    //Since view data was not supplied during object creation in this\n    //example the value below is being set for the first time for\n    //`paragraph_data_from_file_renderer` inside the internal view\n    //data array.\n    $renderer-\u003eparagraph_data_from_file_renderer = 'This is a Paragraph!!';\n\n    //OR set data using the setVar() method\n    // $renderer-\u003esetVar('paragraph_data_from_file_renderer', 'This is a Paragraph!!');\n\n    //This will update the value of `paragraph_data_from_file_renderer` in the\n    //internal view data array (ie. the protected `data` property in \\Rotexsoft\\FileRenderer\\Renderer).\n    $renderer-\u003eparagraph_data_from_file_renderer = 'This is a new Paragraph!!';\n?\u003e\n```\n\n#### Getting View Data\n\nView data values can be accessed after the Renderer object is created / instantiated\n```php\n\u003c?php\n    $view_data = [ 'paragraph_data_from_file_renderer' =\u003e 'This is a Paragraph!!' ];\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./views/view.php', $view_data);\n\n    //You can access the value of `paragraph_data_from_file_renderer` like this:\n    $renderer-\u003eparagraph_data_from_file_renderer;\n\n    //OR like this:\n    $renderer-\u003egetVar('paragraph_data_from_file_renderer');\n?\u003e\n```\n\n#### Unsetting View Data\n\nView data values can be deleted after the Renderer object is created / instantiated\n```php\n\u003c?php\n    $view_data = [ 'paragraph_data_from_file_renderer' =\u003e 'This is a Paragraph!!' ];\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./views/view.php', $view_data);\n\n    //You can completely remove the `paragraph_data_from_file_renderer` entry\n    //inside the internal view data array after the Renderer object creation\n    //like this:\n    unset($renderer-\u003eparagraph_data_from_file_renderer);\n?\u003e\n```\n\n### File paths\n\nThese are paths that will be searched for the file to be rendered via the __**render*()**__ methods.\n\nIf a path is prepended to the name of the file to be rendered (which can be supplied either during\nthe creation of the renderer object or during a call to any of the __**render*()**__ methods) and\nthe file with the prepnded path exists, that file will be rendered and the renderer will not\nbother searching the file paths supplied during construction or via call(s) to __**appendPath($path)**__\nand / or __**prependPath($path)**__.\n\nFor example, assuming `view.php` exists in `./views`, `./views/controller1` and\n`./views/base-controller` the code below will lead to `./views/view.php` being\nrendered without even trying to search `./views/controller1` or\n`./views/base-controller` for `view.php`:\n\n```php\n\u003c?php\n    $file_paths = [ './views/controller1', './views/base-controller'  ];\n    $view_data = [ 'paragraph_data_from_file_renderer' =\u003e 'This is a Paragraph!!' ];\n\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./views/view.php', $view_data, $file_paths);\n\n    //$renderer-\u003erenderToScreen() OR $renderer-\u003erenderToScreen('./views/view.php');\n    //will both lead to the rendering of './views/view.php'\n?\u003e\n```\n\nIf a path is not prepended to the name of the file to be rendered, then the search for a file to\nbe rendered starts from the first element (i.e file path value) inside the registered array of\nfile paths to the last element inside the array. It is up to the user of this package to register\nfile paths in a way that seems sensible to their use-case.\n\nGiven the following file paths:\n```php\n\u003c?php\n    $file_paths = [ './views/controller1', './views/base-controller'  ];\n    $view_data = [ 'paragraph_data_from_file_renderer' =\u003e 'This is a Paragraph!!' ];\n\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('view.php', $view_data, $file_paths);\n?\u003e\n```\n\nIf `view.php` exists in both `./views/controller1` and `./views/base-controller`, then the\nsearch will lead to `./views/controller1/view.php` being selected and rendered when any of\nthe **render*()** methods is called. This is because `./views/controller1` comes before\n`./views/base-controller` in the file paths array.\n\nIf you want to give `./views/base-controller` a higher precedence in the file paths\narray, you can do the following:\n\n```php\n\u003c?php\n    $renderer-\u003eremoveFirstNPaths(1); //will remove './views/controller1' from the file paths array\n\n    //$renderer-\u003egetFilePaths() at this point will return [ './views/base-controller' ]\n\n    $renderer-\u003eappendPath('./views/controller1'); // will add './views/controller1' to the end of the\n                                                  // file paths array\n    // $renderer-\u003egetFilePaths() at this point will return\n    //      [ './views/base-controller', './views/controller1' ]\n?\u003e\n```\n\nYou can also accomplish the same thing with the following:\n\n```php\n\u003c?php\n    $renderer-\u003eremoveLastNPaths(1); //will remove './views/base-controller' from the file paths array\n\n    //$renderer-\u003egetFilePaths() at this point will return [ './views/controller1' ]\n\n    $renderer-\u003eprependPath('./views/base-controller'); // will add './views/base-controller' to the\n                                                       // front of the file paths array\n    // $renderer-\u003egetFilePaths() at this point will return\n    //      [ './views/base-controller', './views/controller1' ]\n?\u003e\n```\n\n### Escaping Data to be Passed to Views\n\nEscaping functionality is provided via the laminas-escaper package. It is **STRONGLY RECOMMENDED** that you read this\n[article](https://docs.laminas.dev/laminas-escaper/theory-of-operation/)\nto understand the principles behind properly escaping data.\n\nEscaping is possible in four contexts:\n* **Html:** this type of escaping should be used for view data variables which may contain html markup.\nFor example:\n\n`./views/view-with-escapable-html.php`\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eEncodings set correctly!\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n            What framework are you using?\n            \u003c?php echo $var_that_should_be_html_escaped; ?\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nGiven `$var_that_should_be_html_escaped` with an initial value of:\n\u003e `'\u003cscript\u003ealert(\"zf2\");\u003c/script\u003e'`\n\nit will be transformed to\n\u003e `'\u0026lt;script\u0026gt;alert(\u0026quot;zf2\u0026quot;);\u0026lt;/script\u0026gt;'`\n\nafter **html** escaping is applied to it.\n\n* **Html Attribute:** this type of escaping should be used for view data variables which are meant to be\nrendered as attribute values within html elements in a view. For example:\n\n`./views/view-with-escapable-html-attrs.php`\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eEncodings set correctly!\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n            \u003cspan title=\"\u003c?php echo $var_that_should_be_html_attr_escaped; ?\u003e\" \u003e\n                What framework are you using?\n            \u003c/span\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nGiven `$var_that_should_be_html_attr_escaped` has an initial value of:\n\u003e`'faketitle\" onmouseover=\"alert(/ZF2!/);'`\n\nit will be transformed to\n\u003e`'faketitle\u0026quot;\u0026#x20;onmouseover\u0026#x3D;\u0026quot;alert\u0026#x28;\u0026#x2F;ZF2\u0026#x21;\u0026#x2F;\u0026#x29;\u0026#x3B;'`\n\nafter **html attribute** escaping is applied to it.\n\n* **Css:** this type of escaping should be used for view data variables which are meant to be rendered\nwithin `\u003cstyle\u003e` tags or inside the `style` attribute of any html tag. For example:\n\n`./views/view-with-escapable-css.php`\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eEscaped CSS\u003c/title\u003e\n        \u003cmeta charset=\"UTF-8\"/\u003e\n        \u003cstyle\u003e\n            \u003c?php echo $var_that_should_be_css_escaped; ?\u003e\n        \u003c/style\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cp style=\"\u003c?php echo $another_var_that_should_be_css_escaped; ?\u003e\"\u003e\n            User controlled CSS needs to be properly escaped!\n        \u003c/p\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nGiven `$var_that_should_be_css_escaped` has an initial value of:\n\u003e`\"body { background-image: url('http://example.com/foo.jpg?'); }\u003c/style\u003e\u003cscript\u003ealert('You\\\\'ve been XSSed!')\u003c/script\u003e\u003cstyle\u003e\"`\n\nit will be transformed to\n\u003e`\"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\"`\n\nafter **css** escaping is applied to it.\n\nGiven `$another_var_that_should_be_css_escaped` has an initial value of:\n\u003e`' display: block; \" onclick=\"alert(\\'You\\\\\\'ve been XSSed!\\'); '`\n\nit will be transformed to\n\u003e`'\\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 '`\n\nafter **css** escaping is applied to it.\n\n* **Javascript:** this type of escaping can be safely used for view data variables which are meant to be\nrendered as string literals or digits within Javascript code inside the view to be rendered. Other\nJavascript code that would be injected from view data variables can also be Javascript escaped,\nbut it is possible that escaping them may lead to Javascript syntax error(s) when the view is\nrendered in a browser. For example:\n\n`./views/view-with-escapable-js.php`\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eEscaped Entities\u003c/title\u003e\n        \u003cmeta charset=\"UTF-8\"/\u003e\n        \u003cscript type=\"text/javascript\"\u003e\n            var some_string = '\u003c?php echo $var_that_can_be_safely_js_escaped; ?\u003e';\n            alert(some_string);\n        \u003c/script\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cp onclick=\"var a_number = \u003c?php echo $a_var_that_can_be_safely_js_escaped; ?\u003e; alert(a_number);\"\u003e\n            Javascript escaping the variable in this paragraph's onclick attribute should\n            be safe if the variable contains basic alphanumeric characters. It will definitely\n            prevent XSS attacks.\n        \u003c/p\u003e\n\n        \u003cp onclick=\"\u003c?php echo $a_var_that_cant_be_guaranteed_to_be_safely_js_escaped; ?\u003e\"\u003e\n            Javascript escaping the variable in this paragraph's onclick attribute may lead\n            to Javascript syntax error(s) but will prevent XSS attacks.\n        \u003c/p\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nGiven `$var_that_can_be_safely_js_escaped` has an initial value of:\n\u003e`\"javascript's cool\"`\n\nit will be transformed to\n\u003e`'javascript\\x27s\\x20cool'`\n\nafter **Javascript** escaping is applied to it.\n\nGiven `$a_var_that_can_be_safely_js_escaped` has an initial value of:\n\u003e`'563'`\n\nit will be left unchanged with the same value of\n\u003e`'563'`\n\nafter **Javascript** escaping is applied to it.\n\nGiven `$a_var_that_cant_be_guaranteed_to_be_safely_js_escaped` has an initial value of:\n\u003e`' var x = \\'Yo!\\'; alert(x); '`\n\nit will be transformed to\n\u003e`'\\x20var\\x20x\\x20\\x3D\\x20\\x27Yo\\x21\\x27\\x3B\\x20alert\\x28x\\x29\\x3B\\x20'`\n\nafter **Javascript** escaping is applied to it.\n\nYou can enable escaping\n\n1. during the creation of the Renderer object.\n\n2. during a call to any of the **render*()** methods.\n\n3. manually within your view file by calling any of the public escape methods available in Renderer Class:\n    - `$this-\u003eescapeHtml(string $some_string_variable)`\n    - `$this-\u003eescapeHtmlAttr(string $some_string_variable)`\n    - `$this-\u003eescapeCss(string $some_string_variable)`\n    - `$this-\u003eescapeJs(string $some_string_variable)`\n    - `$this-\u003eescapeUrl(string $some_string_variable)`\n\n\n* To enable escaping during the creation of a Renderer object:\n\n```php\n\u003c?php\n    $file_paths = [];\n\n    $bad_css_with_xss = \u003c\u003c\u003cINPUT\nbody { background-image: url('http://example.com/foo.jpg?'); }\u003c/style\u003e\n\u003cscript\u003ealert('You\\\\'ve been XSSed!')\u003c/script\u003e\u003cstyle\u003e\nINPUT;\n    $bad_css_with_xss2 = ' display: block; \" onclick=\"alert(\\'You\\\\\\'ve been XSSed!\\'); ';\n\n    $view_data = [\n        'var_that_should_be_html_escaped'                       =\u003e '\u003cscript\u003ealert(\"zf2\");\u003c/script\u003e',\n        'var_that_should_be_html_attr_escaped'                  =\u003e 'faketitle\" onmouseover=\"alert(/ZF2!/);',\n        'var_that_should_be_css_escaped'                        =\u003e $bad_css_with_xss,\n        'another_var_that_should_be_css_escaped'                =\u003e $bad_css_with_xss2,\n        'var_that_can_be_safely_js_escaped'                     =\u003e \"javascript's cool\",\n        'a_var_that_can_be_safely_js_escaped'                   =\u003e '563',\n        'a_var_that_cant_be_guaranteed_to_be_safely_js_escaped' =\u003e ' var x = \\'Yo!\\'; alert(x); ',\n    ];\n\n    //an array of key(s) in the data array whose value(s) should each be html escaped\n    $data_vars_2_be_html_escaped = ['var_that_should_be_html_escaped'];\n\n    //an array of key(s) in the data array whose value(s) should each be html attr escaped\n    $data_vars_2_be_html_attr_escaped = ['var_that_should_be_html_attr_escaped'];\n\n    //an array of key(s) in the data array whose value(s) should each be css escaped\n    $data_vars_2_be_css_escaped = [\n        'var_that_should_be_css_escaped',\n        'another_var_that_should_be_css_escaped'\n    ];\n\n    //an array of key(s) in the data array whose value(s) should each be js escaped\n    $data_vars_2_be_js_escaped = [\n        'var_that_can_be_safely_js_escaped',\n        'a_var_that_can_be_safely_js_escaped',\n        'a_var_that_cant_be_guaranteed_to_be_safely_js_escaped'\n    ];\n\n    $escape_encoding = 'utf-8'; // should be the same encoding in which the document is served\n                                // to the browser (ie. the encoding defined in your html document).\n\n    //Escaping functionality is being enabled in the call to the constructor\n    //below because we are passing the $data_vars_2_be_*_escaped arrays to the\n    //constructor. By default, if these escape parameters are not supplied to\n    //the constructor, they will each internally be assigned an empty array\n    //value (meaning that escaping is disabled).\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer(\n                    '', //file name can be blank, but should be supplied when any render*() method is called\n                    $view_data,\n                    $file_paths,\n                    $escape_encoding,\n                    $data_vars_2_be_html_escaped,\n                    $data_vars_2_be_html_attr_escaped,\n                    $data_vars_2_be_css_escaped,\n                    $data_vars_2_be_js_escaped\n                );\n\n    $renderer-\u003erenderToScreen('./views/view-with-escapable-html.php'); //The escaping of the view data\n                                                                       //occurs only once during this\n                                                                       //first call to renderToScreen\n                                                                       //in order to prevent escaping\n                                                                       //the same data more than once.\n\n    $renderer-\u003erenderToScreen('./views/view-with-escapable-html-attrs.php'); //Already escaped data\n                                                                             //will be bound to this\n                                                                             //view.\n\n    $rendered_view = $renderer-\u003erenderToString('./views/view-with-escapable-css.php'); //Already\n                                                                                       //escaped data\n                                                                                       //will be bound\n                                                                                       //to this view.\n\n    $renderer-\u003erenderToScreen('./views/view-with-escapable-js.php');  //Already escaped data will be\n                                                                      //bound to this view.  \n?\u003e\n```\n\n\u003e#### Using Wild Cards in Escape Specification\n\n\u003eTo specify that all fields in the data array be **HTML escaped**, set the `$data_vars_2_be_html_escaped`\narray in the example above with a value of `['*']`\n\n\u003eTo specify that all fields in the data array be **HTML attribute escaped**, set the `$data_vars_2_be_html_attr_escaped`\narray in the example above with a value of `['*']`\n\n\u003eTo specify that all fields in the data array be **CSS escaped**, set the `$data_vars_2_be_css_escaped`\narray in the example above with a value of `['*']`\n\n\u003eTo specify that all fields in the data array be **Javascript escaped**, set the `$data_vars_2_be_js_escaped`\narray in the example above with a value of `['*']`\n\n* To enable escaping during a call to any of the **render*()** methods:\n\n```php\n\u003c?php\n    $bad_css_with_xss = \u003c\u003c\u003cINPUT\nbody { background-image: url('http://example.com/foo.jpg?'); }\u003c/style\u003e\n\u003cscript\u003ealert('You\\\\'ve been XSSed!')\u003c/script\u003e\u003cstyle\u003e\nINPUT;\n\n    $bad_css_with_xss2 = ' display: block; \" onclick=\"alert(\\'You\\\\\\'ve been XSSed!\\'); ';\n\n    $view_data = [\n        'var_that_should_be_html_escaped'                       =\u003e '\u003cscript\u003ealert(\"zf2\");\u003c/script\u003e',\n        'var_that_should_be_html_attr_escaped'                  =\u003e 'faketitle\" onmouseover=\"alert(/ZF2!/);',\n        'var_that_should_be_css_escaped'                        =\u003e $bad_css_with_xss,\n        'another_var_that_should_be_css_escaped'                =\u003e $bad_css_with_xss2,\n        'var_that_can_be_safely_js_escaped'                     =\u003e \"javascript's cool\",\n        'a_var_that_can_be_safely_js_escaped'                   =\u003e '563',\n        'a_var_that_cant_be_guaranteed_to_be_safely_js_escaped' =\u003e ' var x = \\'Yo!\\'; alert(x); ',\n    ];\n\n    //an array of key(s) in the data array whose value(s) should each be html escaped\n    $data_vars_2_be_html_escaped = ['var_that_should_be_html_escaped'];\n\n    //an array of key(s) in the data array whose value(s) should each be html attr escaped\n    $data_vars_2_be_html_attr_escaped = ['var_that_should_be_html_attr_escaped'];\n\n    //an array of key(s) in the data array whose value(s) should each be css escaped\n    $data_vars_2_be_css_escaped = [\n        'var_that_should_be_css_escaped',\n        'another_var_that_should_be_css_escaped'\n    ];\n\n    //an array of key(s) in the data array whose value(s) should each be js escaped\n    $data_vars_2_be_js_escaped = [\n        'var_that_can_be_safely_js_escaped',\n        'a_var_that_can_be_safely_js_escaped',\n        'a_var_that_cant_be_guaranteed_to_be_safely_js_escaped'\n    ];\n\n    $escape_encoding = 'utf-8'; // should be the same encoding in which the document is served\n                                // to the browser (ie. the encoding defined in your html document).\n\n    //create a renderer\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer();\n\n    //Escaping functionality is being enabled in the call to renderToScreen\n    //below because we are passing the $data_vars_2_be_*_escaped arrays to it.\n    //By default, if these escape parameters are not supplied, they will each\n    //internally be assigned an empty array value and merged with their\n    //corresponding internal \\Rotexsoft\\FileRenderer\\Renderer property\n    //values for $renderer-\u003edata_vars_2_html_escape, $renderer-\u003edata_vars_2_css_escape\n    //$renderer-\u003edata_vars_2_html_attr_escape and $renderer-\u003edata_vars_2_js_escape.\n    //Note that these properties are protected and not externally accessible.\n    $renderer-\u003erenderToScreen(\n                    './views/view-with-escapable-html.php',\n                    $view_data,                             //The escaping of the view data\n                    $escape_encoding,                       //occurs only once during this\n                    $data_vars_2_be_html_escaped,           //first call to renderToScreen\n                    $data_vars_2_be_html_attr_escaped,      //in order to prevent escaping\n                    $data_vars_2_be_css_escaped,            //the same data more than once.\n                    $data_vars_2_be_js_escaped\n                );                                                      \n\n    $renderer-\u003erenderToScreen(\n                    './views/view-with-escapable-html-attrs.php',   \n                    $view_data,                                     //Already escaped data in the\n                    $escape_encoding,                               //first call to renderToScreen\n                    $data_vars_2_be_html_escaped,                   //will be bound to this view\n                    $data_vars_2_be_html_attr_escaped,              //because the $view_data and\n                    $data_vars_2_be_css_escaped,                    //other parameters are the same\n                    $data_vars_2_be_js_escaped                      //and we are rendering using the\n                );                                                  //same instance of the Renderer class.\n\n    $rendered_view = $renderer-\u003erenderToString(\n                    './views/view-with-escapable-css.php',\n                    $view_data,                             //Already escaped data in the\n                    $escape_encoding,                       //first call to renderToScreen\n                    $data_vars_2_be_html_escaped,           //will be bound to this view\n                    $data_vars_2_be_html_attr_escaped,      //because the $view_data and\n                    $data_vars_2_be_css_escaped,            //other parameters are the same\n                    $data_vars_2_be_js_escaped              //and we are rendering using the\n                );                                          //same instance of the Renderer class.\n\n    $renderer-\u003erenderToScreen(\n                    './views/view-with-escapable-js.php',\n                    $view_data,                             //Already escaped data in the\n                    $escape_encoding,                       //first call to renderToScreen\n                    $data_vars_2_be_html_escaped,           //will be bound to this view\n                    $data_vars_2_be_html_attr_escaped,      //because the $view_data and\n                    $data_vars_2_be_css_escaped,            //other parameters are the same\n                    $data_vars_2_be_js_escaped              //and we are rendering using the\n                );                                          //same instance of the Renderer class.\n?\u003e\n```\n\n\u003eEnabling escaping via the constructor, is a neat way to enforce escaping of specified\nview data variables in subsequent calls to the **render*()** methods without having to\npass the escape paremeters each subsequent time any of the **render*()** methods is called.\nThis is how to enable **auto-escaping** on an instance of the Renderer class. You\njust have to make sure that the escaping parameters are set in a way that makes the most\nsense for the view(s) you are trying to render.\n\nOnly string values in the data array and its sub-arrays (if any) will be escaped if escaping is enabled.\n\nMore on escaping from the laminas-escaper website:\n\n\u003eHTML escaping is accomplished via Laminas\\Escaper\\Escaper's escapeHtml method. Internally it uses PHP's htmlspecialchars,\nand additionally correctly sets the flags and encoding. One thing a developer needs to pay special attention too, is the\nencoding in which the document is served to the client; **it must be the same** as the encoding used for escaping!\nGo [here](https://docs.laminas.dev/laminas-escaper/escaping-html/) for more details.\n\n\u003eHTML Attribute escaping is accomplished via Laminas\\Escaper\\Escaper's escapeHtmlAttr method. Internally it will convert the data to UTF-8,\ncheck for it's validity, and use an extended set of characters to escape that are not covered by htmlspecialchars to cover the cases\nwhere an attribute might be unquoted or quoted illegally.\nGo [here](https://docs.laminas.dev/laminas-escaper/escaping-html-attributes/) for more details.\n\n\u003eCSS escaping is accomplished via Laminas\\Escaper\\Escaper's escapeCss method. CSS escaping excludes only basic alphanumeric characters\nand escapes all other characters into valid CSS hexadecimal escapes.\nGo [here](https://docs.laminas.dev/laminas-escaper/escaping-css/) for more details.\n\n\u003eJavascript escaping is accomplished via Laminas\\Escaper\\Escaper's escapeJs method.\nJavascript string literals in HTML are subject to significant restrictions particularly due to the potential for unquoted attributes\nand any uncertainty as to whether Javascript will be viewed as being CDATA or PCDATA by the browser. To eliminate any possible XSS\nvulnerabilities, Javascript escaping for HTML extends the escaping rules of both ECMAScript and JSON to include any potentially\ndangerous character. Very similar to HTML attribute value escaping, this means escaping everything except basic alphanumeric\ncharacters and the comma, period and underscore characters as hexadecimal or unicode escapes.\nJavascript escaping applies to all literal strings and digits. It is not possible to safely escape other Javascript markup.\nAn extended set of characters are escaped beyond ECMAScript's rules for Javascript literal string escaping in order to prevent\nmisinterpretation of Javascript as HTML leading to the injection of special characters and entities.\nGo [here](https://docs.laminas.dev/laminas-escaper/escaping-javascript/) for more details.\n\n### Advanced Usage\n\n#### Implementing a Two-Step View Templating System\n\nThe simplest way to implement a **Two-Step View Templating System** is to create two instances of the **Renderer**\nclass. One instance will be used to render the layout view file and the other will be used to render the page content\nthat will be passed as a data field to the first renderer (ie. the layout renderer). A single instance of the **Renderer**\nclass could also be used to accomplish the same result. It's up to you to decide how data should be passed to the views.\n\n**Implementation:** Assuming `layout.php`, `sample-content-page.php`,\n`two-step-view-implemetation-two-renderers.php` and `two-step-view-implemetation-one-renderer.php`\nare all in the same folder.\n\n`layout.php`\n\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eTwo Step View Example\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n            \u003c?php echo $page_content; ?\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n`sample-content-page.php`\n\n```html\n\u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout.php\u003c/strong\u003e.\u003c/p\u003e\n```\n\n`two-step-view-implemetation-two-renderers.php`\n\n```php\n\u003c?php\n    $layout_data = [];\n    $layout_renderer = new \\Rotexsoft\\FileRenderer\\Renderer();\n    $layout_page_content_renderer = new \\Rotexsoft\\FileRenderer\\Renderer();\n\n    //Render the page content and store it in the data array to be passed to the layout.\n    $layout_data['page_content'] =\n             $layout_page_content_renderer-\u003erenderToString('./sample-content-page.php');\n\n    //Render the layout\n    $layout_renderer-\u003erenderToScreen('./layout.php', $layout_data);\n?\u003e\n```\n\n`two-step-view-implemetation-one-renderer.php`\n\n```php\n\u003c?php\n    $layout_data = [];\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer();\n\n    //Render the page content and store it in the data array to be passed to the layout.\n    $layout_data['page_content'] = $renderer-\u003erenderToString('./sample-content-page.php');\n\n    //Render the layout\n    $renderer-\u003erenderToScreen('./layout.php', $layout_data);\n?\u003e\n```\n\nRunning `two-step-view-implemetation-two-renderers.php` or `two-step-view-implemetation-one-renderer.php`\nwill lead to the output below:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eTwo Step View Example\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n            \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003eview.php\u003c/strong\u003e.\u003c/p\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n##### Sharing Data between Layout and Page Content Views\n\n`two-step-view-implemetation-one-renderer-share-data.php`\n\n```php\n\u003c?php\n    $layout_data = []; //pass this data array to renderToScreen or renderToString\n                       //when rendering layout.php. This is additional data that\n                       //will only be available to layout.php.\n\n    //The 'page_content' entry in the array below will be available to all\n    //views rendered using $renderer. Passing a data array with a 'page_content'\n    //entry to renderToString or renderToScreen will cause the intial value of\n    //the 'page_content' entry (in this case 'Default Page Content!') to be\n    //ignored when rendering (the value of the 'page_content' entry in the data\n    //array passed to renderToString or renderToScreen will be used instead).\n    $shared_data = ['page_content' =\u003e 'Default Page Content!'];\n    $renderer = new \\Rotexsoft\\FileRenderer\\Renderer('', $shared_data);\n\n    //Render the page content and store it in the data array to be passed to the layout.\n    $layout_data['page_content'] = $renderer-\u003erenderToString('./sample-content-page.php');\n\n    //Render the layout\n    $renderer-\u003erenderToScreen('./layout.php', $layout_data); // will cause\n                                                             // $layout_data['page_content']\n                                                             // to be used as $page_content\n                                                             // in layout.php instead of the\n                                                             // value of $shared_data['page_content'].\n\n    $renderer-\u003erenderToScreen('./layout.php'); // This will cause\n                                               // $shared_data['page_content']\n                                               // to be used as $page_content\n                                               // in layout.php because we are\n                                               // not passing any data array to\n                                               // renderToScreen so it looks for\n                                               // data in the $shared_data passed\n                                               // to the constructor. Note that\n                                               // the values in $shared_data are\n                                               // stored in a protected property\n                                               // of $renderer (ie. $renderer-\u003edata\n                                               // whose value is publicly accessible\n                                               // via $renderer-\u003egetData()).\n?\u003e\n```\n\nThe example above can be extended for use-cases where more than one renderer is being used.\n\n\n#### Nesting Renderers\n\nYou can actually pass instances of **\\Rotexsoft\\FileRenderer\\Renderer** to php functions and statements that accept string arguments like **echo**, **sprintf** \u0026 the likes. \n\nThe 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. \n\n**\\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. \n\nThis 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:\n\n- an array containing one or more renderers is passed as the second argument passed to **\\Rotexsoft\\FileRenderer\\Renderer::__construct(...)**\n- calling **\\Rotexsoft\\FileRenderer\\Renderer::setVar($key, $value)** with a second argument that is a renderer or an array of renderers\n- object property assignment via the magic setter **\\Rotexsoft\\FileRenderer\\Renderer::__set($key, $value)** builtin php mechanism\n\nNow let's see how we can leverage this automatic conversion of renderer objects to strings in an application.\n\nAssume you have the four php files below in your application:\n\n`layout.php`\n\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eNesting Renderers Example\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n            \u003c?php echo $layout_content; ?\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n`layout_content.php`\n\n```php\n            \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout.php\u003c/strong\u003e.\u003c/p\u003e\n            \u003c?= $layout_content_1; ?\u003e\n```\n\n`layout_content_1.php`\n\n```php\n            \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content.php\u003c/strong\u003e.\u003c/p\u003e\n            \u003c?= $layout_content_2; ?\u003e\n```\n\n`layout_content_2.php`\n\n```php\n            \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content_1.php\u003c/strong\u003e.\u003c/p\u003e\n```\n\nWe can render them via nesting like so in a file that is in the same folder with the four php files above \n(they could be in any folder, just make sure the correct path is prepended to the file name passed as \nthe first argument to the constructor of the renderer class):\n\n`nesting_tester.php`\n\n```php\n$layout_renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./layout.php');\n$page_renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./layout_content.php');\n$page_renderer2 = new \\Rotexsoft\\FileRenderer\\Renderer('./layout_content_1.php');\n$page_renderer3 = new \\Rotexsoft\\FileRenderer\\Renderer('./layout_content_2.php');\n\n$layout_renderer-\u003elayout_content= $page_renderer;\n$page_renderer-\u003elayout_content_1= $page_renderer2;\n$page_renderer2-\u003elayout_content_2= $page_renderer3;\n\necho $layout_renderer; \n```\n\nWhich results in the output below:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eNesting Renderers Example\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n                        \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout.php\u003c/strong\u003e.\u003c/p\u003e\n                        \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content.php\u003c/strong\u003e.\u003c/p\u003e\n                        \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content_1.php\u003c/strong\u003e.\u003c/p\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nNow let's walk through what just happened.\n\nWe created four renderer objects assigned to **$layout_renderer**, **$page_renderer**,\n**$page_renderer2** and **$page_renderer3** to render **layout.php**, **layout_content.php**, \n**layout_content_1.php** and **layout_content_2.php** respectively.\n\n```php\n$layout_renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./layout.php');\n$page_renderer = new \\Rotexsoft\\FileRenderer\\Renderer('./layout_content.php');\n$page_renderer2 = new \\Rotexsoft\\FileRenderer\\Renderer('./layout_content_1.php');\n$page_renderer3 = new \\Rotexsoft\\FileRenderer\\Renderer('./layout_content_2.php');\n```\n\nWe then did the following assignments:\n\n* 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**\n\n```php\n$layout_renderer-\u003elayout_content= $page_renderer;\n```\n\n* 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**\n\n```php\n$page_renderer-\u003elayout_content_1= $page_renderer2;\n```\n\n* 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**\n\n```php\n$page_renderer2-\u003elayout_content_2= $page_renderer3;\n```\n\nWe finally execute the **echo** statement with **$layout_renderer** as its argument:\n\n```php\necho $layout_renderer; \n```\n\nThis leads to php automatically executing **$layout_renderer-\u003e__toString()**, which leads to the \nrendering of **layout.php** which has the echo statement below inside it\n\n```php\n\u003c?php echo $layout_content; ?\u003e \n```\n\n**$layout_content** in **layout.php** shown in the echo statement snippet above is actually referencing the renderer assigned to \n**$page_renderer** in **nesting_tester.php** earlier above. \n\nThis echo statement in **layout.php** leads to php automatically executing **$layout_content-\u003e__toString()**, \nwhich leads to the rendering of **layout_content.php** which has the echo statement below inside it\n\n```php\n\u003c?= $layout_content_1; ?\u003e\n```\n\n**$layout_content_1** in **layout_content.php** shown in the echo statement snippet above is actually referencing the renderer assigned to \n**$page_renderer2** in **nesting_tester.php** earlier above. \n\nThis echo statement in **layout_content.php** leads to php automatically executing **$layout_content_1-\u003e__toString()**, \nwhich leads to the rendering of **layout_content_1.php** which has the echo statement below inside it\n\n```php\n\u003c?= $layout_content_2; ?\u003e\n```\n**$layout_content_2** in **layout_content_1.php** shown in the echo statement snippet above is actually referencing the renderer assigned to \n**$page_renderer3** in **nesting_tester.php** earlier above. \n\nThis echo statement in **layout_content_1.php** leads to php automatically executing **$layout_content_2-\u003e__toString()**, \nwhich 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.\n\n```php\n            \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content_1.php\u003c/strong\u003e.\u003c/p\u003e\n```\n\nThis all leads to \n1. the output of rendering **layout_content_2.php** being returned back to the echo statement in **layout_content_1.php**,\n2. the output of rendering **layout_content_1.php** is in turn returned back to the echo statement in **layout_content.php**, \n3. the output of rendering **layout_content.php** is in turn returned back to the echo statement in **layout.php** \n4. and finally all these outputs  get combined inside in **layout.php** and  printed out to the screen as the output below (earlier shown above):\n\n```php\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003ctitle\u003eNesting Renderers Example\u003c/title\u003e\n        \u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv\u003e\n                        \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout.php\u003c/strong\u003e.\u003c/p\u003e\n                        \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content.php\u003c/strong\u003e.\u003c/p\u003e\n                        \u003cp\u003eThis is a sample page to be injected into \u003cstrong\u003elayout_content_1.php\u003c/strong\u003e.\u003c/p\u003e\n        \u003c/div\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\nThat's how you nest renderers and render their combined output. \n\n\u003e Note: with nesting, you have to supply all the information needed to render each file to the constructor of the \nrenderer class when creating each renderer object. See **\\Rotexsoft\\FileRenderer\\Renderer::__construct(...)** for\nmore details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frotexsoft%2Ffile-renderer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frotexsoft%2Ffile-renderer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frotexsoft%2Ffile-renderer/lists"}