{"id":13704081,"url":"https://github.com/phly/phly_mustache","last_synced_at":"2025-04-09T18:23:54.424Z","repository":{"id":57039000,"uuid":"870109","full_name":"phly/phly_mustache","owner":"phly","description":"PHP 5.3 Mustache implementation","archived":false,"fork":false,"pushed_at":"2015-09-02T17:14:10.000Z","size":1484,"stargazers_count":122,"open_issues_count":1,"forks_count":11,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-12-20T12:02:17.930Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phly.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}},"created_at":"2010-08-29T14:16:15.000Z","updated_at":"2023-05-18T17:21:27.000Z","dependencies_parsed_at":"2022-08-23T23:31:00.694Z","dependency_job_id":null,"html_url":"https://github.com/phly/phly_mustache","commit_stats":null,"previous_names":["weierophinney/phly_mustache"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fphly_mustache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fphly_mustache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fphly_mustache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fphly_mustache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phly","download_url":"https://codeload.github.com/phly/phly_mustache/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248086155,"owners_count":21045286,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-08-02T21:01:03.961Z","updated_at":"2025-04-09T18:23:54.399Z","avatar_url":"https://github.com/phly.png","language":"PHP","funding_links":[],"categories":["模板 Templating","目录"],"sub_categories":["模板 Templating"],"readme":"# Phly\\Mustache\n\n\u003e # MOVED!\n\u003e\n\u003e This package has moved to [phly/phly-mustache](https://github.com/phly/phly-mustache),\n\u003e and the package name has changed to `phly/phly-mustache`.\n\u003e\n\u003e I have updated packagist to mark `phly/mustache` as abandoned and to point\n\u003e users to the new package name. All previous releases are available under the\n\u003e old package name, and have the same functionality. The new package contains\n\u003e the v2 code, however, which has never been released under the old name.\n\nPhly\\Mustache is a Mustache (http://mustache.github.com) implementation written\nfor PHP 5.3+. It conforms to the principles of mustache, and allows for\nextension of the format via pragmas.\n\nFor full documentation, please visit \n[ReadTheDocs](http://phly-mustache.readthedocs.org/).\n\nThe mailing list is at https://groups.google.com/d/forum/phly_mustache\n\nAt this time, Phly\\Mustache has support for the following:\n\n- `PhlyTest\\Mustache\\Mustache`\n  - Renders string templates\n  - Renders file templates\n  - Can use object properties for substitutions\n  - Can use method return value for substitutions\n  - Template may use conditionals\n  - Conditional is skipped if value is false\n  - Conditional is skipped if value is empty\n  - Template iterates arrays\n  - Template iterates traversable objects\n  - Higher order sections render inside out\n  - Template will dereference nested arrays\n  - Template will dereference nested objects\n  - Inverted sections render on empty values\n  - Renders partials\n  - Allows aliasing partials\n  - Escapes standard characters\n  - Triple mustaches prevent escaping\n  - Honors implicit iterator pragma\n  - Allows setting alternate template suffix\n  - Strips comments from rendered output\n  - Allows specifying alternate delimiters\n  - Alternate delimiters set in section only apply to that section\n  - Alternate delimiters apply to child sections\n  - Alternate delimiters do not carry to partials\n  - Pragmas are section specific\n  - Pragmas do not extend to partials\n  - Handles recursive partials\n  - Lexer strips unwanted whitespace from tokens\n  - Array values that refer to p h p built ins should not call them\n  - Object properties that refer to p h p built ins should not call them\n  - Array values that refer to static methods should not call them\n  - String values that refer to functions should not call them\n  - Array values that refer to static methods in array syntax should not call them\n  - Std class as view should not raise error\n  - Dot notation is exanded to sub property of view\n  - With dot notation if subproperty does not exist empty string is rendered\n\n- `PhlyTest\\Mustache\\HierarchicalViews`\n  - Understands hierarchical templates\n  - Placeholders are rendered as unnamed sections\n  - Only placeholders with replacements receive substitutions\n  - Can render multiple placeholders\n  - Can render nested child placeholders\n  - Nested children can render placeholders defined in parent child\n\n- `PhlyTest\\Mustache\\DefaultResolver`\n  - Resolves using mustache suffix by default\n  - Resolves using provided suffix\n  - Resolves using specified directory separator\n  - Uses path stack internally\n\n- `PhlyTest\\Mustache\\Pragma\\SubViews`\n  - Sub view content is captured in parent\n  - Renders nested sub views\n  - Sub view uses parent view when no view provided\n  - Should render sub view returned by closure\n  - Std class composing sub view should not raise error\n\n\nArchitecture\n============\n\nPhly\\Mustache consists of five primary classes:\n\n- Lexer: tokenizes mustache syntax.\n- Renderer: renders a list of tokens, using substitions provided via a view.\n- Pragma: interface for pragmas, which may modify how tokens are handled\n- Resolver: resolves a template name to mustache syntax or tokens.\n- Mustache: facade/gateway class. Tokenizes and renders templates, caches\n  tokens, provides partial aliasing, and acts as primary interface for\n  end-users.\n\nUsage\n=====\nUsage is fairly straightforward:\n\n    include '/path/to/library/Phly/Mustache/_autoload.php';\n    use Phly\\Mustache\\Mustache;\n\n    $mustache = new Mustache();\n    echo $mustache-\u003erender('some-template', $view);\n\nBy default, phly_mustache will look under the current directory for templates\nending with '.mustache'; you can create a stack of directories to search by\nusing the setTemplatePath() method:\n\n    $mustache-\u003esetTemplatePath($path1)\n             -\u003esetTemplatePath($path2);\n\nIn the above, it will search first $path2, then $path1 to resolve the template.\n\nYou may also change the suffix it will use to resolve templates:\n\n    $mustache-\u003esetSuffix('html'); // use '.html' as the suffix\n\nIf your templates use pragmas, you must first add pragma handlers to the\nrenderer. This can be done as follows:\n\n    use Phly\\Mustache\\Pragma\\ImplicitIterator as ImplicitIteratorPragma;\n    $mustache-\u003egetRenderer()-\u003eaddPragma(new ImplicitIteratorPragma());\n    $mustache-\u003erender('template-with-pragma', $view);\n\nViews can be either associative arrays or objects. For objects, any public\nmember, either a property or a method, may be referenced in your template. As an\nexample:\n\n    class View\n    {\n        public $first_name = 'Matthew';\n\n        public $last_name  = \"Weier O'Phinney\";\n\n        public function full_name()\n        {\n            return $this-\u003efirst_name . ' ' . $this-\u003elast_name;\n        }\n    }\n\nAny property (or array key) may also refer to a valid callback; in such cases,\nthe return value of the callback will be used.\n\n    $view = new \\stdClass;\n    $view-\u003efirst_name = 'Matthew';\n    $view-\u003elast_name  = \"Weier O'Phinney\";\n    $view-\u003efull_name  = function() use ($view) {\n        return $view-\u003efirst_name . ' ' . $view-\u003elast_name;\n    };\n\nThe following sections detail unique and/or advanced features of phly_mustache.\n\nAutoloading\n===========\nphly_mustache follows the PSR-0 standard for class naming conventions, meaning\nany PSR-0-compliant class loader will work. To simplify things out of the box,\nthe component contains an \"\\_autoload.php\" file which will register an autoloader\nfor the phly_mustache component with spl_autoload. You can simply include that\nfile, and start using phly_mustache.\n\nHigher Order Sections\n=====================\n\"Higher order sections\" refer to callbacks that return callbacks. As an example,\nconsider the following template:\n\n    {{#bolder}}Hi {{name}}.{{/bolder}}\n\nand the following view:\n    \n    $view = new \\stdClass;\n    $view-\u003ename = 'Tater';\n    $view-\u003ebolder = function() {\n        return function($text, $renderer) {\n            return '\u003cb\u003e' . $renderer($text) . '\u003c/b\u003e';\n        };\n    };\n\nIn this case, the contents of the section, \"Hi {{name}}.\" will be passed as the\nfirst argument to the section, and a callback capable of rendering will be\npassed as the second (this is basically a closure that curries in the current\nRenderer object and calls the appropriate method). This allows you to re-use a\ngiven \"section\" in order to create re-usable capabilities; think of them like\n\"view helpers\" in systems like Zend_View, Solar_View, Savant, etc.\n\nPartials\n========\nPartials are a basic form of inclusion within Mustache; anytime you find you\nhave re-usable bits of templates, move them into a partial, and refer to the\npartial from the parent template.\n\nTypically, you will only reference partials within your templates, using\nstandard syntax:\n\n    {{\u003epartial-name}}\n\nHowever, you may optionally pass a list of partials when rendering. When you do\nso, the list should be a set of alias/template pairs:\n\n    $mustache-\u003erender($template, array(), array(\n        'winnings' =\u003e 'user-winnings',\n    ));\n\nIn the above example, 'winnings' refers to the template\n\"user-winnings.mustache\". Thus, within the $template being rendered, you may\nrefer to the following partial:\n\n    {{\u003ewinnings}}\n\nand it will resolve to the appropriate aliased template.\n\nA few things to remember when using partials:\n\n - The parent template may change tag delimiters, but if you want to use the\n   same delimiters in your partial, you will need to make the same declaration.\n - The parent template may utilize one or more pragmas, but those declarations\n   will not perist to the partial; if you want those pragmas, you must reference\n   them in your partial.\n\nBasically, partials render in their own scope. If you remember that one rule,\nyou should have no problems.\n\nHierarchical Views and Placeholders\n===================================\n\n(Available in versions 1.1.0 and up).\n\nPlaceholders are basically unnamed sections, and are denoted by the combination\nof `{{$name}}` and `{{/name}}`. When encountered by the renderer, any mustache\ncontent within will be rendered as normal mustache content.\n\nPlaceholders are primarily of use with the concept of hierarchical views. These\nare denoted by the combination of `{{\u003cname}}` and `{{/name}}`. When encountered,\nthe template denoted by `name` will be tokenized, and any placeholders that are\ndefined in the content will be used to replace those found in the parent\ntemplate.\n\nAs an example, consider the following parent template, \"super.mustache\":\n\n    \u003chtml\u003e\n    \u003chead\u003e\u003ctitle\u003e{{$title}}Default title{{/title}}\u003c/title\u003e\u003c/head\u003e\n    \u003cbody\u003e\n    \u003cdiv class=\"content\"\u003e\n    {{$content}}Default content of the page{{/content}}\n    \u003c/div\u003e\n    \u003c/body\u003e\n    \u003c/html\u003e\n\nIf rendered by itself, it will result in the following:\n\n    \u003chtml\u003e\n    \u003chead\u003e\u003ctitle\u003eDefault title\u003c/title\u003e\u003c/head\u003e\n    \u003cbody\u003e\n    \u003cdiv class=\"content\"\u003e\n    Default content of the page\n    \u003c/div\u003e\n    \u003c/body\u003e\n    \u003c/html\u003e\n\nNow, consider the following child template, \"sub.mustache\":\n\n    {{\u003csuper}}\n    {{$title}}Profile of {{username}}{{/title}}\n    {{$content}}\n    Here is {{username}}'s profile page\n    {{/content}}\n    {{/super}}\n\nIf we have a view that defines \"username\" as \"Matthew\" and render\n\"sub.mustache\", we'll get the following:\n\n    \u003chtml\u003e\n    \u003chead\u003e\u003ctitle\u003eProfile of Matthew\u003c/title\u003e\u003c/head\u003e\n    \u003cbody\u003e\n    \u003cdiv class=\"content\"\u003e\n    Here is Matthew's profile page\n    \u003c/div\u003e\n    \u003c/body\u003e\n    \u003c/html\u003e\n\nNotice how the child retains the view context of the parent, and that all\nmustache tokens defined in it are rendered as if they were simply another\nmustache template.\n\nHierarchical templates may be nested arbitrarily deep.\n\n(This feature was inspired by https://gist.github.com/1854699)\n\nWhitespace Stripping\n====================\nBecause this is a very literal compiler, whitespace can sometimes be an issue. A\nnumber of measures have been built in to reduce such issues by stripping\nwhitespace (primarily newlines) surrounding certain tokens, but they come at a\nslight performance penalty.\n\nFor markup languages like XML, XHTML or HTML5, you likely will not run into\nissues in the final rendered output. As such, you can optionally disable\nwhitespace stripping:\n\n    $mustache-\u003egetLexer()-\u003edisableStripWhitespace(true);\n\nCaching Tokens\n==============\nTokens from parsed templates may be cached for later usage; alternately, a new\ninstance of phly_mustache may be seeded with cached tokens from a previous\ninstance. \n\nTo get the list of tokens, use the following:\n\n    $tokens = $mustache-\u003egetAllTokens();\n\nThis will return a list of template name/token list pairs, based on the\ntemplates compiled by this instance. You may then seed another instance using\nthe following:\n\n    $mustache-\u003erestoreTokens($tokens);\n\nThis will overwrite any tokens already compiled by that instance.\n\nSince the tokens are template name/token list pairs, you can safely pass them to\narray_merge(), allowing multiple instances of phly_mustache to build up a large\ncache of template tokens. This will greatly improve performance when rendering\ntemplates on subsequent calls -- particularly if you cache the tokens in a\nmemory store such as memcached.\n\nPragmas\n=======\nPragmas are tags of the form:\n\n {{%PRAGMA-NAME option=value}}\n\nwhere options are key/value pairs, and are entirely optional. Pragmas are\nuser-defined, and can be used to extend and/or modify the capabilities of the\nrenderer.\n\nPragmas should implement Phly\\Mustache\\Pragma, which defines methods for\nretrieving the pragma name (used during registration of the pragma, and\nreferenced by templates; this is case sensitive currently), determining whether\nor not the pragma can intercept rendering of a specific token type, and handling\nthe token. \n\nPragmas should be registered _before_ rendering any template that references\nthem. \n\n    $this-\u003emustache-\u003egetRenderer()-\u003eaddPragma($pragmaObject);\n    // ...\n    $this-\u003emustache-\u003erender(/*...*/);\n\nWhen declared in a template, they exist for the duration of the current\nscope, which means:\n\n - If declared in a section, they apply to that section and any child sections\n   *only*\n - If declared for a file, they apply to that file and all child sections *only*\n - Pragmas are never passed on to partials; each partial is rendered with an\n   empty set of pragmas, and must declare any pragmas it requires for\n   appropriate rendering.\n\nFor ideas on how you might use or implement pragmas, examine the pragmas shipped\nwith phly_mustache.\n\nPragmas shipped with phly_mustache\n----------------------------------\n\nIMPLICIT-ITERATOR\nThis pragma allows iteration of indexed arrays or Traversable objects with\nscalar values, with the option of specifying the iterator \"key\" to use within\nthe template. By default, a variable key \".\" will be replaced by the current\nvalue of the iterator.\n\nA sample template:\n\n    {{#some_iterable_data}}\n        {{.}}\n    {{/some_iterable_data}}\n\nTo use an explicit iterator key, specify it via the \"iterator\" option of the\npragma:\n\n    {{%IMPLICIT-ITERATOR iterator=bob}}\n    {{#some_iterable_data}}\n        {{bob}}\n    {{/some_iterable_data}}\n\nSUB-VIEWS\nThe Sub-Views pragma allows you to implement the two-step view pattern using\nMustache. When active, any variable whose value is an instance of\nPhly\\Mustache\\Pragma\\SubView will be substituted by rendering the template and\nview that object encapsulates.\n\nThe SubView class takes a template name and a view as a constructor:\n\n    use Phly\\Mustache\\Pragma\\SubView;\n    $subView = new SubView('some-partial', array('name' =\u003e 'Matthew'));\n\nThat object is then assigned as a value to a view key:\n\n    $view = new \\stdClass;\n    $view-\u003econtent = $subView;\n\nThe template might look like this:\n\n    {{!layout}}\n    {{%SUB-VIEWS}}\n    \u003chtml\u003e\n    \u003cbody\u003e\n        {{content}}\n    \u003c/body\u003e\n    \u003c/html\u003e\n\nand the partial like this:\n\n    {{!some-partial}}\n    Hello, {{name}}!\n\nRendering the view:\n\n    use Phly\\Mustache\\Mustache,\n        Phly\\Mustache\\Pragma\\SubViews;\n    $mustache = new Mustache();\n    $subViews = new SubViews($mustache);\n    $rendered = $mustache-\u003erender('layout', $view);\n\nwill result in:\n\n    \u003chtml\u003e\n    \u003cbody\u003e\n        Hello, Matthew!\n    \u003c/body\u003e\n    \u003c/html\u003e\n\nSub views may be nested, and re-used.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphly%2Fphly_mustache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphly%2Fphly_mustache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphly%2Fphly_mustache/lists"}