Compare commits

..

2 Commits

Author SHA1 Message Date
Simon Wisselink 5c0072430c Add unit test 2021-03-22 10:35:05 +01:00
Simon Wisselink 07de9164b7 Fixed render crash when using inline include with a string template. Fixed #639 2021-03-22 10:27:58 +01:00
927 changed files with 39534 additions and 42120 deletions
+4 -4
View File
@@ -7,13 +7,13 @@
# exclude from git export
/tests export-ignore
/utilities export-ignore
/docker-compose.yml export-ignore
/.github export-ignore
/run_tests_for_all_php_versions.sh export-ignore
/utilities/ export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/make-release.sh export-ignore
/phpunit.sh export-ignore
/phpunit.xml export-ignore
/TODO.md export-ignore
/travis.ini export-ignore
-85
View File
@@ -1,85 +0,0 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
on:
pull_request:
push:
branches:
- 'master'
name: CI
jobs:
tests:
name: Tests
runs-on: ${{ matrix.os }}
env:
PHP_EXTENSIONS: dom, json, libxml, mbstring, pdo_sqlite, soap, xml, xmlwriter
PHP_INI_VALUES: assert.exception=1, zend.assertions=1
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
compiler:
- default
include:
- os: ubuntu-latest
php-version: "8.0"
compiler: jit
- os: ubuntu-latest
php-version: "8.1"
compiler: jit
- os: ubuntu-latest
php-version: "8.2"
compiler: jit
- os: ubuntu-latest
php-version: "8.3"
compiler: jit
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Override PHP ini values for JIT compiler
if: matrix.compiler == 'jit'
run: echo "PHP_INI_VALUES::assert.exception=1, zend.assertions=1, opcache.enable=1, opcache.enable_cli=1, opcache.optimization_level=-1, opcache.jit=1255, opcache.jit_buffer_size=32M" >> $GITHUB_ENV
- name: Install PHP with extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: pcov
extensions: ${{ env.PHP_EXTENSIONS }}
ini-values: ${{ env.PHP_INI_VALUES }}
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v3
with:
path: vendor
key: v5r2-${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
v5r1-${{ runner.os }}-php-${{ matrix.php-version }}-
- name: Install dependencies
uses: php-actions/composer@v6
- name: Run make
run: make -B
- name: Run tests with phpunit
run: php ./vendor/phpunit/phpunit/phpunit
+6 -2
View File
@@ -1,9 +1,13 @@
.idea/
/site
# Smarty
lexer/*.php
lexer/*.php.bak
lexer/*.out
utilies/*.php
# Dev
phpunit*
.phpunit.result.cache
vendor/*
composer.lock
+39
View File
@@ -0,0 +1,39 @@
language: php
os: linux
dist: xenial
install:
- travis_retry composer install
jobs:
include:
- php: 5.3 # Composer and PHPUnit require PHP 5.3.2+ to run, so we cannot test below 5.3
dist: precise # PHP 5.3 is supported only on Precise.
- php: 5.4
dist: trusty # PHP 5.4 is supported only on Trusty.
- php: 5.5
dist: trusty # PHP 5.5 is supported only on Trusty.
- php: 5.6
- php: 7.0
- php: 7.1
- php: 7.2
- php: 7.3
- php: 7.4
- php: nightly
install: travis_retry composer config platform.php 7.4.0 && composer install
fast_finish: true
allow_failures:
- php: nightly # PHP 8 is still in beta
services:
- memcached
- mysql
before_script:
- mysql -e "create database IF NOT EXISTS test;" -uroot
before_install:
- phpenv config-rm xdebug.ini || return 0
script:
- ./phpunit.sh
+4 -232
View File
@@ -6,239 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [5.0.2] - 2024-03-28
- Fix Smarty::assign() not returning $this when called with an array as first parameter [#972](https://github.com/smarty-php/smarty/pull/972)
## [5.0.1] - 2024-03-27
- Fix error in Smarty\Smarty::compileAllTemplates() by including missing FilesystemIterator class [#966](https://github.com/smarty-php/smarty/issues/966)
## [5.0.0] - 2024-03-25
- Fixed that scoped variables would overwrite parent scope [#952](https://github.com/smarty-php/smarty/issues/952)
- Removed publicly accessible `$tpl->_var_stack` variable
### Fixed
- Too many shorthand attributes error when using a modifier as a function with more than 3 parameters in an expression [#949](https://github.com/smarty-php/smarty/issues/949)
### Removed
- Dropped support for undocumented `{time()}` added in v5.0.0 since we already have the documented `{$smarty.now}`
## [5.0.0-rc3] - 2024-02-26
### Added
- PHP8.3 support [#925](https://github.com/smarty-php/smarty/issues/925)
- Backlink to GitHub in docs
- Explain how to do escaping and set-up auto-escaping in docs [#865](https://github.com/smarty-php/smarty/issues/865)
- Link to variable scope page in the documentation for the assign tag [#878](https://github.com/smarty-php/smarty/issues/878)
- Add support for implode, substr and json_encode as modifiers/functions in templates [#939](https://github.com/smarty-php/smarty/issues/939)
- Add template path to CompilerException to enable rich debug features [#935](https://github.com/smarty-php/smarty/issues/935)
### Fixed
- The {debug} tag was broken in v5 [#922](https://github.com/smarty-php/smarty/issues/922)
- Documentation on `{if $x is even by $y}` syntax
- Fix incorrect compilation of expressions when escape_html=true [#930](https://github.com/smarty-php/smarty/pull/930)
## [5.0.0-rc2] - 2023-11-11
### Fixed
- Registered output filters wouldn't run [#899](https://github.com/smarty-php/smarty/issues/899)
- Use of negative numbers in {math} equations [#895](https://github.com/smarty-php/smarty/issues/895)
- Do not auto-html-escape custom function results [#906](https://github.com/smarty-php/smarty/issues/906)
- Fix case-sensitive tag names [#907](https://github.com/smarty-php/smarty/issues/907)
### Removed
- Removed `$smarty->registered_filters` array
## [5.0.0-rc1] - 2023-08-08
### Added
- Added support for PHP8.2
- Added a new way to extend Smarty functionality using `Smarty::addExtension()` or `Smarty::setExtensions()`. Please see the docs for more information.
- Custom tags can accept positional parameters, so you can write a block compiler that support this: `{trans "Jack" "dull boy"}All work and no play makes %s a %s.{/trans}` [#164](https://github.com/smarty-php/smarty/issues/164)
- Full support for ternary operator: `{$test ? $a : $b}` and `{$var ?: $value_if_falsy}` [#881](https://github.com/smarty-php/smarty/issues/881)
- Full support for null coalescing operator: `{$var ?? $value_if_null}` [#882](https://github.com/smarty-php/smarty/issues/882)
### Changed
- All Smarty code is now in the \Smarty namespace. For simple use-cases, you only need to add
`use \Smarty\Smarty;` to your script and everything will work. If you extend Smarty or use
Smarty plug-ins, please review your code to see if they assume specific class or method names.
E.g.: `Smarty_Internal_Template` is now `\Smarty\Template\`, `SmartyException` is now `\Smarty\Exception`.
- Template variable scope bubbling has been simplified and made more consistent.
The global scope now equals the Smarty scope in order to avoid global state side effects. Please read
the documentation for more details.
- Lexers and Parsers PHP files are reliably generated from sources (.y and .plex) using the make file
- Smarty now always runs in multibyte mode, using `symfony/polyfill-mbstring` if required. Please use the
multibyte extension for optimal performance.
- Smarty no longer calls `mb_internal_encoding()` and doesn't check for deprecated `mbstring.func_overload` ini directive [#480](https://github.com/smarty-php/smarty/issues/480)
- Generated `<script>` tags lo longer have deprecated `type="text/javascript"` or `language="Javascript"` attributes [#815](https://github.com/smarty-php/smarty/issues/815)
- Smarty will throw a compiler exception instead of silently ignoring a modifier on a function call, like this: `{include|dot:"x-template-id" file="included.dot.tpl"}` [#526](https://github.com/smarty-php/smarty/issues/526)
- The documentation was largely rewritten
### Deprecated
- `$smarty->getPluginsDir()`
- `$smarty->loadFilter()`
- `$smarty->setPluginsDir()`
- `$smarty->assignGlobal()`
- Using `$smarty->registerFilter()` for registering variable filters will trigger a notice.
### Removed
- Dropped support for PHP7.1
- Removed `$smarty->left_delimiter` and `$smarty->right_delimiter`, use `$smarty->getLeftDelimiter()`/`$smarty->setLeftDelimiter()` and `$smarty->getRightDelimiter()`/`$smarty->setRightDelimiter()`
- Removed support for the `$cache_attrs` parameter for registered plugins
- Removed support for undocumented `{make_nocache}` tag
- Removed support for deprecated `{insert}` tag, the 'insert' plugin type and the associated $smarty->trusted_dir variable
- Removed the undocumented `{block_parent}` and `{parent}` alternatives to `{$smarty.block.parent}`
- Removed the undocumented `{block_child}` and `{child}` alternatives to `{$smarty.block.child}`
- Removed support for loading config files into a non-local scope using `{config_load}` from a template
- Removed `$smarty->autoload_filters` in favor of `$smarty->registerFilter()`
- Removed `$smarty->trusted_dir` and `$smarty->allow_php_templates` since support for executing php scripts from templates has been dropped
- Removed `$smarty->php_functions` and `$smarty->php_modifiers`.
- You can no longer use native PHP-functions or userland functions in your templates without registering them. If you need a function in your templates,
register it first.
- Removed support for `$smarty->getTags()`
- Removed the abandoned `$smarty->direct_access_security` setting
- Dropped support for `$smarty->plugins_dir` and `$smarty->use_include_path`. If you must, use `$smarty->addPluginsDir()` instead,
but it's better to use Smarty::addExtension() to add an extension or Smarty::registerPlugin to
quickly register a plugin using a callback function.
- Removed constants such as SMARTY_DIR to prevent global side effects.
- Removed direct access to `$smarty->template_dir`. Use `$smarty->setTemplateDir()`.
- Removed direct access to `$smarty->cache_dir`. Use `$smarty->setCacheDir()`.
- Removed direct access to `$smarty->compile_dir`. Use `$smarty->setCompileDir()`.
- Removed `$smarty->loadPlugin()`, use `$smarty->registerPlugin()` instead.
- Removed `$smarty->appendByRef()` and `$smarty->assignByRef()`.
- Removed `$smarty->_current_file`
- Removed `$smarty->allow_ambiguous_resources` (ambiguous resources handlers should still work)
### Fixed
- `|strip_tags` does not work if the input is 0 [#890](https://github.com/smarty-php/smarty/issues/890)
## [4.3.2] - 2023-07-19
### Fixed
- `$smarty->muteUndefinedOrNullWarnings()` now also mutes PHP8 warnings for undefined properties
## [4.3.1] - 2023-03-28
### Security
- Fixed Cross site scripting vulnerability in Javascript escaping. This addresses CVE-2023-28447.
### Fixed
- `$smarty->muteUndefinedOrNullWarnings()` now also mutes PHP7 notices for undefined array indexes [#736](https://github.com/smarty-php/smarty/issues/736)
- `$smarty->muteUndefinedOrNullWarnings()` now treats undefined vars and array access of a null or false variables
equivalent across all supported PHP versions
- `$smarty->muteUndefinedOrNullWarnings()` now allows dereferencing of non-objects across all supported PHP versions [#831](https://github.com/smarty-php/smarty/issues/831)
- PHP 8.1 deprecation warnings on null strings in modifiers [#834](https://github.com/smarty-php/smarty/pull/834)
## [4.3.0] - 2022-11-22
### Added
- PHP8.2 compatibility [#775](https://github.com/smarty-php/smarty/pull/775)
### Changed
- Include docs and demo in the releases [#799](https://github.com/smarty-php/smarty/issues/799)
- Using PHP functions as modifiers now triggers a deprecation notice because we will drop support for this in the next major release [#813](https://github.com/smarty-php/smarty/issues/813)
- Dropped remaining references to removed PHP-support in Smarty 4 from docs, lexer and security class. [#816](https://github.com/smarty-php/smarty/issues/816)
- Support umask when writing (template) files and set dir permissions to 777 [#548](https://github.com/smarty-php/smarty/issues/548) [#819](https://github.com/smarty-php/smarty/issues/819)
### Fixed
- Output buffer is now cleaned for internal PHP errors as well, not just for Exceptions [#514](https://github.com/smarty-php/smarty/issues/514)
- Fixed recursion and out of memory errors when caching in complicated template set-ups using inheritance and includes [#801](https://github.com/smarty-php/smarty/pull/801)
- Fixed PHP8.1 deprecation errors in strip_tags
- Fix Variable Usage in Exception message when unable to load subtemplate [#808](https://github.com/smarty-php/smarty/pull/808)
- Fixed PHP8.1 deprecation notices for strftime [#672](https://github.com/smarty-php/smarty/issues/672)
- Fixed PHP8.1 deprecation errors passing null to parameter in trim [#807](https://github.com/smarty-php/smarty/pull/807)
- Adapt Smarty upper/lower functions to be codesafe (e.g. for Turkish locale) [#586](https://github.com/smarty-php/smarty/pull/586)
- Bug fix for underscore and limited length in template name in custom resources [#581](https://github.com/smarty-php/smarty/pull/581)
## [4.2.1] - 2022-09-14
### Security
- Applied appropriate javascript and html escaping in mailto plugin to counter injection attacks [#454](https://github.com/smarty-php/smarty/issues/454)
### Fixed
- Fixed PHP8.1 deprecation notices in modifiers (upper, explode, number_format and replace) [#755](https://github.com/smarty-php/smarty/pull/755) and [#788](https://github.com/smarty-php/smarty/pull/788)
- Fixed PHP8.1 deprecation notices in capitalize modifier [#789](https://github.com/smarty-php/smarty/issues/789)
- Fixed use of `rand()` without a parameter in math function [#794](https://github.com/smarty-php/smarty/issues/794)
- Fixed unselected year/month/day not working in html_select_date [#395](https://github.com/smarty-php/smarty/issues/395)
## [4.2.0] - 2022-08-01
### Fixed
- Fixed problems with smarty_mb_str_replace [#549](https://github.com/smarty-php/smarty/issues/549)
- Fixed second parameter of unescape modifier not working [#777](https://github.com/smarty-php/smarty/issues/777)
### Changed
- Updated HTML of the debug template [#599](https://github.com/smarty-php/smarty/pull/599)
## [4.1.1] - 2022-05-17
### Security
- Prevent PHP injection through malicious block name or include file name. This addresses CVE-2022-29221
### Fixed
- Exclude docs and demo from export and composer [#751](https://github.com/smarty-php/smarty/pull/751)
- PHP 8.1 deprecation notices in demo/plugins/cacheresource.pdo.php [#706](https://github.com/smarty-php/smarty/issues/706)
- PHP 8.1 deprecation notices in truncate modifier [#699](https://github.com/smarty-php/smarty/issues/699)
- Math equation `max(x, y)` didn't work anymore [#721](https://github.com/smarty-php/smarty/issues/721)
- Fix PHP 8.1 deprecated warning when calling rtrim [#743](https://github.com/smarty-php/smarty/pull/743)
- PHP 8.1: fix deprecation in escape modifier [#727](https://github.com/smarty-php/smarty/pull/727)
## [4.1.0] - 2022-02-06
### Added
- PHP8.1 compatibility [#713](https://github.com/smarty-php/smarty/pull/713)
## [4.0.4] - 2022-01-18
### Fixed
- Fixed illegal characters bug in math function security check [#702](https://github.com/smarty-php/smarty/issues/702)
## [4.0.3] - 2022-01-10
### Security
- Prevent evasion of the `static_classes` security policy. This addresses CVE-2021-21408
## [4.0.2] - 2022-01-10
### Security
- Prevent arbitrary PHP code execution through maliciously crafted expression for the math function. This addresses CVE-2021-29454
## [4.0.1] - 2022-01-09
### Security
- Rewrote the mailto function to not use `eval` when encoding with javascript
## [4.0.0] - 2021-11-25
## [4.0.0-rc.0] - 2021-10-13
### Added
- You can now use `$smarty->muteUndefinedOrNullWarnings()` to activate convert warnings about undefined or null template vars to notices when running PHP8
### Changed
- Switch CI from Travis to Github CI
- Updated unit tests to avoid skipped and risky test warnings
### Removed
- Dropped support for PHP7.0 and below, so Smarty now requires PHP >=7.1
- Dropped support for php asp tags in templates (removed from php since php7.0)
- Dropped deprecated API calls that where only accessible through SmartyBC
- Dropped support for {php} and {include_php} tags and embedded PHP in templates. Embedded PHP will now be passed through as is.
- Removed all PHP_VERSION_ID and compare_version checks and conditional code blocks that are now no longer required
- Dropped deprecated SMARTY_RESOURCE_CHAR_SET and SMARTY_RESOURCE_DATE_FORMAT constants
- Dropped deprecated Smarty::muteExpectedErrors and Smarty::unmuteExpectedErrors API methods
- Dropped deprecated $smarty->getVariable() method. Use $smarty->getTemplateVars() instead.
- $smarty->registerResource() no longer accepts an array of callback functions
## [3.1.40] - 2021-10-13
### Changed
- modifier escape now triggers a E_USER_NOTICE when an unsupported escape type is used https://github.com/smarty-php/smarty/pull/649
### Security
- More advanced javascript escaping to handle https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements thanks to m-haritonov
### Fixed
- Fixed render crash when using inline include with a string template https://github.com/smarty-php/smarty/issues/639
## [3.1.39] - 2021-02-17
@@ -1895,7 +1667,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
27.09.2011
- bugfix possible warning "attempt to modify property of non-object" in {section} (issue #34)
- added chaining to \Smarty\Data so $smarty->assign('a',1)->assign('b',2); is possible now
- added chaining to Smarty_Internal_Data so $smarty->assign('a',1)->assign('b',2); is possible now
- bugfix remove race condition when a custom resource did change timestamp during compilation
- bugfix variable property did not work on objects variable in template
- bugfix smarty_make_timestamp() failed to process DateTime objects properly
@@ -2230,7 +2002,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- optimize smarty_modified_escape for hex, hexentity, decentity.
28/12/2010
- changed $tpl_vars, $config_vars and $parent to belong to \Smarty\Data
- changed $tpl_vars, $config_vars and $parent to belong to Smarty_Internal_Data
- added Smarty::registerCacheResource() for dynamic cache resource object registration
27/12/2010
+31
View File
@@ -0,0 +1,31 @@
Starting with Smarty 3.1.21 Composer has been configured to load the packages from github.
*******************************************************************************
* *
* NOTE: Because of this change you must clear your local composer cache with *
* the "composer clearcache" command *
* *
*******************************************************************************
To get the latest stable version use
"require": {
"smarty/smarty": "~3.1"
}
in your composer.json file.
To get the trunk version use
"require": {
"smarty/smarty": "~3.1@dev"
}
The "smarty/smarty" package will start at libs/.... subfolder.
To retrieve the development and documentation folders add
"require-dev": {
"smarty/smarty-dev": "~3.1@dev"
}
If you are using (include) the composer generated autoloader.php which is located
in the /vendor folder it is no longer needed to require the Smarty.class.php file.
-119
View File
@@ -1,119 +0,0 @@
# Contributing to Smarty
First off, thanks for taking the time to contribute! ❤️
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> - Star the project
> - Tell a friend about it
> - Refer this project in your project's readme
> - Mention the project at local meetups and tell your friends/colleagues
## I Have a Question
> If you want to ask a question, we assume that you have read the available [Documentation](https://smarty-php.github.io/smarty).
Before you ask a question, it is best to search for existing [Issues](https://github.com/smarty-php/smarty/issues) that might help you.
In case you have found a suitable issue and still need clarification, you can write your question in this issue.
It is also advisable to search the internet for answers first.
If you then still feel the need to ask a question and need clarification, we recommend the following:
- [Open an Issue](https://github.com/smarty-php/smarty/issues/new).
- Provide as much context as you can about what you're running into.
- Provide Smarty and PHP versions
We will then take care of the issue as soon as possible.
## I Want To Contribute
> ### Legal Notice
> When contributing to this project, you must agree that you have authored 100% of the content,
> that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
### Reporting Bugs
#### Before Submitting a Bug Report
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to
investigate carefully, collect information and describe the issue in detail in your report. Please complete the
following steps in advance to help us fix any potential bug as fast as possible.
- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side. (Make sure that you have read the [documentation](https://smarty-php.github.io/smarty). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/smarty-php/smarty/issues?q=label%3Abug).
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
- Collect information about the bug:
- For an Exception: please provide the Stack trace
- OS (Windows, Linux, macOS)
- PHP version
- Smarty version
- A minimal snippet of (your) code that triggers the bug
- Expected output versus actual output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
#### How Do I Submit a Good Bug Report?
> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public.
> For sensitive bugs, please see [SECURITY.md](SECURITY.md).
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
- Open an [Issue](https://github.com/smarty-php/smarty/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section.
Once it's filed:
- The project team will label the issue accordingly.
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced.
- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be implemented by someone.
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for CONTRIBUTING.md, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
#### Before Submitting an Enhancement
- Make sure that you are using the latest version.
- Read the [documentation](https://smarty-php.github.io/smarty) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/smarty-php/smarty/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
#### How Do I Submit a Good Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://github.com/smarty-php/smarty/issues).
- Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you.
- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
- **Explain why this enhancement would be useful** to most CONTRIBUTING.md users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
### Improving The Documentation
The [docs](docs/index.md) are written in markdown, configured in [mkdocs.yml](mkdocs.yml) and published
to [GitHub pages](https://smarty-php.github.io/smarty) using [mkdocs](https://www.mkdocs.org/) and [mike](https://github.com/jimporter/mike).
To preview the docs while you are writing, run:
```bash
mkdocs serve
```
This should launch a local web server and give you a link to open in your browser.
When you are finished, commit your changes and provide a [Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
#### Publishing the docs
If you are a maintainer, you can publish the document using [mike](https://github.com/jimporter/mike). Make sure you provide the correct version.
```bash
mike deploy 5.x
```
## Attribution
This guide is based on the **contributing.md**. [Make your own](https://contributing.md/)!
+91
View File
@@ -0,0 +1,91 @@
3.1.3"
New tags for inheritance parent and chilD
{parent} == {$smarty.block.parent}
{child} == {$smarty.block.child}
Both tags support the assign attribute like
{child assign=foo}
3.1.31
New tags for inheritance parent and child
{block_parent} == {$smarty.block.parent}
{block_child} == {$smarty.block.child}
Since 3.1.28 you can mix inheritance by extends resource with the {extends} tag.
A template called by extends resource can extend a subtemplate or chain buy the {extends} tag.
Since 3.1.31 this feature can be turned off by setting the new Smarty property Smarty::$extends_recursion to false.
3.1.28
Starting with version 3.1.28 template inheritance is no longer a compile time process.
All {block} tag parent/child relations are resolved at run time.
This does resolve all known existing restrictions (see below).
The $smarty::$inheritance_merge_compiled_includes property has been removed.
Any access to it is ignored.
New features:
Any code outside root {block} tags in child templates is now executed but any output will be ignored.
{extends 'foo.tpl'}
{$bar = 'on'} // assigns variable $bar seen in parent templates
{block 'buh'}{/block}
{extends 'foo.tpl'}
{$bar} // the output of variable bar is ignored
{block 'buh'}{/block}
{block} tags can be dynamically en/disabled by conditions.
{block 'root'}
{if $foo}
{block 'v1'}
....
{/block}
{else}
{block 'v1'}
....
{/block}
{/if}
{/block}
{block} tags can have variable names.
{block $foo}
....
{/block}
Starting with 3.1.28 you can mix inheritance by extends resource with the {extends} tag.
A template called by extends resource can extend a subtemplate or chain buy the {extends} tag.
NOTE There is a BC break. If you used the extends resource {extends} tags have been ignored.
THE FOLLOWING RESTRICTIONS ARE NO LONGER EXISTING:
In Smarty 3.1 template inheritance is a compile time process. All the extending of {block} tags
is done at compile time and the parent and child templates are compiled in a single compiled template.
{include} subtemplate could also {block} tags. Such subtemplate could not compiled by it's own because
it could be used in other context where the {block} extended with a different result. For that reasion
the compiled code of {include} subtemplates gets also merged in compiled inheritance template.
Merging the code into a single compile template has some drawbacks.
1. You could not use variable file names in {include} Smarty would use the {include} of compilation time.
2. You could not use individual compile_id in {include}
3. Separate caching of subtemplate was not possible
4. Any change of the template directory structure between calls was not necessarily seen.
Starting with 3.1.15 some of the above conditions got checked and resulted in an exception. It turned out
that a couple of users did use some of above and now got exceptions.
To resolve this starting with 3.1.16 there is a new configuration parameter $inheritance_merge_compiled_includes.
For most backward compatibility its default setting is true.
With this setting all {include} subtemplate will be merge into the compiled inheritance template, but the above cases
could be rejected by exception.
If $smarty->inheritance_merge_compiled_includes = false; {include} subtemplate will not be merged.You must now manually merge all {include} subtemplate which do contain {block} tags. This is done by setting the "inline" option.
{include file='foo.bar' inline}
1. In case of a variable file name like {include file=$foo inline} you must use the variable in a compile_id $smarty->compile_id = $foo;
2. If you use individual compile_id in {include file='foo.tpl' compile_id=$bar inline} it must be used in the global compile_id as well $smarty->compile_id = $bar;
3. If call templates with different template_dir configurations and a parent could same named child template from different folders
you must make the folder name part of the compile_id.
-19
View File
@@ -1,19 +0,0 @@
all: lexers parsers
lexers: src/Lexer/ConfigfileLexer.php src/Lexer/TemplateLexer.php
parsers: src/Parser/ConfigfileParser.php src/Parser/TemplateParser.php
src/Lexer/ConfigfileLexer.php: src/Lexer/ConfigfileLexer.plex
php ./utilities/make-lexer.php src/Lexer/ConfigfileLexer.plex src/Lexer/ConfigfileLexer.php
src/Lexer/TemplateLexer.php: src/Lexer/TemplateLexer.plex
php ./utilities/make-lexer.php src/Lexer/TemplateLexer.plex src/Lexer/TemplateLexer.php
src/Parser/ConfigfileParser.php: src/Parser/ConfigfileParser.y
php ./utilities/make-parser.php src/Parser/ConfigfileParser.y src/Parser/ConfigfileParser.php
src/Parser/TemplateParser.php: src/Parser/TemplateParser.y
php ./utilities/make-parser.php src/Parser/TemplateParser.y src/Parser/TemplateParser.php
clean:
rm -f src/Lexer/ConfigfileLexer.php src/Lexer/TemplateLexer.php src/Parser/ConfigfileParser.php src/Parser/TemplateParser.php
+291
View File
@@ -0,0 +1,291 @@
This file contains a brief description of new features which have been added to Smarty 3.1
Smarty 3.1.33-dev
Variable capture name in Smarty special variable
================================================
{$smarty.capture.$foo} can now be used to access the content of a named
capture block
Smarty 3.1.32
New tags for inheritance parent and child
=========================================
{parent} == {$smarty.block.parent}
{child} == {$smarty.block.child}
Both tags support the assign attribute like
{child assign=foo}
Deprecate functions Smarty::muteExpectedErrors() and Smarty::unmuteExpectedErrors()
===================================================================================
These functions to start a special error handler are no longer needed as Smarty does
no longer use error suppression like @filemtime().
For backward compatibility the functions still can be called.
Using literals containing Smarty's left and right delimiter
===========================================================
New Methods
$smarty->setLiterals(array $literals)
$smarty->addLiterals(array $literals)
to define literals containing Smarty delimiter. This can avoid the need for extreme usage
of {literal} {/literal} tags.
A) Treat '{{' and '}}' as literal
If Smarty::$auto_literal is enabled
{{ foo }}
will be treated now as literal. (This does apply for any number of delimiter repeatations).
However {{foo}} is not an literal but will be interpreted as a recursive Smarty tag.
If you use
$smarty->setLiterals(array('{{','}}'));
{{foo}} is now a literal as well.
NOTE: In the last example nested Smarty tags starting with '{{' or ending with '}}' will not
work any longer, but this should be very very raw occouring restriction.
B) Example 2
Assume your delimiter are '<-' , '->' and '<--' , '-->' shall be literals
$smarty->setLiterals(array('<--','-->'));
The capture buffers can now be accessed as array
================================================
{capture name='foo'}
bah
{\capture}
{capture name='buh'}
blar
{\capture}
{foreach $smarty.capture as $name => $buffer}
....
{/foreach}
Smarty 3.1.31
New tags for inheritance parent and child
=========================================
{block_parent} == {$smarty.block.parent}
{block_child} == {$smarty.block.child}
Smarty 3.1.30
Loop optimization {foreach} and {section}
=========================================
Smarty does optimize the {foreach} and {section} loops by removing code for not needed loop
properties.
The compiler collects needed properties by scanning the current template for $item@property,
$smarty.foreach.name.property and $smarty.section.name.property.
The compiler does not know if additional properties will be needed outside the current template scope.
Additional properties can be generated by adding them with the property attribute.
Example:
index.tpl
{foreach $from as $item properties=[iteration, index]}
{include 'sub.tpl'}
{$item.total}
{/foreach}
sub.tpl
{$item.index} {$item.iteration} {$item.total}
In above example code for the 'total' property is automatically generated as $item.total is used in
index.tpl. Code for 'iteration' and 'index' must be added with properties=[iteration, index].
New tag {make_nocache}
======================
Syntax: {make_nocache $foo}
This tag makes a variable which does exists normally only while rendering the compiled template
available in the cached template for use in not cached expressions.
Expample:
{foreach from=$list item=item}
<li>{$item.name} {make_nocache $item}{if $current==$item.id} ACTIVE{/if}</li>
{/foreach}
The {foreach} loop is rendered while processing the compiled template, but $current is a nocache
variable. Normally the {if $current==$item.id} would fail as the $item variable is unknown in the cached template. {make_nocache $item} does make the current $item value known in thee cached template.
{make_nocache} is ignored when caching is disabled or the variable does exists as nocache variable.
NOTE: if the variable value does contain objects these must have the __set_state method implemented.
Scope Attributes
================
The scope handling has been updated to cover all cases of variable assignments in templates.
The tags {assign}, {append} direct assignments like {$foo = ...}, {$foo[...]= ...} support
the following optional scope attributes:
scope='parent' - the variable will be assigned in the current template and if the template
was included by {include} the calling template
scope='tpl_root' - the variable will be assigned in the outermost root template called by $smarty->display()
or $smarty->fetch() and is bubbled up all {include} sub-templates to the current template.
scope='smarty' - the variable will be assigned in the Smarty object and is bubbled up all {include} sub-templates
to the current template.
scope='global' - the variable will be assigned as Smarty object global variable and is bubbled up all {include}
sub-templates to the current template.
scope='root' - the variable will be assigned if a data object was used for variable definitions in the data
object or in the Smarty object otherwise and is bubbled up all {include} sub-templates to the
current template.
scope='local' - this scope has only a meaning if the tag is called within a template {function}.
The variable will be assigned in the local scope of the template function and the
template which did call the template function.
The {config_load} tag supports all of the above except the global scope.
The scope attribute can be used also with the {include} tag.
Supported scope are parent, tpl_root, smarty, global and root.
A scope used together with the {include} tag will cause that with some exceptions any variable
assignment within that sub-template will update/assign the variable in other scopes according
to the above rules. It does include also variables assigned by plugins, tags supporting the assign=foo attribute and direct assignments in {if} and {while} like {if $foo=$bar}.
Excluded are the key and value variables of {foreach}, {for} loop variables , variables passed by attributes
in {include} and direct increments/decrements like {$foo++}, {$foo--}
Note: The scopes should be used only to the extend really need. If a variable value assigned in an included
sub-template should be returned to the calling sub-template just use {$foo='bar' scope='parent'}.
Use scopes only with variables for which it's realy needed. Avoid general scope settings with the
{include} tag as it can have a performance impact.
The {assign}, {append}, {config_load} and {$foo...=...} tags have a new option flag 'noscope'.Thi
Example: {$foo='bar' noscope} This will assign $foo only in the current template and any scope settings
at {include} is ignored.
Caching
=======
Caching does now observe the template_dir setting and will create separate cache files if required
Compiled Templates
==================
The template_dir setting is now encoded in the uid of the file name.
The content of the compiled template may depend on the template_dir search order
{include .... inline} is used or $smarty->merge_compiled_includes is enabled
APC
===
If APC is enabled force an apc_compile_file() when compiled or cached template was updated
Smarty 3.1.28
OPCACHE
=======
Smarty does now invalidate automatically updated and cleared compiled or cached template files in OPCACHE.
Correct operation is no longer dependent on OPCACHE configuration settings.
Template inheritance
====================
Template inheritance is now processed in run time.
See the INHERITANCE_RELEASE_NOTES
Modifier regex_replace
======================
An optional limit parameter was added
fetch() and display()
=====================
The fetch() and display() methods of the template object accept now optionally the same parameter
as the corresponding Smarty methods to get the content of another template.
Example:
$template->display(); Does display template of template object
$template->display('foo.tpl'); Does display template 'foo.bar'
File: resource
==============
Multiple template_dir entries can now be selected by a comma separated list of indices.
The template_dir array is searched in the order of the indices. (Could be used to change the default search order)
Example:
$smarty->display('[1],[0]foo.bar');
Filter support
==============
Optional filter names
An optional filter name was added to $smarty->registerFilter(). It can be used to unregister a filter by name.
- $smarty->registerFilter('output', $callback, 'name');
$smarty->unregister('output', 'name');
Closures
$smarty->registerFilter() does now accept closures.
- $smarty->registerFilter('pre', function($source) {return $source;});
If no optional filter name was specified it gets the default name 'closure'.
If you register multiple closures register each with a unique filter name.
- $smarty->registerFilter('pre', function($source) {return $source;}, 'closure_1');
- $smarty->registerFilter('pre', function($source) {return $source;}, 'closure_2');
Smarty 3.1.22
Namespace support within templates
==================================
Within templates you can now use namespace specifications on:
- Constants like foo\bar\FOO
- Class names like foo\bar\Baz::FOO, foo\bar\Baz::$foo, foo\bar\Baz::foo()
- PHP function names like foo\bar\baz()
Security
========
- disable special $smarty variable -
The Smarty_Security class has the new property $disabled_special_smarty_vars.
It's an array which can be loaded with the $smarty special variable names like
'template_object', 'template', 'current_dir' and others which will be disabled.
Note: That this security check is performed at compile time.
- limit template nesting -
Property $max_template_nesting of Smarty_Security does set the maximum template nesting level.
The main template is level 1. The nesting level is checked at run time. When the maximum will be exceeded
an Exception will be thrown. The default setting is 0 which does disable this check.
- trusted static methods -
The Smarty_Security class has the new property $trusted_static_methods to restrict access to static methods.
It's an nested array of trusted class and method names.
Format:
array (
'class_1' => array('method_1', 'method_2'), // allowed methods
'class_2' => array(), // all methods of class allowed
)
To disable access for all methods of all classes set $trusted_static_methods = null;
The default value is an empty array() which does enables all methods of all classes, but for backward compatibility
the setting of $static_classes will be checked.
Note: That this security check is performed at compile time.
- trusted static properties -
The Smarty_Security class has the new property $trusted_static_properties to restrict access to static properties.
It's an nested array of trusted class and property names.
Format:
array (
'class_1' => array('prop_1', 'prop_2'), // allowed properties listed
'class_2' => array(), // all properties of class allowed
}
To disable access for all properties of all classes set $trusted_static_properties = null;
The default value is an empty array() which does enables all properties of all classes, but for backward compatibility
the setting of $static_classes will be checked.
Note: That this security check is performed at compile time.
- trusted constants .
The Smarty_Security class has the new property $trusted_constants to restrict access to constants.
It's an array of trusted constant names.
Format:
array (
'SMARTY_DIR' , // allowed constant
}
If the array is empty (default) the usage of constants can be controlled with the
Smarty_Security::$allow_constants property (default true)
Compiled Templates
==================
Smarty does now automatically detects a change of the $merge_compiled_includes and $escape_html
property and creates different compiled templates files depending on the setting.
Same applies to config files and the $config_overwrite, $config_booleanize and
$config_read_hidden properties.
Debugging
=========
The layout of the debug window has been changed for better readability
New class constants
Smarty::DEBUG_OFF
Smarty::DEBUG_ON
Smarty::DEBUG_INDIVIDUAL
have been introduced for setting the $debugging property.
Smarty::DEBUG_INDIVIDUAL will create for each display() and fetch() call an individual debug window.
+575
View File
@@ -0,0 +1,575 @@
Smarty 3.x
Author: Monte Ohrt <monte at ohrt dot com >
Author: Uwe Tews
AN INTRODUCTION TO SMARTY 3
NOTICE FOR 3.1 release:
Please see the SMARTY_3.1_NOTES.txt file that comes with the distribution.
NOTICE for 3.0.5 release:
Smarty now follows the PHP error_reporting level by default. If PHP does not mask E_NOTICE and you try to access an unset template variable, you will now get an E_NOTICE warning. To revert to the old behavior:
$smarty->error_reporting = E_ALL & ~E_NOTICE;
NOTICE for 3.0 release:
IMPORTANT: Some API adjustments have been made between the RC4 and 3.0 release.
We felt it is better to make these now instead of after a 3.0 release, then have to
immediately deprecate APIs in 3.1. Online documentation has been updated
to reflect these changes. Specifically:
---- API CHANGES RC4 -> 3.0 ----
$smarty->register->*
$smarty->unregister->*
$smarty->utility->*
$samrty->cache->*
Have all been changed to local method calls such as:
$smarty->clearAllCache()
$smarty->registerFoo()
$smarty->unregisterFoo()
$smarty->testInstall()
etc.
Registration of function, block, compiler, and modifier plugins have been
consolidated under two API calls:
$smarty->registerPlugin(...)
$smarty->unregisterPlugin(...)
Registration of pre, post, output and variable filters have been
consolidated under two API calls:
$smarty->registerFilter(...)
$smarty->unregisterFilter(...)
Please refer to the online documentation for all specific changes:
http://www.smarty.net/documentation
----
The Smarty 3 API has been refactored to a syntax geared
for consistency and modularity. The Smarty 2 API syntax is still supported, but
will throw a deprecation notice. You can disable the notices, but it is highly
recommended to adjust your syntax to Smarty 3, as the Smarty 2 syntax must run
through an extra rerouting wrapper.
Basically, all Smarty methods now follow the "fooBarBaz" camel case syntax. Also,
all Smarty properties now have getters and setters. So for example, the property
$smarty->cache_dir can be set with $smarty->setCacheDir('foo/') and can be
retrieved with $smarty->getCacheDir().
Some of the Smarty 3 APIs have been revoked such as the "is*" methods that were
just duplicate functions of the now available "get*" methods.
Here is a rundown of the Smarty 3 API:
$smarty->fetch($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->display($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->isCached($template, $cache_id = null, $compile_id = null)
$smarty->createData($parent = null)
$smarty->createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
$smarty->enableSecurity()
$smarty->disableSecurity()
$smarty->setTemplateDir($template_dir)
$smarty->addTemplateDir($template_dir)
$smarty->templateExists($resource_name)
$smarty->loadPlugin($plugin_name, $check = true)
$smarty->loadFilter($type, $name)
$smarty->setExceptionHandler($handler)
$smarty->addPluginsDir($plugins_dir)
$smarty->getGlobal($varname = null)
$smarty->getRegisteredObject($name)
$smarty->getDebugTemplate()
$smarty->setDebugTemplate($tpl_name)
$smarty->assign($tpl_var, $value = null, $nocache = false)
$smarty->assignGlobal($varname, $value = null, $nocache = false)
$smarty->assignByRef($tpl_var, &$value, $nocache = false)
$smarty->append($tpl_var, $value = null, $merge = false, $nocache = false)
$smarty->appendByRef($tpl_var, &$value, $merge = false)
$smarty->clearAssign($tpl_var)
$smarty->clearAllAssign()
$smarty->configLoad($config_file, $sections = null)
$smarty->getVariable($variable, $_ptr = null, $search_parents = true, $error_enable = true)
$smarty->getConfigVariable($variable)
$smarty->getStreamVariable($variable)
$smarty->getConfigVars($varname = null)
$smarty->clearConfig($varname = null)
$smarty->getTemplateVars($varname = null, $_ptr = null, $search_parents = true)
$smarty->clearAllCache($exp_time = null, $type = null)
$smarty->clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
$smarty->registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = array())
$smarty->registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
$smarty->registerFilter($type, $function_name)
$smarty->registerResource($resource_type, $function_names)
$smarty->registerDefaultPluginHandler($function_name)
$smarty->registerDefaultTemplateHandler($function_name)
$smarty->unregisterPlugin($type, $tag)
$smarty->unregisterObject($object_name)
$smarty->unregisterFilter($type, $function_name)
$smarty->unregisterResource($resource_type)
$smarty->compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
$smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
$smarty->testInstall()
// then all the getters/setters, available for all properties. Here are a few:
$caching = $smarty->getCaching(); // get $smarty->caching
$smarty->setCaching(true); // set $smarty->caching
$smarty->setDeprecationNotices(false); // set $smarty->deprecation_notices
$smarty->setCacheId($id); // set $smarty->cache_id
$debugging = $smarty->getDebugging(); // get $smarty->debugging
FILE STRUCTURE
The Smarty 3 file structure is similar to Smarty 2:
/libs/
Smarty.class.php
/libs/sysplugins/
internal.*
/libs/plugins/
function.mailto.php
modifier.escape.php
...
A lot of Smarty 3 core functionality lies in the sysplugins directory; you do
not need to change any files here. The /libs/plugins/ folder is where Smarty
plugins are located. You can add your own here, or create a separate plugin
directory, just the same as Smarty 2. You will still need to create your own
/cache/, /templates/, /templates_c/, /configs/ folders. Be sure /cache/ and
/templates_c/ are writable.
The typical way to use Smarty 3 should also look familiar:
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->assign('foo','bar');
$smarty->display('index.tpl');
However, Smarty 3 works completely different on the inside. Smarty 3 is mostly
backward compatible with Smarty 2, except for the following items:
*) Smarty 3 is PHP 5 only. It will not work with PHP 4.
*) The {php} tag is disabled by default. Enable with $smarty->allow_php_tag=true.
*) Delimiters surrounded by whitespace are no longer treated as Smarty tags.
Therefore, { foo } will not compile as a tag, you must use {foo}. This change
Makes Javascript/CSS easier to work with, eliminating the need for {literal}.
This can be disabled by setting $smarty->auto_literal = false;
*) The Smarty 3 API is a bit different. Many Smarty 2 API calls are deprecated
but still work. You will want to update your calls to Smarty 3 for maximum
efficiency.
There are many things that are new to Smarty 3. Here are the notable items:
LEXER/PARSER
============
Smarty 3 now uses a lexing tokenizer for its parser/compiler. Basically, this
means Smarty has some syntax additions that make life easier such as in-template
math, shorter/intuitive function parameter options, infinite function recursion,
more accurate error handling, etc.
WHAT IS NEW IN SMARTY TEMPLATE SYNTAX
=====================================
Smarty 3 allows expressions almost anywhere. Expressions can include PHP
functions as long as they are not disabled by the security policy, object
methods and properties, etc. The {math} plugin is no longer necessary but
is still supported for BC.
Examples:
{$x+$y} will output the sum of x and y.
{$foo = strlen($bar)} function in assignment
{assign var=foo value= $x+$y} in attributes
{$foo = myfunct( ($x+$y)*3 )} as function parameter
{$foo[$x+3]} as array index
Smarty tags can be used as values within other tags.
Example: {$foo={counter}+3}
Smarty tags can also be used inside double quoted strings.
Example: {$foo="this is message {counter}"}
You can define arrays within templates.
Examples:
{assign var=foo value=[1,2,3]}
{assign var=foo value=['y'=>'yellow','b'=>'blue']}
Arrays can be nested.
{assign var=foo value=[1,[9,8],3]}
There is a new short syntax supported for assigning variables.
Example: {$foo=$bar+2}
You can assign a value to a specific array element. If the variable exists but
is not an array, it is converted to an array before the new values are assigned.
Examples:
{$foo['bar']=1}
{$foo['bar']['blar']=1}
You can append values to an array. If the variable exists but is not an array,
it is converted to an array before the new values are assigned.
Example: {$foo[]=1}
You can use a PHP-like syntax for accessing array elements, as well as the
original "dot" notation.
Examples:
{$foo[1]} normal access
{$foo['bar']}
{$foo['bar'][1]}
{$foo[$x+$x]} index may contain any expression
{$foo[$bar[1]]} nested index
{$foo[section_name]} smarty section access, not array access!
The original "dot" notation stays, and with improvements.
Examples:
{$foo.a.b.c} => $foo['a']['b']['c']
{$foo.a.$b.c} => $foo['a'][$b]['c'] with variable index
{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] with expression as index
{$foo.a.{$b.c}} => $foo['a'][$b['c']] with nested index
note that { and } are used to address ambiguties when nesting the dot syntax.
Variable names themselves can be variable and contain expressions.
Examples:
$foo normal variable
$foo_{$bar} variable name containing other variable
$foo_{$x+$y} variable name containing expressions
$foo_{$bar}_buh_{$blar} variable name with multiple segments
{$foo_{$x}} will output the variable $foo_1 if $x has a value of 1.
Object method chaining is implemented.
Example: {$object->method1($x)->method2($y)}
{for} tag added for looping (replacement for {section} tag):
{for $x=0, $y=count($foo); $x<$y; $x++} .... {/for}
Any number of statements can be used separated by comma as the first
initial expression at {for}.
{for $x = $start to $end step $step} ... {/for}is in the SVN now .
You can use also
{for $x = $start to $end} ... {/for}
In this case the step value will be automatically 1 or -1 depending on the start and end values.
Instead of $start and $end you can use any valid expression.
Inside the loop the following special vars can be accessed:
$x@iteration = number of iteration
$x@total = total number of iterations
$x@first = true on first iteration
$x@last = true on last iteration
The Smarty 2 {section} syntax is still supported.
New shorter {foreach} syntax to loop over an array.
Example: {foreach $myarray as $var}...{/foreach}
Within the foreach loop, properties are access via:
$var@key foreach $var array key
$var@iteration foreach current iteration count (1,2,3...)
$var@index foreach current index count (0,1,2...)
$var@total foreach $var array total
$var@first true on first iteration
$var@last true on last iteration
The Smarty 2 {foreach} tag syntax is still supported.
NOTE: {$bar[foo]} still indicates a variable inside of a {section} named foo.
If you want to access an array element with index foo, you must use quotes
such as {$bar['foo']}, or use the dot syntax {$bar.foo}.
while block tag is now implemented:
{while $foo}...{/while}
{while $x lt 10}...{/while}
Direct access to PHP functions:
Just as you can use PHP functions as modifiers directly, you can now access
PHP functions directly, provided they are permitted by security settings:
{time()}
There is a new {function}...{/function} block tag to implement a template function.
This enables reuse of code sequences like a plugin function. It can call itself recursively.
Template function must be called with the new {call name=foo...} tag.
Example:
Template file:
{function name=menu level=0}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{call name=menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{call name=menu data=$menu}
Generated output:
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
The function tag itself must have the "name" attribute. This name is the tag
name when calling the function. The function tag may have any number of
additional attributes. These will be default settings for local variables.
New {nocache} block function:
{nocache}...{/nocache} will declare a section of the template to be non-cached
when template caching is enabled.
New nocache attribute:
You can declare variable/function output as non-cached with the nocache attribute.
Examples:
{$foo nocache=true}
{$foo nocache} /* same */
{foo bar="baz" nocache=true}
{foo bar="baz" nocache} /* same */
{time() nocache=true}
{time() nocache} /* same */
Or you can also assign the variable in your script as nocache:
$smarty->assign('foo',$something,true); // third param is nocache setting
{$foo} /* non-cached */
$smarty.current_dir returns the directory name of the current template.
You can use strings directly as templates with the "string" resource type.
Examples:
$smarty->display('string:This is my template, {$foo}!'); // php
{include file="string:This is my template, {$foo}!"} // template
VARIABLE SCOPE / VARIABLE STORAGE
=================================
In Smarty 2, all assigned variables were stored within the Smarty object.
Therefore, all variables assigned in PHP were accessible by all subsequent
fetch and display template calls.
In Smarty 3, we have the choice to assign variables to the main Smarty object,
to user-created data objects, and to user-created template objects.
These objects can be chained. The object at the end of a chain can access all
variables belonging to that template and all variables within the parent objects.
The Smarty object can only be the root of a chain, but a chain can be isolated
from the Smarty object.
All known Smarty assignment interfaces will work on the data and template objects.
Besides the above mentioned objects, there is also a special storage area for
global variables.
A Smarty data object can be created as follows:
$data = $smarty->createData(); // create root data object
$data->assign('foo','bar'); // assign variables as usual
$data->config_load('my.conf'); // load config file
$data= $smarty->createData($smarty); // create data object having a parent link to
the Smarty object
$data2= $smarty->createData($data); // create data object having a parent link to
the $data data object
A template object can be created by using the createTemplate method. It has the
same parameter assignments as the fetch() or display() method.
Function definition:
function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null)
The first parameter can be a template name, a smarty object or a data object.
Examples:
$tpl = $smarty->createTemplate('mytpl.tpl'); // create template object not linked to any parent
$tpl->assign('foo','bar'); // directly assign variables
$tpl->config_load('my.conf'); // load config file
$tpl = $smarty->createTemplate('mytpl.tpl',$smarty); // create template having a parent link to the Smarty object
$tpl = $smarty->createTemplate('mytpl.tpl',$data); // create template having a parent link to the $data object
The standard fetch() and display() methods will implicitly create a template object.
If the $parent parameter is not specified in these method calls, the template object
is will link back to the Smarty object as it's parent.
If a template is called by an {include...} tag from another template, the
subtemplate links back to the calling template as it's parent.
All variables assigned locally or from a parent template are accessible. If the
template creates or modifies a variable by using the {assign var=foo...} or
{$foo=...} tags, these new values are only known locally (local scope). When the
template exits, none of the new variables or modifications can be seen in the
parent template(s). This is same behavior as in Smarty 2.
With Smarty 3, we can assign variables with a scope attribute which allows the
availablility of these new variables or modifications globally (ie in the parent
templates.)
Possible scopes are local, parent, root and global.
Examples:
{assign var=foo value='bar'} // no scope is specified, the default 'local'
{$foo='bar'} // same, local scope
{assign var=foo value='bar' scope='local'} // same, local scope
{assign var=foo value='bar' scope='parent'} // Values will be available to the parent object
{$foo='bar' scope='parent'} // (normally the calling template)
{assign var=foo value='bar' scope='root'} // Values will be exported up to the root object, so they can
{$foo='bar' scope='root'} // be seen from all templates using the same root.
{assign var=foo value='bar' scope='global'} // Values will be exported to global variable storage,
{$foo='bar' scope='global'} // they are available to any and all templates.
The scope attribute can also be attached to the {include...} tag. In this case,
the specified scope will be the default scope for all assignments within the
included template.
PLUGINS
=======
Smarty 3 plugins follow the same coding rules as in Smarty 2.
The main difference is that the template object is now passed in place of the smarty object.
The smarty object can be still be accessed through $template->smarty.
smarty_plugintype_name (array $params, Smarty_Internal_Template $template)
The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty 2 internals.
TEMPLATE INHERITANCE:
=====================
With template inheritance you can define blocks, which are areas that can be
overridden by child templates, so your templates could look like this:
parent.tpl:
<html>
<head>
<title>{block name='title'}My site name{/block}</title>
</head>
<body>
<h1>{block name='page-title'}Default page title{/block}</h1>
<div id="content">
{block name='content'}
Default content
{/block}
</div>
</body>
</html>
child.tpl:
{extends file='parent.tpl'}
{block name='title'}
Child title
{/block}
grandchild.tpl:
{extends file='child.tpl'}
{block name='title'}Home - {$smarty.block.parent}{/block}
{block name='page-title'}My home{/block}
{block name='content'}
{foreach $images as $img}
<img src="{$img.url}" alt="{$img.description}" />
{/foreach}
{/block}
We redefined all the blocks here, however in the title block we used {$smarty.block.parent},
which tells Smarty to insert the default content from the parent template in its place.
The content block was overridden to display the image files, and page-title has also be
overridden to display a completely different title.
If we render grandchild.tpl we will get this:
<html>
<head>
<title>Home - Child title</title>
</head>
<body>
<h1>My home</h1>
<div id="content">
<img src="/example.jpg" alt="image" />
<img src="/example2.jpg" alt="image" />
<img src="/example3.jpg" alt="image" />
</div>
</body>
</html>
NOTE: In the child templates everything outside the {extends} or {block} tag sections
is ignored.
The inheritance tree can be as big as you want (meaning you can extend a file that
extends another one that extends another one and so on..), but be aware that all files
have to be checked for modifications at runtime so the more inheritance the more overhead you add.
Instead of defining the parent/child relationships with the {extends} tag in the child template you
can use the resource as follow:
$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl');
Child {block} tags may optionally have a append or prepend attribute. In this case the parent block content
is appended or prepended to the child block content.
{block name='title' append} My title {/block}
PHP STREAMS:
============
(see online documentation)
VARIBLE FILTERS:
================
(see online documentation)
STATIC CLASS ACCESS AND NAMESPACE SUPPORT
=========================================
You can register a class with optional namespace for the use in the template like:
$smarty->register->templateClass('foo','name\name2\myclass');
In the template you can use it like this:
{foo::method()} etc.
=======================
Please look through it and send any questions/suggestions/etc to the forums.
http://www.phpinsider.com/smarty-forum/viewtopic.php?t=14168
Monte and Uwe
+70 -12
View File
@@ -1,20 +1,78 @@
# Smarty template engine
Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.
# Smarty 3 template engine
[smarty.net](https://www.smarty.net/)
![CI](https://github.com/smarty-php/smarty/workflows/CI/badge.svg)
[![Build Status](https://travis-ci.org/smarty-php/smarty.svg?branch=master)](https://travis-ci.org/smarty-php/smarty)
## Documentation
Read the [documentation](https://smarty-php.github.io/smarty/) to find out how to use it.
For documentation see
[www.smarty.net/docs/en/](https://www.smarty.net/docs/en/)
## Requirements
Smarty v5 can be run with PHP 7.2 to PHP 8.3.
## Installation
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
Smarty can be run with PHP 5.2 to PHP 7.4.
To get the latest stable version of Smarty use:
```bash
composer require smarty/smarty
````
## Distribution repository
More in the [Getting Started](./docs/getting-started.md) section of the docs.
> Smarty 3.1.28 introduces run time template inheritance
> Read the NEW_FEATURES and INHERITANCE_RELEASE_NOTES file for recent extensions to Smarty 3.1 functionality
Smarty versions 3.1.11 or later are now on github and can be installed with Composer.
The "smarty/smarty" package will start at libs/.... subfolder.
To get the latest stable version of Smarty 3.1 use:
```json
"require": {
"smarty/smarty": "~3.1"
}
```
in your composer.json file.
To get the trunk version use:
```json
"require": {
"smarty/smarty": "~3.1@dev"
}
```
For a specific version use something like:
```json
"require": {
"smarty/smarty": "3.1.19"
}
```
PHPUnit test can be installed by corresponding composer entries like:
```json
"require": {
"smarty/smarty-phpunit": "3.1.19"
}
```
Similar applies for the lexer/parser generator.
```json
"require": {
"smarty/smarty-lexer": "3.1.19"
}
```
Or you could use:
```json
"require": {
"smarty/smarty-dev": "3.1.19"
}
```
Which is a wrapper to install all 3 packages.
Composer can also be used for Smarty2 versions 2.6.24 to 2.6.30.
+7 -8
View File
@@ -2,19 +2,18 @@
## Supported Versions
Smarty currently supports the latest minor version of Smarty 4 and Smarty 5.
Smarty currently supports the latest minor version of Smarty 3 and Smarty 4. (Smarty 4 has not been released yet.)
| Version | Supported |
|---------|--------------------|
| 5.0.x | :white_check_mark: |
| 4.3.x | :white_check_mark: |
| < 4.3 | :x: |
| ------- | ------------------ |
| 4.0.x | :white_check_mark: |
| 3.1.x | :white_check_mark: |
| < 3.1 | :x: |
## Reporting a Vulnerability
If you have discovered a security issue with Smarty, please contact us at mail [at] simonwisselink.nl. Do not
disclose your findings publicly and **PLEASE** do not file an Issue (because that would disclose your findings
publicly.)
If you have discovered a security issue with Smarty, please contact us at mail [at] simonwisselink.nl. Do not
disclose your findings publicly and PLEASE PLEASE do not file an Issue.
We will try to confirm the vulnerability and develop a fix if appropriate. When we release the fix, we will publish
a security release. Please let us know if you want to be credited.
+109
View File
@@ -0,0 +1,109 @@
= Known incompatibilities with Smarty 2 =
== Syntax ==
Smarty 3 API has a new syntax. Much of the Smarty 2 syntax is supported
by a wrapper but deprecated. See the README that comes with Smarty 3 for more
information.
The {$array|@mod} syntax has always been a bit confusing, where an "@" is required
to apply a modifier to an array instead of the individual elements. Normally you
always want the modifier to apply to the variable regardless of its type. In Smarty 3,
{$array|mod} and {$array|@mod} behave identical. It is safe to drop the "@" and the
modifier will still apply to the array. If you really want the modifier to apply to
each array element, you must loop the array in-template, or use a custom modifier that
supports array iteration. Most smarty functions already escape values where necessary
such as {html_options}
== PHP Version ==
Smarty 3 is PHP 5 only. It will not work with PHP 4.
== {php} Tag ==
The {php} tag is disabled by default. The use of {php} tags is
deprecated. It can be enabled with $smarty->allow_php_tag=true.
But if you scatter PHP code which belongs together into several
{php} tags it may not work any longer.
== Delimiters and whitespace ==
Delimiters surrounded by whitespace are no longer treated as Smarty tags.
Therefore, { foo } will not compile as a tag, you must use {foo}. This change
Makes Javascript/CSS easier to work with, eliminating the need for {literal}.
This can be disabled by setting $smarty->auto_literal = false;
== Unquoted Strings ==
Smarty 2 was a bit more forgiving (and ambiguous) when it comes to unquoted strings
in parameters. Smarty3 is more restrictive. You can still pass strings without quotes
so long as they contain no special characters. (anything outside of A-Za-z0-9_)
For example filename strings must be quoted
<source lang="smarty">
{include file='path/foo.tpl'}
</source>
== Extending the Smarty class ==
Smarty 3 makes use of the __construct method for initialization. If you are extending
the Smarty class, its constructor is not called implicitly if the your child class defines
its own constructor. In order to run Smarty's constructor, a call to parent::__construct()
within your child constructor is required.
<source lang="php">
class MySmarty extends Smarty {
function __construct() {
parent::__construct();
// your initialization code goes here
}
}
</source>
== Autoloader ==
Smarty 3 does register its own autoloader with spl_autoload_register. If your code has
an existing __autoload function then this function must be explicitly registered on
the __autoload stack. See http://us3.php.net/manual/en/function.spl-autoload-register.php
for further details.
== Plugin Filenames ==
Smarty 3 optionally supports the PHP spl_autoloader. The autoloader requires filenames
to be lower case. Because of this, Smarty plugin file names must also be lowercase.
In Smarty 2, mixed case file names did work.
== Scope of Special Smarty Variables ==
In Smarty 2 the special Smarty variables $smarty.section... and $smarty.foreach...
had global scope. If you had loops with the same name in subtemplates you could accidentally
overwrite values of parent template.
In Smarty 3 these special Smarty variable have only local scope in the template which
is defining the loop. If you need their value in a subtemplate you have to pass them
as parameter.
<source lang="smarty">
{include file='path/foo.tpl' index=$smarty.section.foo.index}
</source>
== SMARTY_RESOURCE_CHAR_SET ==
Smarty 3 sets the constant SMARTY_RESOURCE_CHAR_SET to utf-8 as default template charset.
This is now used also on modifiers like escape as default charset. If your templates use
other charsets make sure that you define the constant accordingly. Otherwise you may not
get any output.
== newline at {if} tags ==
A \n was added to the compiled code of the {if},{else},{elseif},{/if} tags to get output of newlines as expected by the template source.
If one of the {if} tags is at the line end you will now get a newline in the HTML output.
== trigger_error() ==
The API function trigger_error() has been removed because it did just map to PHP trigger_error.
However it's still included in the Smarty2 API wrapper.
== Smarty constants ==
The constants
SMARTY_PHP_PASSTHRU
SMARTY_PHP_QUOTE
SMARTY_PHP_REMOVE
SMARTY_PHP_ALLOW
have been replaced with class constants
Smarty::PHP_PASSTHRU
Smarty::PHP_QUOTE
Smarty::PHP_REMOVE
Smarty::PHP_ALLOW
+24
View File
@@ -0,0 +1,24 @@
== Smarty2 backward compatibility ==
All Smarty2 specific API functions and deprecated functionality has been moved
to the SmartyBC class.
== {php} Tag ==
The {php} tag is no longer available in the standard Smarty calls.
The use of {php} tags is deprecated and only available in the SmartyBC class.
== {include_php} Tag ==
The {include_php} tag is no longer available in the standard Smarty calls.
The use of {include_php} tags is deprecated and only available in the SmartyBC class.
== php template resource ==
The support of the php template resource is removed.
== $cache_dir, $compile_dir, $config_dir, $template_dir access ==
The mentioned properties can't be accessed directly any longer. You must use
corresponding getter/setters like addConfigDir(), setConfigDir(), getConfigDir()
== obsolete Smarty class properties ==
The following no longer used properties are removed:
$allow_php_tag
$allow_php_template
$deprecation_notices
+306
View File
@@ -0,0 +1,306 @@
Smarty 3.1 Notes
================
Smarty 3.1 is a departure from 2.0 compatibility. Most notably, all
backward compatibility has been moved to a separate class file named
SmartyBC.class.php. If you require compatibility with 2.0, you will
need to use this class.
Some differences from 3.0 are also present. 3.1 begins the journey of
requiring setters/getters for property access. So far this is only
implemented on the five directory properties: template_dir,
plugins_dir, configs_dir, compile_dir and cache_dir. These properties
are now protected, it is required to use the setters/getters instead.
That said, direct property access will still work, however slightly
slower since they will now fall through __set() and __get() and in
turn passed through the setter/getter methods. 3.2 will exhibit a full
list of setter/getter methods for all (currently) public properties,
so code-completion in your IDE will work as expected.
There is absolutely no PHP allowed in templates any more. All
deprecated features of Smarty 2.0 are gone. Again, use the SmartyBC
class if you need any backward compatibility.
Internal Changes
Full UTF-8 Compatibility
The plugins shipped with Smarty 3.1 have been rewritten to fully
support UTF-8 strings if Multibyte String is available. Without
MBString UTF-8 cannot be handled properly. For those rare cases where
templates themselves have to juggle encodings, the new modifiers
to_charset and from_charset may come in handy.
Plugin API and Performance
All Plugins (modifiers, functions, blocks, resources,
default_template_handlers, etc) are now receiving the
Smarty_Internal_Template instance, where they were supplied with the
Smarty instance in Smarty 3.0. *. As The Smarty_Internal_Template
mimics the behavior of Smarty, this API simplification should not
require any changes to custom plugins.
The plugins shipped with Smarty 3.1 have been rewritten for better
performance. Most notably {html_select_date} and {html_select_time}
have been improved vastly. Performance aside, plugins have also been
reviewed and generalized in their API. {html_select_date} and
{html_select_time} now share almost all available options.
The escape modifier now knows the $double_encode option, which will
prevent entities from being encoded again.
The capitalize modifier now know the $lc_rest option, which makes sure
all letters following a capital letter are lower-cased.
The count_sentences modifier now accepts (.?!) as
legitimate endings of a sentence - previously only (.) was
accepted
The new unescape modifier is there to reverse the effects of the
escape modifier. This applies to the escape formats html, htmlall and
entity.
default_template_handler_func
The invocation of $smarty->$default_template_handler_func had to be
altered. Instead of a Smarty_Internal_Template, the fifth argument is
now provided with the Smarty instance. New footprint:
/**
* Default Template Handler
*
* called when Smarty's file: resource is unable to load a requested file
*
* @param string $type resource type (e.g. "file", "string", "eval", "resource")
* @param string $name resource name (e.g. "foo/bar.tpl")
* @param string &$content template's content
* @param integer &$modified template's modification time
* @param Smarty $smarty Smarty instance
* @return string|boolean path to file or boolean true if $content and $modified
* have been filled, boolean false if no default template
* could be loaded
*/
function default_template_handler_func($type, $name, &$content, &$modified, Smarty $smarty) {
if (false) {
// return corrected filepath
return "/tmp/some/foobar.tpl";
} elseif (false) {
// return a template directly
$content = "the template source";
$modified = time();
return true;
} else {
// tell smarty that we failed
return false;
}
}
Stuff done to the compiler
Many performance improvements have happened internally. One notable
improvement is that all compiled templates are now handled as PHP
functions. This speeds up repeated templates tremendously, as each one
calls an (in-memory) PHP function instead of performing another file
include/scan.
New Features
Template syntax
{block}..{/block}
The {block} tag has a new hide option flag. It does suppress the block
content if no corresponding child block exists.
EXAMPLE:
parent.tpl
{block name=body hide} child content "{$smarty.block.child}" was
inserted {block}
In the above example the whole block will be suppressed if no child
block "body" is existing.
{setfilter}..{/setfilter}
The new {setfilter} block tag allows the definition of filters which
run on variable output.
SYNTAX:
{setfilter filter1|filter2|filter3....}
Smarty3 will lookup up matching filters in the following search order:
1. variable filter plugin in plugins_dir.
2. a valid modifier. A modifier specification will also accept
additional parameter like filter2:'foo'
3. a PHP function
{/setfilter} will turn previous filter setting off again.
{setfilter} tags can be nested.
EXAMPLE:
{setfilter filter1}
{$foo}
{setfilter filter2}
{$bar}
{/setfilter}
{$buh}
{/setfilter}
{$blar}
In the above example filter1 will run on the output of $foo, filter2
on $bar, filter1 again on $buh and no filter on $blar.
NOTES:
- {$foo nofilter} will suppress the filters
- These filters will run in addition to filters defined by
registerFilter('variable',...), autoLoadFilter('variable',...) and
defined default modifier.
- {setfilter} will effect only the current template, not included
subtemplates.
Resource API
Smarty 3.1 features a new approach to resource management. The
Smarty_Resource API allows simple, yet powerful integration of custom
resources for templates and configuration files. It offers simple
functions for loading data from a custom resource (e.g. database) as
well as define new template types adhering to the special
non-compiling (e,g, plain php) and non-compile-caching (e.g. eval:
resource type) resources.
See demo/plugins/resource.mysql.php for an example custom database
resource.
Note that old-fashioned registration of callbacks for resource
management has been deprecated but is still possible with SmartyBC.
CacheResource API
In line with the Resource API, the CacheResource API offers a more
comfortable handling of output-cache data. With the
Smarty_CacheResource_Custom accessing databases is made simple. With
the introduction of Smarty_CacheResource_KeyValueStore the
implementation of resources like memcache or APC became a no-brainer;
simple hash-based storage systems are now supporting hierarchical
output-caches.
See demo/plugins/cacheresource.mysql.php for an example custom
database CacheResource.
See demo/plugins/cacheresource.memcache.php for an example custom
memcache CacheResource using the KeyValueStore helper.
Note that old-fashioned registration of $cache_handler is not possible
anymore. As the functionality had not been ported to Smarty 3.0.x
properly, it has been dropped from 3.1 completely.
Locking facilities have been implemented to avoid concurrent cache
generation. Enable cache locking by setting
$smarty->cache_locking = true;
Relative Paths in Templates (File-Resource)
As of Smarty 3.1 {include file="../foo.tpl"} and {include
file="./foo.tpl"} will resolve relative to the template they're in.
Relative paths are available with {include file="..."} and
{extends file="..."}. As $smarty->fetch('../foo.tpl') and
$smarty->fetch('./foo.tpl') cannot be relative to a template, an
exception is thrown.
Addressing a specific $template_dir
Smarty 3.1 introduces the $template_dir index notation.
$smarty->fetch('[foo]bar.tpl') and {include file="[foo]bar.tpl"}
require the template bar.tpl to be loaded from $template_dir['foo'];
Smarty::setTemplateDir() and Smarty::addTemplateDir() offer ways to
define indexes along with the actual directories.
Mixing Resources in extends-Resource
Taking the php extends: template resource one step further, it is now
possible to mix resources within an extends: call like
$smarty->fetch("extends:file:foo.tpl|db:bar.tpl");
To make eval: and string: resources available to the inheritance
chain, eval:base64:TPL_STRING and eval:urlencode:TPL_STRING have been
introduced. Supplying the base64 or urlencode flags will trigger
decoding the TPL_STRING in with either base64_decode() or urldecode().
extends-Resource in template inheritance
Template based inheritance may now inherit from php's extends:
resource like {extends file="extends:foo.tpl|db:bar.tpl"}.
New Smarty property escape_html
$smarty->escape_html = true will autoescape all template variable
output by calling htmlspecialchars({$output}, ENT_QUOTES,
SMARTY_RESOURCE_CHAR_SET).
NOTE:
This is a compile time option. If you change the setting you must make
sure that the templates get recompiled.
New option at Smarty property compile_check
The automatic recompilation of modified templates can now be
controlled by the following settings:
$smarty->compile_check = COMPILECHECK_OFF (false) - template files
will not be checked
$smarty->compile_check = COMPILECHECK_ON (true) - template files will
always be checked
$smarty->compile_check = COMPILECHECK_CACHEMISS - template files will
be checked if caching is enabled and there is no existing cache file
or it has expired
Automatic recompilation on Smarty version change
Templates will now be automatically recompiled on Smarty version
changes to avoide incompatibillities in the compiled code. Compiled
template checked against the current setting of the SMARTY_VERSION
constant.
default_config_handler_func()
Analogous to the default_template_handler_func()
default_config_handler_func() has been introduced.
default_plugin_handler_func()
An optional default_plugin_handler_func() can be defined which gets called
by the compiler on tags which can't be resolved internally or by plugins.
The default_plugin_handler() can map tags to plugins on the fly.
New getters/setters
The following setters/getters will be part of the official
documentation, and will be strongly recommended. Direct property
access will still work for the foreseeable future... it will be
transparently routed through the setters/getters, and consequently a
bit slower.
array|string getTemplateDir( [string $index] )
replaces $smarty->template_dir; and $smarty->template_dir[$index];
Smarty setTemplateDir( array|string $path )
replaces $smarty->template_dir = "foo"; and $smarty->template_dir =
array("foo", "bar");
Smarty addTemplateDir( array|string $path, [string $index])
replaces $smarty->template_dir[] = "bar"; and
$smarty->template_dir[$index] = "bar";
array|string getConfigDir( [string $index] )
replaces $smarty->config_dir; and $smarty->config_dir[$index];
Smarty setConfigDir( array|string $path )
replaces $smarty->config_dir = "foo"; and $smarty->config_dir =
array("foo", "bar");
Smarty addConfigDir( array|string $path, [string $index])
replaces $smarty->config_dir[] = "bar"; and
$smarty->config_dir[$index] = "bar";
array getPluginsDir()
replaces $smarty->plugins_dir;
Smarty setPluginsDir( array|string $path )
replaces $smarty->plugins_dir = "foo";
Smarty addPluginsDir( array|string $path )
replaces $smarty->plugins_dir[] = "bar";
string getCompileDir()
replaces $smarty->compile_dir;
Smarty setCompileDir( string $path )
replaces $smarty->compile_dir = "foo";
string getCacheDir()
replaces $smarty->cache_dir;
Smarty setCacheDir( string $path )
replaces $smarty->cache_dir;
+2
View File
@@ -0,0 +1,2 @@
# Pre-release Todos
-33
View File
@@ -1,33 +0,0 @@
# @TODO
## CI-building optimization
- compiled & cached templates should not contain references to local filesystem paths. Add an optional rootpath param
to `(add|set)TemplateDir` or as a separate method. Make it default to `getcwd()`. If a relative path is passed to
`(add|set)TemplateDir`, prefix it with the rootpath at runtime, but do not store the path.
## Review direct variable property access
- review ->value{$index} in ForTag
## include inline
- Re-introduce merge_compiled_includes and the {include inline} attribute?
## Output buffering
- Fix ob_ output buffering commands being scattered around the codebase
## Review public static vars
- such as _CHARSET and _IS_WINDOWS
## Block / inheritance
- Consider phasing out $smarty.block.child as this reverses the inheritance hierarchy and might cause infinite loops
when combined with $smarty.block.parent
## Plugin system
- fix template security checks in one place in compiler
## Beatify output
- compiled templates could be proper classes, possibly using [nette/php-generator](https://packagist.org/packages/nette/php-generator)
## Unrelated / other
- review (and avoid) use of 'clone' keyword
- compiler->has_code seems silly. Why not have proper return values?
- what is 'user literal support', why are unit tests skipped?
-1
View File
@@ -1 +0,0 @@
- Fix warning when calling hasVariable for an undefined variable [#977](https://github.com/smarty-php/smarty/issues/977)
+9 -16
View File
@@ -5,7 +5,7 @@
"keywords": [
"templating"
],
"homepage": "https://smarty-php.github.io/smarty/",
"homepage": "http://www.smarty.net",
"license": "LGPL-3.0",
"authors": [
{
@@ -19,35 +19,28 @@
{
"name": "Rodney Rehm",
"email": "rodney.rehm@medialize.de"
},
{
"name": "Simon Wisselink",
"homepage": "https://www.iwink.nl/"
}
],
"support": {
"irc": "irc://irc.freenode.org/smarty",
"issues": "https://github.com/smarty-php/smarty/issues",
"forum": "https://github.com/smarty-php/smarty/discussions"
"forum": "http://www.smarty.net/forums/"
},
"require": {
"php": "^7.2 || ^8.0",
"symfony/polyfill-mbstring": "^1.27"
"php": ">=5.2"
},
"autoload": {
"psr-4" : {
"Smarty\\" : "src/"
},
"files": [
"src/functions.php"
"classmap": [
"libs/"
]
},
"extra": {
"branch-alias": {
"dev-master": "5.0.x-dev"
"dev-master": "3.1.x-dev"
}
},
"require-dev": {
"phpunit/phpunit": "^8.5 || ^7.5",
"smarty/smarty-lexer": "^4.0.2"
"phpunit/phpunit": "^7.5 || ^6.5 || ^5.7 || ^4.8",
"smarty/smarty-lexer": "^3.1"
}
}
+4 -4
View File
@@ -2,11 +2,11 @@
/**
* Example Application
*
* @package Example-application
*/
$smarty = new \Smarty\Smarty;
require '../libs/Smarty.class.php';
$smarty = new Smarty;
//$smarty->force_compile = true;
$smarty->debugging = true;
$smarty->caching = true;
$smarty->cache_lifetime = 120;
@@ -6,11 +6,23 @@
* memcache as the storage resource for Smarty's output caching.
* *
*
* @package CacheResource-examples
* @author Uwe Tews
*/
class Smarty_CacheResource_Apc extends \Smarty\Cacheresource\KeyValueStore
class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore
{
/**
* Smarty_CacheResource_Apc constructor.
*
* @throws \Exception
*/
public function __construct()
{
// test if APC is present
if (!function_exists('apc_cache_info')) {
throw new Exception('APC Template Caching Error: APC is not installed');
}
}
/**
* Read values for a set of keys from cache
@@ -7,32 +7,30 @@
* Note that memcache has a limitation of 256 characters per cache-key.
* To avoid complications all cache-keys are translated to a sha1 hash.
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore
{
/**
* memcache instance
*
* @var Memcache
*/
private $memcache = null;
protected $memcache = null;
/**
* @return Memcache|Memcached
*/
public function getMemcache() {
if ($this->memcache === null) {
if (class_exists('Memcached')) {
$this->memcache = new Memcached();
} else {
$this->memcache = new Memcache();
}
$this->memcache->addServer('127.0.0.1', 11211);
}
return $this->memcache;
}
/**
* Smarty_CacheResource_Memcache constructor.
*/
public function __construct()
{
if (class_exists('Memcached')) {
$this->memcache = new Memcached();
} else {
$this->memcache = new Memcache();
}
$this->memcache->addServer('127.0.0.1', 11211);
}
/**
* Read values for a set of keys from cache
@@ -47,7 +45,7 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
$res = array();
foreach ($keys as $key) {
$k = sha1($key);
$res[$key] = $this->getMemcache()->get($k);
$res[$key] = $this->memcache->get($k);
}
return $res;
}
@@ -65,9 +63,9 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
foreach ($keys as $k => $v) {
$k = sha1($k);
if (class_exists('Memcached')) {
$this->getMemcache()->set($k, $v, $expire);
$this->memcache->set($k, $v, $expire);
} else {
$this->getMemcache()->set($k, $v, 0, $expire);
$this->memcache->set($k, $v, 0, $expire);
}
}
return true;
@@ -84,7 +82,7 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
{
foreach ($keys as $k) {
$k = sha1($k);
$this->getMemcache()->delete($k);
$this->memcache->delete($k);
}
return true;
}
@@ -96,6 +94,6 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
*/
protected function purge()
{
return $this->getMemcache()->flush();
return $this->memcache->flush();
}
}
@@ -1,7 +1,5 @@
<?php
use Smarty\Exception;
/**
* MySQL CacheResource
* CacheResource Implementation based on the Custom API to use
@@ -21,73 +19,68 @@ use Smarty\Exception;
* INDEX(`modified`)
* ) ENGINE = InnoDB;</pre>
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom
{
/**
* @var \PDO
*/
protected $db;
/**
* @return PDO
* @throws Exception
*/
protected function db(): PDO {
static $dbConn = null;
try {
return $dbConn ?? ($dbConn = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty"));
} catch (PDOException $e) {
throw new Exception('Mysql Resource failed: ' . $e->getMessage());
}
}
/**
* @var \PDOStatement
*/
protected $fetch;
/**
* @return false|PDOStatement
* @throws Exception
*/
protected function fetchQuery() {
static $query = null;
return $query ?? $query = $this->db()->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
}
/**
* @var \PDOStatement
*/
protected $fetchTimestamp;
/**
* @return false|PDOStatement
* @throws Exception
*/
protected function fetchTimestampQuery() {
static $query = null;
return $query ?? $query = $this->db()->prepare('SELECT modified FROM output_cache WHERE id = :id');
}
/**
* @var \PDOStatement
*/
protected $save;
/**
* @return false|PDOStatement
* @throws Exception
*/
protected function saveQuery() {
static $query = null;
return $query ?? $query = $this->db()->prepare(
'REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
/**
* Smarty_CacheResource_Mysql constructor.
*
* @throws \SmartyException
*/
public function __construct()
{
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
$this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
$this->save = $this->db->prepare(
'REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
VALUES (:id, :name, :cache_id, :compile_id, :content)'
);
}
);
}
/**
* fetch cached content and its modification time from data source
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param string $content cached content
* @param integer $mtime cache modification timestamp (epoch)
*
* @return void
* @throws Exception
*/
/**
* fetch cached content and its modification time from data source
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param string $content cached content
* @param integer $mtime cache modification timestamp (epoch)
*
* @return void
*/
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
{
$this->fetchQuery()->execute(array('id' => $id));
$row = $this->fetchQuery()->fetch();
$this->fetchQuery()->closeCursor();
$this->fetch->execute(array('id' => $id));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$content = $row[ 'content' ];
$mtime = strtotime($row[ 'modified' ]);
@@ -112,9 +105,9 @@ class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
*/
protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
{
$this->fetchTimestampQuery()->execute(array('id' => $id));
$mtime = strtotime($this->fetchTimestampQuery()->fetchColumn());
$this->fetchTimestampQuery()->closeCursor();
$this->fetchTimestamp->execute(array('id' => $id));
$mtime = strtotime($this->fetchTimestamp->fetchColumn());
$this->fetchTimestamp->closeCursor();
return $mtime;
}
@@ -132,14 +125,14 @@ class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
*/
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
{
$this->saveQuery()->execute(
$this->save->execute(
array('id' => $id,
'name' => $name,
'cache_id' => $cache_id,
'compile_id' => $compile_id,
'content' => $content,)
);
return !!$this->saveQuery()->rowCount();
return !!$this->save->rowCount();
}
/**
@@ -157,18 +150,18 @@ class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
// delete the whole cache
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
// returning the number of deleted caches would require a second query to count them
$query = $this->db()->query('TRUNCATE TABLE output_cache');
$query = $this->db->query('TRUNCATE TABLE output_cache');
return -1;
}
// build the filter
$where = array();
// equal test name
if ($name !== null) {
$where[] = 'name = ' . $this->db()->quote($name);
$where[] = 'name = ' . $this->db->quote($name);
}
// equal test compile_id
if ($compile_id !== null) {
$where[] = 'compile_id = ' . $this->db()->quote($compile_id);
$where[] = 'compile_id = ' . $this->db->quote($compile_id);
}
// range test expiration time
if ($exp_time !== null) {
@@ -178,13 +171,13 @@ class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
if ($cache_id !== null) {
$where[] =
'(cache_id = ' .
$this->db()->quote($cache_id) .
$this->db->quote($cache_id) .
' OR cache_id LIKE ' .
$this->db()->quote($cache_id . '|%') .
$this->db->quote($cache_id . '|%') .
')';
}
// run delete query
$query = $this->db()->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
$query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
return $query->rowCount();
}
}
@@ -1,7 +1,5 @@
<?php
use Smarty\Exception;
/**
* PDO Cache Handler
* Allows you to store Smarty Cache files into your db.
@@ -24,11 +22,12 @@ use Smarty\Exception;
* Example usage :
* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
* $smarty->setCachingType('pdo');
* $smarty->loadPlugin('Smarty_CacheResource_Pdo');
* $smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo($cnx, 'smarty_cache'));
*
* @author Beno!t POLASZEK - 2014
*/
class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
{
/**
* @var string[]
@@ -121,12 +120,12 @@ class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
* @param string $table : table (or view) name
* @param string $database : optional - if table is located in another db
*
* @throws \Smarty\Exception
* @throws \SmartyException
*/
public function __construct(PDO $pdo, $table, $database = null)
{
if (is_null($table)) {
throw new Exception("Table name for caching can't be null");
throw new SmartyException("Table name for caching can't be null");
}
$this->pdo = $pdo;
$this->table = $table;
@@ -197,7 +196,7 @@ class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
* @return void
* @access protected
*/
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime)
{
$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);
$stmt->execute();
@@ -245,7 +244,7 @@ class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
* @return boolean success
* @access protected
*/
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content)
{
$stmt = $this->pdo->prepare($this->insertStatement);
$stmt->bindValue('id', $id);
@@ -323,7 +322,7 @@ class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
$where[] = 'compile_id = ' . $this->pdo->quote($compile_id);
}
// for clearing expired caches
if ($exp_time === \Smarty\Smarty::CLEAR_EXPIRED) {
if ($exp_time === Smarty::CLEAR_EXPIRED) {
$where[] = 'expire < CURRENT_TIMESTAMP';
} // range test expiration time
elseif ($exp_time !== null) {
@@ -1,12 +1,12 @@
<?php
require_once __DIR__ . '/cacheresource.pdo.php';
require_once 'cacheresource.pdo.php';
/**
* PDO Cache Handler with GZIP support
* Example usage :
* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
* $smarty->setCachingType('pdo_gzip');
* $smarty->loadPlugin('Smarty_CacheResource_Pdo_Gzip');
* $smarty->registerCacheResource('pdo_gzip', new Smarty_CacheResource_Pdo_Gzip($cnx, 'smarty_cache'));
*
* @require Smarty_CacheResource_Pdo class
@@ -1,43 +1,38 @@
<?php
use Smarty\Exception;
use Smarty\Template;
use Smarty\Template\Source;
/**
* Extends All Resource
* Resource Implementation modifying the extends-Resource to walk
* through the template_dirs and inherit all templates of the same name
*
* @package Resource-examples
* @author Rodney Rehm
*/
class My_Resource_Extendsall extends \Smarty\Resource\ExtendsPlugin
class Smarty_Resource_Extendsall extends Smarty_Internal_Resource_Extends
{
/**
* populate Source Object with meta data from Resource
*
* @param Source $source source object
* @param Template $_template template object
* @param Smarty_Template_Source $source source object
* @param Smarty_Internal_Template $_template template object
*
* @return void
*/
public function populate(Source $source, Template $_template = null)
public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
{
$uid = '';
$sources = array();
$timestamp = 0;
foreach ($source->getSmarty()->getTemplateDir() as $key => $directory) {
foreach ($source->smarty->getTemplateDir() as $key => $directory) {
try {
$s = \Smarty\Template\Source::load(null, $source->getSmarty(),
'file:' . '[' . $key . ']' . $source->name);
$s = Smarty_Resource::source(null, $source->smarty, 'file:' . '[' . $key . ']' . $source->name);
if (!$s->exists) {
continue;
}
$sources[ $s->uid ] = $s;
$uid .= $s->uid;
$uid .= $s->filepath;
$timestamp = $s->timestamp > $timestamp ? $s->timestamp : $timestamp;
} catch (Exception $e) {
} catch (SmartyException $e) {
}
}
if (!$sources) {
@@ -48,7 +43,8 @@ class My_Resource_Extendsall extends \Smarty\Resource\ExtendsPlugin
reset($sources);
$s = current($sources);
$source->components = $sources;
$source->uid = sha1($uid . $source->getSmarty()->_joined_template_dir);
$source->filepath = $s->filepath;
$source->uid = sha1($uid . $source->smarty->_joined_template_dir);
$source->exists = true;
$source->timestamp = $timestamp;
}
+101
View File
@@ -0,0 +1,101 @@
<?php
/**
* MySQL Resource
* Resource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's templates and configs.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
* `name` varchar(100) NOT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* `source` text,
* PRIMARY KEY (`name`)
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
* Demo data:
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
* world"}{$x}');</pre>
*
*
* @package Resource-examples
* @author Rodney Rehm
*/
class Smarty_Resource_Mysql extends Smarty_Resource_Custom
{
/**
* PDO instance
*
* @var \PDO
*/
protected $db;
/**
* prepared fetch() statement
*
* @var \PDOStatement
*/
protected $fetch;
/**
* prepared fetchTimestamp() statement
*
* @var \PDOStatement
*/
protected $mtime;
/**
* Smarty_Resource_Mysql constructor.
*
* @throws \SmartyException
*/
public function __construct()
{
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name');
$this->mtime = $this->db->prepare('SELECT modified FROM templates WHERE name = :name');
}
/**
* Fetch a template and its modification time from database
*
* @param string $name template name
* @param string $source template source
* @param integer $mtime template modification timestamp (epoch)
*
* @return void
*/
protected function fetch($name, &$source, &$mtime)
{
$this->fetch->execute(array('name' => $name));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$source = $row[ 'source' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$source = null;
$mtime = null;
}
}
/**
* Fetch a template's modification time from database
*
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than
* loading the comple template source.
*
* @param string $name template name
*
* @return integer timestamp (epoch) the template was modified
*/
protected function fetchTimestamp($name)
{
$this->mtime->execute(array('name' => $name));
$mtime = $this->mtime->fetchColumn();
$this->mtime->closeCursor();
return strtotime($mtime);
}
}
+77
View File
@@ -0,0 +1,77 @@
<?php
/**
* MySQL Resource
* Resource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's templates and configs.
* Note that this MySQL implementation fetches the source and timestamps in
* a single database query, instead of two separate like resource.mysql.php does.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
* `name` varchar(100) NOT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* `source` text,
* PRIMARY KEY (`name`)
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
* Demo data:
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
* world"}{$x}');</pre>
*
*
* @package Resource-examples
* @author Rodney Rehm
*/
class Smarty_Resource_Mysqls extends Smarty_Resource_Custom
{
/**
* PDO instance
*
* @var \PDO
*/
protected $db;
/**
* prepared fetch() statement
*
* @var \PDOStatement
*/
protected $fetch;
/**
* Smarty_Resource_Mysqls constructor.
*
* @throws \SmartyException
*/
public function __construct()
{
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name');
}
/**
* Fetch a template and its modification time from database
*
* @param string $name template name
* @param string $source template source
* @param integer $mtime template modification timestamp (epoch)
*
* @return void
*/
protected function fetch($name, &$source, &$mtime)
{
$this->fetch->execute(array('name' => $name));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$source = $row[ 'source' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$source = null;
$mtime = null;
}
}
}
+2
View File
@@ -11,6 +11,8 @@
The current date and time is {$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}
The value of global assigned variable $SCRIPT_NAME is {$SCRIPT_NAME}
Example of accessing server environment variable SERVER_NAME: {$smarty.server.SERVER_NAME}
The value of {ldelim}$Name{rdelim} is <b>{$Name}</b>
-75
View File
@@ -1,75 +0,0 @@
version: "2"
services:
base:
build:
context: .
dockerfile: ./utilities/testrunners/php72/Dockerfile
volumes:
- smarty-code:/app
working_dir: /app
php72:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php72/Dockerfile
php73:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php73/Dockerfile
php74:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php74/Dockerfile
php80:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php80/Dockerfile
php81:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php81/Dockerfile
php82:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php82/Dockerfile
php83:
extends:
service: base
build:
dockerfile: ./utilities/testrunners/php83/Dockerfile
volumes:
smarty-code:
x-mutagen:
sync:
defaults:
symlink:
mode: "posix-raw"
ignore:
vcs: true
paths:
- ".docker"
- ".env.docker"
- ".bundles"
- "docker-compose.yml"
- ".idea"
- ".DS_Store"
mode: "two-way-resolved"
configurationBeta:
permissions:
defaultOwner: "id:${APP_USER_ID}"
defaultGroup: "id:${APP_GROUP_ID}"
defaultFileMode: 0666
defaultDirectoryMode: 0755
permissions:
defaultOwner: "id:${APP_USER_ID}"
defaultGroup: "id:${APP_GROUP_ID}"
smarty-code:
alpha: "."
beta: "volume://smarty-code"
-1
View File
@@ -1 +0,0 @@
theme: jekyll-theme-minimal
-93
View File
@@ -1,93 +0,0 @@
# Basics
## Installation
For installation instructies, please see the [getting started section](../getting-started.md).
## Rendering a template
Here's how you create an instance of Smarty in your PHP scripts:
```php
<?php
require 'vendor/autoload.php';
use Smarty\Smarty;
$smarty = new Smarty();
```
You now have a Smarty object that you can use to render templates.
```php
<?php
require 'vendor/autoload.php';
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->display('string:The current smarty version is: {$smarty.version}.');
// or
echo $smarty->fetch('string:The current smarty version is: {$smarty.version}.');
```
## Using file-based templates
You probably want to manage your templates as files. Create a subdirectory called 'templates' and
then configure Smarty to use that:
```php
<?php
require 'vendor/autoload.php';
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->setTemplateDir(__DIR__ . '/templates');
```
Say you have a template file called 'version.tpl', stored in the 'templates' directory like this:
```smarty
<h1>Hi</h1>
The current smarty version is: {$smarty.version|escape}.
```
You can now render this, using:
```php
<?php
require 'vendor/autoload.php';
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->setTemplateDir(__DIR__ . '/templates');
$smarty->display('version.tpl');
```
## Assigning variables
Templates start to become really useful once you add variables to the mix.
Create a template called 'footer.tpl' in the 'templates' directory like this:
```smarty
<small>Copyright {$companyName|escape}</small>
```
Now assign a value to the 'companyName' variable and render your template like this:
```php
<?php
require 'vendor/autoload.php';
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->setTemplateDir(__DIR__ . '/templates');
$smarty->assign('companyName', 'AC & ME Corp.');
$smarty->display('footer.tpl');
```
Run this, and you will see:
```html
<small>Copyright AC &amp; ME Corp.</small>
```
Note how the [escape modifier](../designers/language-modifiers/language-modifier-escape.md)
translated the `&` character into the proper HTML syntax `&amp;`.
Read more about auto-escaping in the [next section](./configuring.md).
-184
View File
@@ -1,184 +0,0 @@
# Caching
Caching is used to speed up the rendering of a template by saving and re-using the output.
If a cached version of the call is available, that is displayed instead of
regenerating the output. Caching can speed things up tremendously,
especially templates with longer computation times.
Since templates can include or extend other templates, one
cache file could conceivably be made up of several template files,
config files, etc.
> ** Note **
>
> Since templates are dynamic, it is important to be careful what you are
> caching and for how long. For instance, if you are displaying the front
> page of your website that does not change its content very often, it
> might work well to cache this page for an hour or more. On the other
> hand, if you are displaying a page with a timetable containing new
> information by the minute, it would not make sense to cache this page.
## Setting Up Caching
The first thing to do is enable caching by calling `Smarty::setCaching()` with either
`\Smarty\Smarty::CACHING_LIFETIME_CURRENT` or `\Smarty\Smarty::CACHING_LIFETIME_SAVED`.
Or with `\Smarty\Smarty::CACHING_OFF` to disable caching again.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
// enable caching, using the current lifetime (see below)
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// enable caching, using the lifetime set when the cache was saved (see below)
$smarty->setCaching(Smarty::CACHING_LIFETIME_SAVED);
// disable caching
$smarty->setCaching(Smarty::CACHING_OFF);
$smarty->display('index.tpl');
```
With caching enabled, the function call to `$smarty->display('index.tpl')` will
render the template as usual, but also saves a copy of its output. On the
next call to `$smarty->display('index.tpl')`, the cached copy will be used
instead of rendering the template again.
> **Note**
>
> By default, Smarty saved its caches as files in a dir called `cache` relative to the current
> directory. The default directory can be changed using `$smarty->setCacheDir('/some/cache/dir');`
> The files are named similar
> to the template name. Although they end in the `.php` extension, they
> are not intended to be directly executable. Do not edit these files!
## Cache lifetime
Each cached page has a limited lifetime. The default value is 3600
seconds, or one hour. After that time expires, the cache is regenerated.
You can change the lifetime as follows:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// or $smarty->setCaching(Smarty::CACHING_LIFETIME_SAVED);
// set the cache_lifetime to 5 minutes
$smarty->setCacheLifetime(5 * 60);
```
Setting caching to a value of `\Smarty\Smarty::CACHING_LIFETIME_CURRENT` tells Smarty to use
the current lifetime to determine if the cache has expired.
A value of `\Smarty\Smarty::CACHING\_LIFETIME\_SAVED` tells Smarty to use the lifetime value at the time the
cache was generated. This way you can set the just before rendering a template to have granular control over
when that particular cache expires.
An example:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
// retain current cache lifetime for each specific display call
$smarty->setCaching(Smarty::CACHING_LIFETIME_SAVED);
// set the cache_lifetime for index.tpl to 5 minutes
$smarty->setCacheLifetime(300);
$smarty->display('index.tpl');
// set the cache_lifetime for home.tpl to 1 hour
$smarty->setCacheLifetime(3600);
$smarty->display('home.tpl');
// NOTE: the following $cache_lifetime setting will not work when $caching
// is set to Smarty::CACHING_LIFETIME_SAVED.
// The cache lifetime for home.tpl has already been set
// to 1 hour, and will no longer respect the value of $cache_lifetime.
// The home.tpl cache will still expire after 1 hour.
$smarty->setCacheLifetime(30); // 30 seconds
$smarty->display('home.tpl');
```
## Compile check
By default, every template file and config file that is involved with the cache file
is checked for modification. If any of the files have been modified
since the cache was generated, the cache is immediately regenerated.
This is a computational overhead, so for optimum performance, disable this on a production environment:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$smarty->setCompileCheck(Smarty::COMPILECHECK_OFF);
$smarty->display('index.tpl');
```
## Checking if a template is cached
Smarty's `isCached() method can be used to test if a
template has a valid cache or not. If you have a cached template that
requires something like a database fetch, you can use this to skip that
process.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
if (!$smarty->isCached('index.tpl')) {
// No cache available, do variable assignments here.
$smarty->assign('data', do_expensive_database_calls());
}
$smarty->display('index.tpl');
```
## Nocache-blocks
You can keep parts of a page dynamic (disable caching) with the
[`{nocache}{/nocache}`](../../designers/language-builtin-functions/language-function-nocache.md) block function,
or by using the `nocache` parameter for most template functions.
Let's say the whole page can be cached except for a banner that is
displayed down the side of the page. By using a [`{nocache}{/nocache}`](../../designers/language-builtin-functions/language-function-nocache.md)
block for the banner, you can
keep this element dynamic within the cached content.
## Clearing the cache
You can clear all the cache files with Smarty's `clearAllCache()` method, or individual cache
files with the `clearCache()` method.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// clear only cache for index.tpl
$smarty->clearCache('index.tpl');
// clear out all cache files
$smarty->clearAllCache();
// clear out all cache files older than one hour
$smarty->clearAllCache(3600);
// or, clear all expired caches
$smarty->clearAllCache(Smarty::CLEAR_EXPIRED);
```
-36
View File
@@ -1,36 +0,0 @@
# Custom cache storage layers
As an alternative to using the default file-based caching mechanism, you
can specify a custom cache implementation that will be used to read,
write and clear cached files.
With a custom cache implementation you could replace the slow filesystem by a
faster storage engine, centralize the cache to be accessible to multiple
servers.
Smarty requires implementations to extend `\Smarty\Cacheresource\Base`, but encourages you to either extend
`\Smarty\Cacheresource\Custom` or `\Smarty\Cacheresource\KeyValueStore`.
- `\Smarty\Cacheresource\Custom` is a simple API directing all read, write,
clear calls to your implementation. This API allows you to store
wherever and however you deem fit.
- `\Smarty\Cacheresource\KeyValueStore` allows you to turn any
KeyValue-Store (like APC or Memcache) into a full-featured
CacheResource implementation. Everything around deep
cache-groups like "a|b|c" is being handled for you in a way that
guarantees clearing the cache-group "a" will clear all nested groups
as well - even though KeyValue-Stores don't allow this kind of
hierarchy by nature.
Custom CacheResources must be registered on
runtime with `Smarty\Smarty::setCacheResource()`:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->setCacheResource(new My_CacheResource_Mysql());
```
@@ -1,137 +0,0 @@
# Multiple caches per template
## Introduction
You can have multiple cache files for a single call to
`display()` or `fetch()`.
Let's say that
a call to `$smarty->display('index.tpl')` may have several different output
contents depending on some condition, and you want separate caches for
each one. You can do this by passing a `$cache_id` as the second
parameter to the function call:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$my_cache_id = (int) $_GET['article_id'];
$smarty->display('index.tpl', $my_cache_id);
```
Above, we are passing the variable `$my_cache_id` to
[`display()`](#api.display) as the `$cache_id`. For each unique value of
`$my_cache_id`, a separate cache will be generated for `index.tpl`. In
this example, `article_id` was passed in the URL and is used as the
`$cache_id`.
> **Note**
>
> Be very cautious when passing values from a client (web browser) into
> Smarty or any PHP application. Although the above example of using the
> article_id from the URL looks handy, it could have bad consequences.
> The `$cache_id` is used to create a directory on the file system, so
> if the user decided to write a script that sends random article_id's at a rapid pace,
> this could possibly cause problems at the server level.
> Be sure to sanitize any data passed in before using it. In this example, you might want to check if
> the article_id is a valid ID in the database.
Be sure to pass the same `$cache_id` as the second parameter to
`isCached()` and `clearCache()`.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$my_cache_id = (int) $_GET['article_id'];
if (!$smarty->isCached('index.tpl', $my_cache_id)) {
// ...
}
$smarty->display('index.tpl', $my_cache_id);
```
## Clearing specific caches
You can clear all caches for a particular `$cache_id` by passing NULL as
the first parameter to `clearCache()`.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// clear all caches with "sports" as the $cache_id
$smarty->clearCache(null, 'sports');
$smarty->display('index.tpl', 'sports');
```
In this manner, you can "group" your caches together by giving them the
same `$cache_id`.
## Advanced cache grouping
You can do more elaborate grouping by setting up `$cache_id` groups.
This is accomplished by separating each sub-group with a vertical bar
`|` in the `$cache_id` value. You can have as many sub-groups as you
like.
- You can think of cache groups like a directory hierarchy. For
instance, a cache group of `'a|b|c'` could be thought of as the
directory structure `'/a/b/c/'`.
- `clearCache(null, 'a|b|c')` would be like removing the files
`'/a/b/c/*'`. `clearCache(null, 'a|b')` would be like removing the
files `'/a/b/*'`.
- If you specify a template name such as
`clearCache('foo.tpl', 'a|b|c')` then Smarty will attempt to remove
`'/a/b/c/foo.tpl'`.
- You CANNOT remove a specified template name under multiple cache
groups such as `'/a/b/*/foo.tpl'`, the cache grouping works
left-to-right ONLY. You will need to group your templates under a
single cache group hierarchy to be able to clear them as a group.
Cache grouping should not be confused with your template directory
hierarchy, the cache grouping has no knowledge of how your templates are
structured. So for example, if you have a template structure like
`themes/blue/index.tpl` and you want to be able to clear all the cache
files for the "blue" theme, you will need to create a cache group
structure that mimics your template file structure, such as
`display('themes/blue/index.tpl', 'themes|blue')`, then clear them with
`clearCache(null, 'themes|blue')`.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// clear all caches with 'sports|basketball' as the first two cache_id groups
$smarty->clearCache(null, 'sports|basketball');
// clear all caches with "sports" as the first cache_id group. This would
// include "sports|basketball", or "sports|(anything)|(anything)|(anything)|..."
$smarty->clearCache(null, 'sports');
// clear the foo.tpl cache file with "sports|basketball" as the cache_id
$smarty->clearCache('foo.tpl', 'sports|basketball');
$smarty->display('index.tpl', 'sports|basketball');
```
-193
View File
@@ -1,193 +0,0 @@
# Configuring Smarty
## Setting the template path
By default, Smarty looks for templates to render in `./templates`.
You can change this, or even use multiple paths to use when looking for templates.
If you need to change this, you can use `setTemplateDir()` or `addTemplateDir()`.
Use `getTemplateDir()` to retrieve the configured paths.
```php
<?php
// set a single directory where the config files are stored
$smarty->setTemplateDir('./config');
// set multiple directories where config files are stored
$smarty->setTemplateDir(['./config', './config_2', './config_3']);
// add directory where config files are stored to the current list of dirs
$smarty->addTemplateDir('./config_1');
// add multiple directories to the current list of dirs
$smarty->addTemplateDir([
'./config_2',
'./config_3',
]);
// chaining of method calls
$smarty->setTemplateDir('./config')
->addTemplateDir('./config_1')
->addTemplateDir('./config_2');
// get all directories where config files are stored
$template_dirs = $smarty->getTemplateDir();
var_dump($template_dirs); // array
// get directory identified by key
$template_dir = $smarty->getTemplateDir(0);
var_dump($template_dir); // string
```
## Setting the path for compiled templates
Smarty compiles templates to native PHP to be as fast as possible.
The default path where these PHP-files are stored is `./templates_c`.
If you need to change this, you can use `setCompileDir()`.
Use `getCompileDir()` to retrieve the configured path.
```php
<?php
// set another path to store compiled templates
$smarty->setCompileDir('/data/compiled_templates');
// get directory where compiled templates are stored
$compileDir = $smarty->getCompileDir();
```
## Setting the config path
Smarty can [load data from config files](./variables/config-files.md).
By default, Smarty loads the config files from `./configs`.
You can change this, or even use multiple paths to use when looking for config files.
If you need to change this, you can use `setConfigDir()` or `addConfigDir()`.
Use `getConfigDir()` to retrieve the configured paths.
```php
<?php
// set a single directory where the config files are stored
$smarty->setConfigDir('./config');
// set multiple directories where config files are stored
$smarty->setConfigDir(['./config', './config_2', './config_3']);
// add directory where config files are stored to the current list of dirs
$smarty->addConfigDir('./config_1');
// add multiple directories to the current list of dirs
$smarty->addConfigDir([
'./config_2',
'./config_3',
]);
// chaining of method calls
$smarty->setConfigDir('./config')
->addConfigDir('./config_1', 'one')
->addConfigDir('./config_2', 'two');
// get all directories where config files are stored
$config_dirs = $smarty->getConfigDir();
var_dump($config_dirs); // array
// get directory identified by key
$config_dir = $smarty->getConfigDir(0);
var_dump($config_dir); // string
```
## Setting the path for caches
Even though Smarty runs templates as native PHP for maximum speed, it still needs to
execute the PHP code on each call. If your data doesn't change all that often, you
may be able to speed up your application even more by using output caching.
Output caching can be a tricky subject, so we devoted an entire [section to caching](./caching/basics.md).
Be sure to read that if you want to use caching.
By default, Smarty stores caches to PHP-files in a subdirectory named `./cache`.
If you need to change this, you can use `setCacheDir()`.
Use `getCacheDir()` to retrieve the configured path.
```php
<?php
// set another path to store caches
$smarty->setCacheDir('/data/caches');
// get directory where cached templates are stored
$cacheDir = $smarty->getCacheDir();
```
## Enabling auto-escaping
By default, Smarty does not escape anything you render in your templates. If you use
Smarty to render a HTML-page, this means that you will have to make sure that you do
not render any characters that have a special meaning in HTML, such as `&`, `<` and `>`,
or apply the [escape modifier](../designers/language-modifiers/language-modifier-escape.md)
to anything you want to render.
If you forget to do so, you may break your HTML page, or even create a vulnerability for
attacks known as [XSS or Cross Site Scripting](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).
Luckily, you can tell Smarty to automatically apply the escape modifier to any dynamic part of your template.
It's like Smarty magically adds `|escape` to every variable you use on a web page.
Enable auto-escaping for HTML as follows:
```php
$smarty->setEscapeHtml(true);
```
## Disabling compile check
By default, Smarty tests to see if the
current template has changed since the last time
it was compiled. If it has changed, it recompiles that template.
Once an application is put into production, this compile-check step
is usually no longer needed and the extra checks can significantly hurt performance.
Be sure to disable compile checking on production for maximum performance.
```php
<?php
$smarty->setCompileCheck(\Smarty\Smarty::COMPILECHECK_OFF);
```
If [`caching`](./caching/basics.md) is enabled and compile-check is
enabled, then the cache files will get regenerated if an involved
template file or config file was updated.
## Charset encoding
There are a variety of encodings for textual data, ISO-8859-1 (Latin1)
and UTF-8 being the most popular. Unless you change `\Smarty\Smarty::$_CHARSET`,
Smarty recognizes `UTF-8` as the internal charset.
> **Note**
>
> `ISO-8859-1` has been PHP\'s default internal charset since the
> beginning. Unicode has been evolving since 1991. Since then, it has
> become the one charset to conquer them all, as it is capable of
> encoding most of the known characters even across different character
> systems (latin, cyrillic, japanese, ...). `UTF-8` is unicode\'s most
> used encoding, as it allows referencing the thousands of character
> with the smallest size overhead possible.
>
> Since unicode and UTF-8 are very widespread nowadays, their use is
> strongly encouraged.
> **Note**
>
> Smarty\'s internals and core plugins are truly UTF-8 compatible since
> Smarty 3.1.
```php
<?php
// use japanese character encoding
mb_internal_charset('EUC-JP');
\Smarty\Smarty::$_CHARSET = 'EUC-JP';
$smarty = new \Smarty\Smarty();
```
-59
View File
@@ -1,59 +0,0 @@
# Custom block tags
Block tags are tags of the form: `{func} .. {/func}`. In other
words, they enclose a template block and operate on the contents of this
block.
Block functions take precedence over normal tags of the same name, that is, you
cannot have both custom tag `{func}` and block tag `{func}..{/func}`.
- By default, your function implementation is called twice by Smarty:
once for the opening tag, and once for the closing tag. (See
`$repeat` below on how to change this.)
- Only the opening tag of the block has attributes. All attributes are contained in the `$params`
variable as an associative array. The opening tag attributes are
also accessible to your function when processing the closing tag.
- The value of the `$content` variable depends on whether your
function is called for the opening or closing tag. In case of the
opening tag, it will be NULL, and in case of the closing tag it will
be the contents of the template block. Note that the template block
will have already been processed by Smarty, so all you will receive
is the template output, not the template source.
- The parameter `$repeat` is passed by reference to the function
implementation and provides a possibility for it to control how many
times the block is displayed. By default `$repeat` is TRUE at the
first call of the block function (the opening tag) and FALSE on all
subsequent calls to the block function (the block's closing tag).
Each time the function implementation returns with `$repeat` being
TRUE, the contents between `{func}...{/func}` are evaluated and the
function implementation is called again with the new block contents
in the parameter `$content`.
Example:
```php
<?php
function smarty_block_translate($params, $content, \Smarty\Template $template, &$repeat) {
// only output on the closing tag
if (!$repeat){
if (isset($content)) {
$lang = $params['lang'];
// do some intelligent translation thing here with $content
return $translation;
}
}
}
$smarty->registerPlugin(Smarty\Smarty::PLUGIN_BLOCK, 'translate', 'smarty_block_translate');
```
This can now be used in your templates as follows:
```smarty
{translate lang='nl'}
Quia omnis nulla omnis iusto est id et.
{/translate}
```
-101
View File
@@ -1,101 +0,0 @@
# Creating an extension
## Default extensions
In order to organize your custom tags and modifiers, you can create an Extension.
In fact, most of Smarty itself is organized into two extensions:
- the core extension, which provides the basic language tags such as `{if}`, `{for}` and `{assign}`.
- the default extension, which provides all default modifiers such as `|escape`, `|nl2br` and `|number_format`
and tags such as `{html_image}`, `{mailto}` and `{textformat}` that are enabled by default, but not necessarily universal.
> ** Note **
>
> There is also the 'BCPluginsAdapter' extension, which does not add any new functionality, but
> wraps calls to deprecated methods such as `Smarty\Smarty::addPluginsDir()` and `Smarty\Smarty::loadFilter()`.
## Writing your own extension
In order to write your own custom extension, you must write a class that implements `Smarty\Extension\ExtensionInterface`.
However, it is usually easier to extend `Smarty\Extension\Base` which provides empty implementation for each of the methods
required by `Smarty\Extension\ExtensionInterface`. This allows you to only override the method(s) you need.
Example:
```php
<?php
use Smarty\Extension\Base;
class MyExtension extends Base {
public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
switch ($modifier) {
case 'array_escape': return new MyArrayEscapeModifierCompiler();
case 'array_unescape': return new MyArrayUnescapeModifierCompiler();
}
return null;
}
}
```
Another example, that would allow you to use any valid PHP callable as a modifier in your templates:
```php
<?php
use Smarty\Extension\Base;
class MyCallablePassThroughExtension extends Base {
public function getModifierCallback(string $modifierName) {
if (is_callable($modifierName)) {
return $modifierName;
}
return null;
}
}
```
Writing an extension allows you to add a group of tags, block tags and modifiers to the Smarty language.
It also allows you to register pre-, post- and output-filters in a structured way.
The files in `src/Extension/` in the `smarty/smarty` dir should give you all the information you need to start
writing your own extension.
## Registering an extension
When you have written your extension, add it to a Smarty instance as follows:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->addExtension(new MyCustomExtension());
```
This will add `MyCustomExtension` to the end of the extension list, meaning that you cannot override tags or modifiers
from one of Smarty's default extensions.
Should you wish to insert your extension at the top of the extension list, or create a very limited Smarty version that
only contains the core extension, you can use `Smarty\Smarty::setExtensions()` to override the list of extensions.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->setExtensions([
new Smarty\Extension\CoreExtension(),
new MyCustomExtension(),
new Smarty\Extension\DefaultExtension(),
]);
```
-10
View File
@@ -1,10 +0,0 @@
# Extending Smarty
By default, Smarty is already very complete and powerful. However, you can unlock its real potential by
extending Smarty.
There are various ways to extend Smarty for it to suit your needs. You can create custom
[tags](tags.md), [block tags](block-tags.md) and [modifiers](modifiers.md) by registering a method as a plugin.
If this becomes too messy, you can group your custom tags, modifiers, and more into an [Extension](extensions.md).
-27
View File
@@ -1,27 +0,0 @@
# Custom modifiers
Modifiers are little functions that are applied
to a variable in the template before it is displayed or used in some
other context. Smarty comes with a bunch of [modifiers](../../designers/language-modifiers/index.md), but you can
easily add your own.
In order to do so, you must write a function that accepts as its first parameter the value on which the
modifier is to operate. The rest of the parameters are optional, depending on what kind of operation is to be performed.
The modifier has to return the result of its processing.
For example:
```php
<?php
function smarty_modifier_substr($string, $offset, $length) {
return substr($string, $offset, $length);
}
$smarty->registerPlugin(Smarty\Smarty::PLUGIN_MODIFIER, 'substr', 'smarty_modifier_substr');
```
You can now use this in your templates as follows:
```smarty
{$applicationName|substr:0:20}
```
-84
View File
@@ -1,84 +0,0 @@
# Custom tags
You can add your own tags to the Smarty language.
## Runtime tags
Usually, you'll add a runtime tag. Adding a runtime tag requires you to provide a callback function that accepts
two parameters:
- `$params`: all attributes from the template as an associative array.
- `$template`: a `Smarty\Template` object representing the template where tag was used.
The output (return value) of the function will be substituted in place
of the tag in the template.
If the function needs to assign some variables to the template or use
some other Smarty-provided functionality, it can use the supplied
`$template` object to do so.
```php
<?php
function smarty_tag_eightball($params, \Smarty\Template $template): string {
$answers = [
'Yes',
'No',
'No way',
'Outlook not so good',
'Ask again soon',
'Maybe in your reality'
];
$result = array_rand($answers);
return $answers[$result];
}
$smarty->registerPlugin(Smarty\Smarty::PLUGIN_FUNCTION, 'eightball', 'smarty_tag_eightball');
```
Which can now be used in the template as:
```smarty
Question: Will we ever have time travel?
Answer: {eightball}.
```
## Compiler tags
Compiler tags are called only during compilation of the template.
They are useful for injecting PHP code or time-sensitive static content
into the template. If there is both a compiler function and a runtime tag registered under the same name,
the compiler function has precedence.
The compiler function is passed two parameters: the params array which
contains precompiled strings for the attribute values and the Smarty
object. It's supposed to return the code to be injected into the
compiled template including the surrounding PHP tags.
Example:
```php
<?php
function smarty_compiler_tplheader($params, Smarty $smarty) {
return "<?php\necho '" . $smarty->_current_file . " compiled at " . date('Y-m-d H:M'). "';\n?>";
}
$smarty->registerPlugin(Smarty\Smarty::PLUGIN_COMPILER, 'tplheader', 'smarty_compiler_tplheader');
```
This function can be called from the template as:
```smarty
{* this function gets executed at compile time only *}
{tplheader}
```
The resulting PHP code in the compiled template would be something like
this:
```php
<?php
echo 'index.tpl compiled at 2023-02-20 20:02';
```
-35
View File
@@ -1,35 +0,0 @@
# Output filters
When a template is rendered, its output can be sent through one or more
output filters.
> **Note**
> This differs from [`prefilters`](prefilters.md) and
> [`postfilters`](postfilters.md) because, pre- and postfilters
> operate on compiled templates before they are saved to the disk, whereas
> output filters operate on the template output when it is executed.
Smarty will pass the template output as the first argument, and expect the function
to return the result of the processing.
Output filters can be either added as part of an [Extension](../extending/extensions.md) or
registered as shown below.
This will provide a rudimentary protection against spambots:
```php
<?php
function protect_email($tpl_output, \Smarty\Template\ $template)
{
return preg_replace(
'!(\S+)@([a-zA-Z0-9\.\-]+\.([a-zA-Z]{2,3}|[0-9]{1,3}))!',
'$1%40$2',
$tpl_output
);
}
// register the outputfilter
$smarty->registerFilter("output", "protect_email");
$smarty->display("index.tpl');
```
-33
View File
@@ -1,33 +0,0 @@
# Postfilters
Template postfilters are PHP functions that your templates are ran
through *after they are compiled*.
Smarty will
pass the compiled template code as the first argument, and expect the
function to return the result of the processing, which must also be valid PHP code.
Prefilters can be either added as part of an [Extension](../extending/extensions.md) or
registered as shown below.
```php
<?php
function add_header_comment($tpl_source, \Smarty\Template\ $template)
{
return "<?php echo \"<!-- Created by Smarty! -->\n\"; ?>\n".$tpl_source;
}
// register the postfilter
$smarty->registerFilter('post', 'add_header_comment');
$smarty->display('index.tpl');
```
The postfilter above will make the compiled Smarty template `index.tpl`
look like:
```smarty
<!-- Created by Smarty! -->
{* rest of template content... *}
```
-26
View File
@@ -1,26 +0,0 @@
# Prefilters
Template prefilters are PHP functions that your templates are ran
through *before they are compiled*. This is good for preprocessing your
templates to remove unwanted comments, keeping an eye on what people are
putting in their templates, etc.
Smarty will pass the template source code as the first argument, and
expect the function to return the resulting template source code.
Prefilters can be either added as part of an [Extension](../extending/extensions.md) or
registered as shown below.
This will remove all the html comments in the template source:
```php
<?php
function remove_dw_comments($tpl_source, \Smarty\Template\ $template)
{
return preg_replace("/<!--#.*-->/U",'',$tpl_source);
}
// register the prefilter
$smarty->registerFilter('pre', 'remove_dw_comments');
$smarty->display('index.tpl');
```
-130
View File
@@ -1,130 +0,0 @@
# Template Inheritance
Inheritance allows you to define base templates that can
be extended by child templates. Extending means that the child template
can override all or some of the named block areas in the base template.
When you render the child template, the result will as if you rendered
the base template, with only the block(s) that you have overridden in the
child templates differing.
- The inheritance tree can be as deep as you want, meaning you can
extend a file that extends another one that extends another one and
so on.
- The child templates can not define any content besides what's
inside [`{block}`](../designers/language-builtin-functions/language-function-block.md) tags they override.
Anything outside of [`{block}`](../designers/language-builtin-functions/language-function-block.md) tags will
be removed.
- Template inheritance is a compile time process which creates a
single compiled template file. Compared to corresponding solutions
based on subtemplates included with the
[`{include}`](../designers/language-builtin-functions/language-function-include.md) tag it does have much
better performance when rendering.
## Basic inheritance
First, create a base template with one or more [blocks](../designers/language-builtin-functions/language-function-block.md).
Then, create a child template. The child template
must have an [{extends} tag](../designers/language-builtin-functions/language-function-extends.md) on its first line.
The child template can redefine one or more blocks defined in the base template.
See below for a simple example.
layout.tpl (base)
```smarty
<html>
<head>
<title>{block name=title}Default Page Title{/block}</title>
{block name=head}{/block}
</head>
<body>
{block name=body}{/block}
</body>
</html>
```
myproject.tpl (child)
```smarty
{extends file='layout.tpl'}
{block name=head}
<link href="/css/mypage.css" rel="stylesheet" type="text/css"/>
<script src="/js/mypage.js"></script>
{/block}
```
mypage.tpl (grandchild)
```smarty
{extends file='myproject.tpl'}
{block name=title}My Page Title{/block}
{block name=head}
<link href="/css/mypage.css" rel="stylesheet" type="text/css"/>
<script src="/js/mypage.js"></script>
{/block}
{block name=body}My HTML Page Body goes here{/block}
```
To render the above, you would use:
```php
<?php
$smarty->display('mypage.tpl');
```
The resulting output is:
```html
<html>
<head>
<title>My Page Title</title>
<link href="/css/mypage.css" rel="stylesheet" type="text/css"/>
<script src="/js/mypage.js"></script>
</head>
<body>
My HTML Page Body goes here
</body>
</html>
```
> **Note**
>
> When [compile-check](./configuring.md#disabling-compile-check) is enabled, all files
> in the inheritance tree
> are checked for modifications upon each invocation. You may want to
> disable compile-check on production servers for this reason.
> **Note**
>
> If you have a subtemplate which is included with
> [`{include}`](../designers/language-builtin-functions/language-function-include.md) and it contains
> [`{block}`](../designers/language-builtin-functions/language-function-block.md) areas it works only if the
> [`{include}`](../designers/language-builtin-functions/language-function-include.md) itself is called from within
> a surrounding [`{block}`](../designers/language-builtin-functions/language-function-block.md). In the final
> parent template you may need a dummy
> [`{block}`](../designers/language-builtin-functions/language-function-block.md) for it.
## Using append and prepend
The content of [`{block}`](../designers/language-builtin-functions/language-function-block.md) tags from child
and parent templates can be merged by the `append` or `prepend`
[`{block}`](../designers/language-builtin-functions/language-function-block.md) tag option flags and
`{$smarty.block.parent}` or `{$smarty.block.child}` placeholders.
## Extends resource type
Instead of using [`{extends}`](../designers/language-builtin-functions/language-function-extends.md) tags in the
template files you can define the inheritance tree in your PHP script by
using the [`extends:` resource](resources.md#the-extends-resource) type.
The code below will return same result as the example above.
```php
<?php
$smarty->display('extends:layout.tpl|myproject.tpl|mypage.tpl');
```
-86
View File
@@ -1,86 +0,0 @@
# Rendering templates
## Fetching or rendering templates directly
As explained in [basics](basics.md), you can use `$smarty->fetch()` or `$smarty->display()`
to render a template directly.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->display('homepage.tpl');
// or
$output = $smarty->fetch('homepage.tpl');
```
When you use `display()`, Smarty renders the template to the standard output stream.
`fetch()` returns the output instead of echoing it.
The example above uses simple filenames to load the template. Smarty also supports
[loading templates from resources](resources.md).
## Creating a template object
You can also create a template object which later can be prepared first,
and rendered later. This can be useful, for example if you plan to re-use several
templates.
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
// create template object with its private variable scope
$tpl = $smarty->createTemplate('index.tpl');
// assign a variable (available only to this template)
$tpl->assign('title', 'My Homepage!');
// display the template
$tpl->display();
```
More on assigning variables in [using data in templates](variables/assigning.md).
## Testing if a template exists
You can use `templateExists()` to check whether a template exists before you attempt to use it.
It accepts either a path to the template on the filesystem or a
resource string specifying the template.
This example uses `$_GET['page']` to
[`{include}`](../designers/language-builtin-functions/language-function-include.md) a content template. If the
template does not exist then an error page is displayed instead. First,
the `page_container.tpl`
```smarty
<html>
<head>
<title>{$title|escape}</title>
</head>
<body>
{* include middle content page *}
{include file=$content_template}
</body>
</html>
```
And the php script:
```php
<?php
// set the filename eg index.inc.tpl
$mid_template = $_GET['page'].'.inc.tpl';
if (!$smarty->templateExists($mid_template)){
$mid_template = 'page_not_found.tpl';
}
$smarty->assign('content_template', $mid_template);
$smarty->display('page_container.tpl');
```
-322
View File
@@ -1,322 +0,0 @@
# Template resources
## The filesystem resource
So far in our examples, we have used simple filenames or paths when loading a template.
For example, to load a template file called `homepage.tpl`, from the filesystem, you could write:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->display('homepage.tpl');
```
The filesystem is the default resource. Templates, however, may come
from a variety of sources. When you render a template, or
when you include a template from within another template, you supply a
resource type, followed by `:` and the appropriate path and template name.
If a resource is not explicitly given, the default resource type is assumed.
The resource type for the filesystem is `file`, which means that the previous example
can be rewritten as follows:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->display('file:homepage.tpl');
```
The file resource pulls templates source files from the directories
specified using `Smarty::setTemplateDir()` (see [Configuring Smarty](configuring.md)).
`setTemplateDir` accepts a single path, but can also ben called with an array of paths.
In that case, the list of directories is traversed in the order they appear in the array. The
first template found is the one to process.
### Templates from a specific directory
Smarty 3.1 introduced the bracket-syntax for specifying an element from
`Smarty::setTemplateDir()`. This allows websites
employing multiple sets of templates better control over which template
to access.
The bracket-syntax can be used as follows:
```php
<?php
// setup template directories
$smarty->setTemplateDir([
'./templates', // element: 0, index: 0
'./templates_2', // element: 1, index: 1
'10' => 'templates_10', // element: 2, index: '10'
'foo' => 'templates_foo', // element: 3, index: 'foo'
]);
/*
assume the template structure
./templates/foo.tpl
./templates_2/foo.tpl
./templates_2/bar.tpl
./templates_10/foo.tpl
./templates_10/bar.tpl
./templates_foo/foo.tpl
*/
// regular access
$smarty->display('file:foo.tpl');
// will load ./templates/foo.tpl
// using numeric index
$smarty->display('file:[1]foo.tpl');
// will load ./templates_2/foo.tpl
// using numeric string index
$smarty->display('file:[10]foo.tpl');
// will load ./templates_10/foo.tpl
// using string index
$smarty->display('file:[foo]foo.tpl');
// will load ./templates_foo/foo.tpl
// using "unknown" numeric index (using element number)
$smarty->display('file:[2]foo.tpl');
// will load ./templates_10/foo.tpl
```
And, from within a Smarty template:
```smarty
{include file="file:foo.tpl"}
{* will load ./templates/foo.tpl *}
{include file="file:[1]foo.tpl"}
{* will load ./templates_2/foo.tpl *}
{include file="file:[foo]foo.tpl"}
{* will load ./templates_foo/foo.tpl *}
```
### Using absolute paths
Templates outside the specified template directories
require the `file:` template resource type, followed by the absolute
path to the template (with leading slash).
```php
<?php
$smarty->display('file:/export/templates/index.tpl');
$smarty->display('file:/path/to/my/templates/menu.tpl');
````
And from within a Smarty template:
```smarty
{include file='file:/usr/local/share/templates/navigation.tpl'}
```
> **Note**
>
> With [`Security`](security.md) enabled, access to
> templates outside of the specified templates directories is
> not allowed unless you whitelist those directories.
### Windows file paths
If you are running on Windows, file paths usually include a drive
letter (such as `C:`) at the beginning of the pathname. Be sure to use `file:` in
the path to avoid namespace conflicts and get the desired results.
```php
<?php
$smarty->display('file:C:/export/templates/index.tpl');
$smarty->display('file:F:/path/to/my/templates/menu.tpl');
```
And from within Smarty template:
```smarty
{include file='file:D:/usr/local/share/templates/navigation.tpl'}
```
### Handling missing templates
If the file resource cannot find the requested template, it will check if there is
a default template handler to call. By default, there is none, and Smarty will return an error,
but you can register a default template handler calling `Smarty::registerDefaultTemplateHandler`
with any [callable](https://www.php.net/manual/en/language.types.callable.php).
```php
<?php
$smarty->registerDefaultTemplateHandler([$this, 'handleMissingTemplate']);
// ...
public function handleMissingTemplate($type, $name, &$content, &$modified, Smarty $smarty) {
if (/* ... */) {
// return corrected filepath
return "/tmp/some/foobar.tpl";
} elseif (/* ... */) {
// return a template directly
$content = "the template source";
$modified = time();
return true;
} else {
// tell smarty that we failed
return false;
}
}
```
## The string and eval resources
Smarty can render templates from a string by using the `string:` or
`eval:` resource.
- The `string:` resource behaves much the same as a template file. The
template source is compiled from a string and stores the compiled
template code for later reuse. Each unique template string will
create a new compiled template file. If your template strings are
accessed frequently, this is a good choice. If you have frequently
changing template strings (or strings with low reuse value), the
`eval:` resource may be a better choice, as it doesn\'t save
compiled templates to disk.
- The `eval:` resource evaluates the template source every time a page
is rendered. This is a good choice for strings with low reuse value.
If the same string is accessed frequently, the `string:` resource
may be a better choice.
> **Note**
>
> With a `string:` resource type, each unique string generates a
> compiled file. Smarty cannot detect a string that has changed, and
> therefore will generate a new compiled file for each unique string. It
> is important to choose the correct resource so that you do not fill
> your disk space with wasted compiled strings.
```php
<?php
$smarty->assign('foo', 'value');
$template_string = 'display {$foo} here';
$smarty->display('string:' . $template_string); // compiles for later reuse
$smarty->display('eval:' . $template_string); // compiles every time
```
From within a Smarty template:
```smarty
{include file="string:$template_string"} {* compiles for later reuse *}
{include file="eval:$template_string"} {* compiles every time *}
```
Both `string:` and `eval:` resources may be encoded with
[`urlencode()`](https://www.php.net/urlencode) or
[`base64_encode()`](https://www.php.net/urlencode). This is not necessary
for the usual use of `string:` and `eval:`, but is required when using
either of them in conjunction with the [`extends resource`](#the-extends-resource).
```php
<?php
$smarty->assign('foo','value');
$template_string_urlencode = urlencode('display {$foo} here');
$template_string_base64 = base64_encode('display {$foo} here');
$smarty->display('eval:urlencode:' . $template_string_urlencode); // will decode string using urldecode()
$smarty->display('eval:base64:' . $template_string_base64); // will decode string using base64_decode()
```
From within a Smarty template:
```smarty
{include file="string:urlencode:$template_string_urlencode"} {* will decode string using urldecode() *}
{include file="eval:base64:$template_string_base64"} {* will decode string using base64_decode() *}
```
## The extends resource
The `extends:` resource is used to define child/parent relationships. For details see section of
[Template inheritance](inheritance.md).
> **Note**
>
> Using the extends resource is usually not necessary. If you have a choice, it is normally more flexible and
> intuitive to handle inheritance chains from within the templates using the [{extends} tag](inheritance.md).
When `string:` and `eval:` templates are used, make sure they are properly url or base64 encoded.
The templates within an inheritance chain are not compiled separately. Only a single compiled template will be generated.
(If an `eval:` resource is found within an inheritance chain, its "don't save a compile file" property is superseded by
the `extends:` resource.)
Example:
```php
<?php
$smarty->display('extends:parent.tpl|child.tpl|grandchild.tpl');
// inheritance from multiple template sources
$smarty->display('extends:db:parent.tpl|file:child.tpl|grandchild.tpl|eval:{block name="fooBazVar_"}hello world{/block}');
```
## The stream resource
Smarty allow you to use [PHP streams](https://www.php.net/manual/en/function.stream-wrapper-register.php)
as a template resource. Smarty will first look for a registered template resource. If nothing is
found, it will check if a PHP stream is available. If a stream is available, Smarty will use it
to fetch the template.
For example,
```php
<?php
stream_wrapper_register('myresource', MyResourceStream::class);
$smarty->display('myresource:bar.tpl');
```
Or, from within a template:
```smarty
{include file="myresource:bar.tpl"}
```
## Adding your own resource type
You can create a class that extends `Smarty\Resource\CustomPlugin` to add your own resource type,
for example to load template from a database.
For example:
```php
<?php
class HelloWorldResource extends Smarty\Resource\CustomPlugin {
protected function fetch($name, &$source, &$mtime) {
$source = '{$x="hello world"}{$x}'; // load your template here based on $name
$mtime = time();
}
}
// ..
$smarty->registerResource('helloworld', new HelloWorldResource());
```
If a Resource's templates should not be run through the Smarty
compiler, the Custom Resource may extend `\Smarty\Resource\UncompiledPlugin`.
The Resource Handler must then implement the function
`renderUncompiled(\Smarty\Template $_template)`. `$_template` is
a reference to the current template and contains all assigned variables
which the implementor can access via
`$_template->getSmarty()->getTemplateVars()`. These Resources simply echo
their rendered content to the output stream. The rendered output will be
output-cached if the Smarty instance was configured accordingly. See
`src/Resource/PhpPlugin.php` for an example.
If the Resource's compiled templates should not be cached on disk, the
Custom Resource may extend `\Smarty\Resource\RecompiledPlugin`. These Resources
are compiled every time they are accessed. This may be an expensive
overhead. See `src/Resource/StringEval.php` for an
example.
## Changing the default resource type
The default resource type is `file`. If you want to change it, use `Smarty::setDefaultResourceType`.
The following example will change the default resource type to `mysql`:
```php
<?php
$smarty->setDefaultResourceType('mysql');
```
-119
View File
@@ -1,119 +0,0 @@
# Security
Security is good for situations when you have untrusted parties editing
the templates, and you want to reduce the risk of system
security compromises through the template language.
The settings of the security policy are defined by overriding public properties of an
instance of the \Smarty\Security class. These are the possible settings:
- `$secure_dir` is an array of template directories that are
considered secure. A directory configured using `$smarty->setTemplateDir()` is
considered secure implicitly. The default is an empty array.
- `$trusted_uri` is an array of regular expressions matching URIs that
are considered trusted. This security directive is used by
[`{fetch}`](../designers/language-custom-functions/language-function-fetch.md) and
[`{html_image}`](../designers/language-custom-functions/language-function-html-image.md). URIs passed to
these functions are reduced to `{$PROTOCOL}://{$HOSTNAME}` to allow
simple regular expressions (without having to deal with edge cases
like authentication-tokens).
The expression `'#https?://.*smarty.net$#i'` would allow accessing
the following URIs:
- `http://smarty.net/foo`
- `http://smarty.net/foo`
- `http://www.smarty.net/foo`
- `http://smarty.net/foo`
- `https://foo.bar.www.smarty.net/foo/bla?blubb=1`
but deny access to these URIs:
- `http://smarty.com/foo` (not matching top-level domain \"com\")
- `ftp://www.smarty.net/foo` (not matching protocol \"ftp\")
- `http://www.smarty.net.otherdomain.com/foo` (not matching end of
domain \"smarty.net\")
- `$static_classes` is an array of classes that are considered
trusted. The default is an empty array which allows access to all
static classes. To disable access to all static classes set
$static_classes = null.
- `$streams` is an array of streams that are considered trusted and
can be used from within template. To disable access to all streams
set $streams = null. An empty array ( $streams = [] ) will
allow all streams. The default is array('file').
- `$allowed_modifiers` is an array of (registered / autoloaded)
modifiers that should be accessible to the template. If this array
is non-empty, only the herein listed modifiers may be used. This is
a whitelist.
- `$disabled_modifiers` is an array of (registered / autoloaded)
modifiers that may not be accessible to the template.
- `$allowed_tags` is a boolean flag which controls if constants can
function-, block and filter plugins that should be accessible to the
template. If this array is non-empty, only the herein listed
modifiers may be used. This is a whitelist.
- `$disabled_tags` is an array of (registered / autoloaded) function-,
block and filter plugins that may not be accessible to the template.
- `$allow_constants` is a boolean flag which controls if constants can
be accessed by the template. The default is "true".
- `$allow_super_globals` is a boolean flag which controls if the PHP
super globals can be accessed by the template. The default is
"true".
If security is enabled, no private methods, functions or properties of
static classes or assigned objects can be accessed (beginning with
'_') by the template.
To customize the security policy settings you can extend the
\Smarty\Security class or create an instance of it.
```php
<?php
use Smarty\Smarty;
class My_Security_Policy extends \Smarty\Security {
public $allow_constants = false;
}
$smarty = new Smarty();
$smarty->enableSecurity('My_Security_Policy');
```
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$my_security_policy = new \Smarty\Security($smarty);
$my_security_policy->allow_constants = false;
$smarty->enableSecurity($my_security_policy);
```
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
// enable default security
$smarty->enableSecurity();
```
> **Note**
>
> Most security policy settings are only checked when the template gets
> compiled. For that reason you should delete all cached and compiled
> template files when you change your security settings.
-139
View File
@@ -1,139 +0,0 @@
# Assigning variables
Templates start to become really useful once you know how to use variables.
## Basic assigning
Let's revisit the example from the [basics section](../basics.md). The following script assigns a value to
the 'companyName' variable and renders the template:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$smarty->assign('companyName', 'AC & ME Corp.');
$smarty->display('footer.tpl');
```
footer.tpl:
```smarty
<small>Copyright {$companyName|escape}</small>
```
Smarty will apply the [escape modifier](../../designers/language-modifiers/language-modifier-escape.md)
to the value assigned to the variable
`companyName` and replace `{$companyName|escape}` with the result.
```html
<small>Copyright AC &amp; ME Corp.</small>
```
Using `$smarty->assign()` is the most common way of assigning data to templates, but there are several other methods.
## Appending data to an existing variable
Using `append()`, you can add data to an existing variable, usually an array.
If you append to a string value, it is converted to an array value and
then appended to. You can explicitly pass name/value pairs, or
associative arrays containing the name/value pairs. If you pass the
optional third parameter of TRUE, the value will be merged with the
current array instead of appended.
Examples:
```php
<?php
// This is effectively the same as assign()
$smarty->append('foo', 'Fred');
// After this line, foo will now be seen as an array in the template
$smarty->append('foo', 'Albert');
$array = [1 => 'one', 2 => 'two'];
$smarty->append('X', $array);
$array2 = [3 => 'three', 4 => 'four'];
// The following line will add a second element to the X array
$smarty->append('X', $array2);
// passing an associative array
$smarty->append(['city' => 'Lincoln', 'state' => 'Nebraska']);
```
## Assigning to template objects
When you use a template objects, as explained in [rendering a template](../rendering.md#creating-a-template-object),
you can assign data to the template objects directly instead of assigning it to Smarty. This way, you can use different
sets of data for different templates.
For example:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty();
$tplBlue = $smarty->createTemplate('blue.tpl');
$tplBlue->assign('name', 'The one');
$tplBlue->display();
$tplRed = $smarty->createTemplate('red.tpl');
$tplRed->assign('name', 'Neo');
$tplRed->display();
```
## Using data objects
For more complex use cases, Smarty supports the concept of data objects.
Data objects are containers to hold data. Data objects can be attached to templates when creating them.
This allows for fine-grained re-use of data.
For example:
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
// create a data object
$data = $smarty->createData();
// assign variable to the data object
$data->assign('name', 'Neo');
// create template object which will use variables from the data object
$tpl = $smarty->createTemplate('index.tpl', $data);
// display the template
$tpl->display();
```
## Clearing assigned data
When re-using templates, you may need to clear data assigned in a previous run. Use `clearAllAssign()` to
clear the values of all assigned variables on data objects, template objects or the Smarty object.
Examples:
```php
<?php
// assigning data to the Smarty object
$smarty->assign('Name', 'Fred');
// ...
$smarty->clearAllAssign();
// using a data object
$data = $smarty->createData();
$data->assign('name', 'Neo');
// ...
$data->clearAllAssign();
// using a template
$tplBlue = $smarty->createTemplate('blue.tpl');
$tplBlue->assign('name', 'The one');
// ...
$tplBlue->clearAllAssign();
```
Note that there it's only useful to clear assigned data if you:
1. repeatedly re-use templates, and
2. the variables used may change on each repetition
If your script simply runs once and then ends, or you always assign the same variables, clearing assigned data
is of no use.
-88
View File
@@ -1,88 +0,0 @@
# Loading data from config files
Instead of [assigning data to templates from PHP](assigning.md), you can also
use a config file.
## Example config file
Config files are best suited to manage template settings
from one file. One example is a multi-language application.
Instead of writing multiple templates to support different languages,
you can write a single template file and load your language dependent strings
from config files.
Example `lang.en.ini`:
```ini
# global variables
pageTitle = "Main Menu"
[Customer]
pageTitle = "Customer Info"
[Login]
pageTitle = "Login"
focus = "username"
Intro = """This is a value that spans more
than one line. you must enclose
it in triple quotes."""
```
Values of [config file variables](../../designers/language-variables/language-config-variables.md) can be in
quotes, but not necessary. You can use either single or double quotes.
If you have a value that spans more than one line, enclose the entire
value with triple quotes \("""\). You can put comments into config
files by any syntax that is not a valid config file syntax. We recommend
using a `#` (hash) at the beginning of the line.
The example config file above has two sections. Section names are
enclosed in \[brackets\]. Section names can be arbitrary strings not
containing `[` or `]` symbols. The variable at the top is a global
variable. Global variables are always
loaded from the config file. If a particular section is loaded, then the
global variables and the variables from that section are also loaded. If
a variable exists both as a global and in a section, the section
variable is used.
## Loading a config file
Config files are loaded into templates with the built-in template
function [`{config_load}`](../../designers/language-builtin-functions/language-function-config-load.md) or by calling
`configLoad()` from PHP:
```php
<?php
$smarty->configLoad('lang.en.ini');
```
Load a specific section with:
```php
<?php
$smarty->configLoad('lang.en.ini', 'Customer');
```
Note that the global section will always be loaded.
## Retrieving config variables in PHP
## Loading from a resource
Config files (or resources) are loaded by the same resource facilities
as templates. That means that a config file can also be loaded from a db. See [resources](../resources.md)
for more information.
## Config overwrite
If you name two variables the same within a section,
the last one will be used unless you call:
```php
<?php
$smarty->setConfigOverwrite(false);
```
When config overwrite is disabled, Smarty will create arrays of config file variables when it encounters
multiple entries with the same name.
See also [`{config_load}`](../../designers/language-builtin-functions/language-function-config-load.md),
[`$default_config_handler_func`](../../programmers/api-variables/variable-default-config-handler-func.md),
[`getConfigVars()`](../../programmers/api-functions/api-get-config-vars.md),
[`clearConfig()`](../../programmers/api-functions/api-clear-config.md) and
[`configLoad()`](../../programmers/api-functions/api-config-load.md)
-106
View File
@@ -1,106 +0,0 @@
# Objects
Smarty allows access to PHP [objects](https://www.php.net/object) through
the templates.
> **Note**
>
> When you assign/register objects to templates, be sure that all
> properties and methods accessed from the template are for presentation
> purposes only. It is very easy to inject application logic through
> objects, and this leads to poor designs that are difficult to manage.
> See the Best Practices section of the Smarty website.
There are two ways to access them.
## Assign the object
You can assign objects to a template and access them much like any other assigned variable.
Example:
```php
<?php
// the object
class My_Object {
public function meth1($params, $smarty_obj) {
return 'this is my meth1';
}
}
// We can also assign objects. assign_by_ref when possible.
$smarty->assign('myobj', new My_Object());
$smarty->display('index.tpl');
```
And here's how to access your object in `index.tpl`:
```smarty
{$myobj->meth1('foo',$bar)}
```
## Register the object
Registerd objects use a different template syntax. Also, a registered object
can be restricted to certain methods or
properties. However, **a registered object cannot be looped over or
assigned in arrays of objects**, etc.
If security is enabled, no private methods or functions can be accessed
(beginning with '_'). If a method and property of the same name exist,
the method will be used.
You can restrict the methods and properties that can be accessed by
listing them in an array as the third registration parameter.
By default, parameters passed to objects through the templates are
passed the same way [custom tags](../../designers/language-custom-functions/index.md) get
them. An associative array is passed as the first parameter, and the
smarty object as the second. If you want the parameters passed one at a
time for each argument like traditional object parameter passing, set
the fourth registration parameter to FALSE.
The optional fifth parameter has only effect with `format` being TRUE
and contains a list of methods that should be treated as blocks. That
means these methods have a closing tag in the template
(`{foobar->meth2}...{/foobar->meth2}`) and the parameters to the methods
have the same synopsis as the parameters for
[`block tags`](../extending/block-tags.md): They get the four
parameters `$params`, `$content`, `$smarty` and `&$repeat` and they also
behave like block tags.
```php
<?php
// the object
class My_Object {
function meth1($params, $smarty_obj) {
return 'this is my meth1';
}
}
$myobj = new My_Object;
// registering the object
$smarty->registerObject('foobar', $myobj);
// if we want to restrict access to certain methods or properties, list them
$smarty->registerObject('foobar', $myobj, array('meth1','meth2','prop1'));
// if you want to use the traditional object parameter format, pass a boolean of false
$smarty->registerObject('foobar', $myobj, null, false);
$smarty->display('index.tpl');
```
And here's how to access your objects in `index.tpl`:
```smarty
{* access our registered object *}
{foobar->meth1 p1='foo' p2=$bar}
{* you can also assign the output *}
{foobar->meth1 p1='foo' p2=$bar assign='output'}
the output was {$output}
```
@@ -1,39 +0,0 @@
# Static Classes
You can directly access static classes. The syntax is roughly the same as in
PHP.
> **Note**
>
> Direct access to PHP classes is not recommended. This ties the
> underlying application code structure directly to the presentation,
> and also complicates template syntax. It is recommended to register
> plugins which insulate templates from PHP classes/objects. Use at your
> own discretion.
## Examples
**class constant BAR**
```smarty
{assign var=foo value=myclass::BAR}
```
**method result**
```smarty
{assign var=foo value=myclass::method()}
```
**method chaining**
```smarty
{assign var=foo value=myclass::method1()->method2}
```
**property bar of class myclass**
```smarty
{assign var=foo value=myclass::$bar}
```
**using Smarty variable bar as class name**
```smarty
{assign var=foo value=$bar::method}
```
-13
View File
@@ -1,13 +0,0 @@
# Streams
You can also use streams to call variables. *{$foo:bar}* will use the
*foo://bar* stream to get the template variable.
Using a PHP stream for a template variable resource from within a
template.
```smarty
{$foo:bar}
```
See also [`Template Resources`](../resources.md)
-273
View File
@@ -1,273 +0,0 @@
# Tips & Tricks
## Blank Variable Handling
There may be times when you want to print a default value for an empty
variable instead of printing nothing, such as printing `&nbsp;` so that
html table backgrounds work properly. Many would use an
[`{if}`](../designers/language-builtin-functions/language-function-if.md) statement to handle this, but there is a
shorthand way with Smarty, using the
[`default`](../designers/language-modifiers/language-modifier-default.md) variable modifier.
> **Note**
>
> "Undefined variable" errors will show an E\_NOTICE if not disabled in
> PHP's [`error_reporting()`](https://www.php.net/error_reporting) level or
> Smarty's [`$error_reporting`](../programmers/api-variables/variable-error-reporting.md) property and
> a variable had not been assigned to Smarty.
```smarty
{* the long way *}
{if $title eq ''}
&nbsp;
{else}
{$title}
{/if}
{* the short way *}
{$title|default:'&nbsp;'}
```
See also [`default`](../designers/language-modifiers/language-modifier-default.md) modifier and [default
variable handling](#default-variable-handling).
## Default Variable Handling
If a variable is used frequently throughout your templates, applying the
[`default`](../designers/language-modifiers/language-modifier-default.md) modifier every time it is
mentioned can get a bit ugly. You can remedy this by assigning the
variable its default value with the
[`{assign}`](../designers/language-builtin-functions/language-function-assign.md) function.
{* do this somewhere at the top of your template *}
{assign var='title' value=$title|default:'no title'}
{* if $title was empty, it now contains the value "no title" when you use it *}
{$title}
See also [`default`](../designers/language-modifiers/language-modifier-default.md) modifier and [blank
variable handling](#blank-variable-handling).
## Passing variable title to header template
When the majority of your templates use the same headers and footers, it
is common to split those out into their own templates and
[`{include}`](../designers/language-builtin-functions/language-function-include.md) them. But what if the header
needs to have a different title, depending on what page you are coming
from? You can pass the title to the header as an
[attribute](../designers/language-basic-syntax/language-syntax-attributes.md) when it is included.
`mainpage.tpl` - When the main page is drawn, the title of "Main Page"
is passed to the `header.tpl`, and will subsequently be used as the
title.
```smarty
{include file='header.tpl' title='Main Page'}
{* template body goes here *}
{include file='footer.tpl'}
```
`archives.tpl` - When the archives page is drawn, the title will be
"Archives". Notice in the archive example, we are using a variable from
the `archives_page.conf` file instead of a hard coded variable.
```smarty
{config_load file='archive_page.conf'}
{include file='header.tpl' title=#archivePageTitle#}
{* template body goes here *}
{include file='footer.tpl'}
```
`header.tpl` - Notice that "Smarty News" is printed if the `$title`
variable is not set, using the [`default`](../designers/language-modifiers/language-modifier-default.md)
variable modifier.
```smarty
<html>
<head>
<title>{$title|default:'Smarty News'}</title>
</head>
<body>
```
`footer.tpl`
```smarty
</body>
</html>
```
## Dates
As a rule of thumb, always pass dates to Smarty as
[timestamps](https://www.php.net/time). This allows template designers to
use the [`date_format`](../designers/language-modifiers/language-modifier-date-format.md) modifier for
full control over date formatting, and also makes it easy to compare
dates if necessary.
```smarty
{$startDate|date_format}
```
This will output:
```
Jan 4, 2009
```
```smarty
{$startDate|date_format:"%Y/%m/%d"}
```
This will output:
```
2009/01/04
```
Dates can be compared in the template by timestamps with:
```smarty
{if $order_date < $invoice_date}
...do something..
{/if}
```
When using [`{html_select_date}`](../designers/language-custom-functions/language-function-html-select-date.md)
in a template, the programmer will most likely want to convert the
output from the form back into timestamp format. Here is a function to
help you with that.
```php
<?php
// this assumes your form elements are named
// startDate_Day, startDate_Month, startDate_Year
$startDate = makeTimeStamp($startDate_Year, $startDate_Month, $startDate_Day);
function makeTimeStamp($year='', $month='', $day='')
{
if(empty($year)) {
$year = strftime('%Y');
}
if(empty($month)) {
$month = strftime('%m');
}
if(empty($day)) {
$day = strftime('%d');
}
return mktime(0, 0, 0, $month, $day, $year);
}
```
See also [`{html_select_date}`](../designers/language-custom-functions/language-function-html-select-date.md),
[`{html_select_time}`](../designers/language-custom-functions/language-function-html-select-time.md),
[`date_format`](../designers/language-modifiers/language-modifier-date-format.md) and
[`$smarty.now`](../designers/language-variables/language-variables-smarty.md#smarty-now),
## Componentized Templates
Traditionally, programming templates into your applications goes as
follows: First, you accumulate your variables within your PHP
application, (maybe with database queries.) Then, you instantiate your
Smarty object, [`assign()`](../programmers/api-functions/api-assign.md) the variables and
[`display()`](../programmers/api-functions/api-display.md) the template. So lets say for example we
have a stock ticker on our template. We would collect the stock data in
our application, then assign these variables in the template and display
it. Now wouldn't it be nice if you could add this stock ticker to any
application by merely including the template, and not worry about
fetching the data up front?
You can do this by writing a custom plugin for fetching the content and
assigning it to a template variable.
`function.load_ticker.php`
```php
<?php
// setup our function for fetching stock data
function fetch_ticker($symbol)
{
// put logic here that fetches $ticker_info
// from some ticker resource
return $ticker_info;
}
function smarty_function_load_ticker($params, $smarty)
{
// call the function
$ticker_info = fetch_ticker($params['symbol']);
// assign template variable
$smarty->assign($params['assign'], $ticker_info);
}
```
`index.tpl`
```smarty
{load_ticker symbol='SMARTY' assign='ticker'}
Stock Name: {$ticker.name} Stock Price: {$ticker.price}
```
See also: [`{include}`](../designers/language-builtin-functions/language-function-include.md).
## Obfuscating E-mail Addresses
Do you ever wonder how your email address gets on so many spam mailing
lists? One way spammers collect email addresses is from web pages. To
help combat this problem, you can make your email address show up in
scrambled javascript in the HTML source, yet it it will look and work
correctly in the browser. This is done with the
[`{mailto}`](../designers/language-custom-functions/language-function-mailto.md) plugin.
```smarty
<div id="contact">Send inquiries to
{mailto address=$EmailAddress encode='javascript' subject='Hello'}
</div>
```
> **Note**
>
> This method isn\'t 100% foolproof. A spammer could conceivably program
> his e-mail collector to decode these values, but not likely\....
> hopefully..yet \... wheres that quantum computer :-?.
See also [`escape`](../designers/language-modifiers/language-modifier-escape.md) modifier and
[`{mailto}`](../designers/language-custom-functions/language-function-mailto.md).
-104
View File
@@ -1,104 +0,0 @@
# Troubleshooting
## Smarty/PHP errors
Smarty can catch many errors such as missing tag attributes or malformed
variable names. If this happens, you will see an error similar to the
following:
```
Warning: Smarty: [in index.tpl line 4]: syntax error: unknown tag - '%blah'
in /path/to/smarty/Smarty.class.php on line 1041
Fatal error: Smarty: [in index.tpl line 28]: syntax error: missing section name
in /path/to/smarty/Smarty.class.php on line 1041
```
Smarty shows you the template name, the line number and the error. After
that, the error consists of the actual line number in the Smarty class
that the error occurred.
There are certain errors that Smarty cannot catch, such as missing close
tags. These types of errors usually end up in PHP compile-time parsing
errors.
`Parse error: parse error in /path/to/smarty/templates_c/index.tpl.php on line 75`
When you encounter a PHP parsing error, the error line number will
correspond to the compiled PHP script, NOT the template itself. Usually
you can look at the template and spot the syntax error. Here are some
common things to look for: missing close tags for
[`{if}{/if}`](../designers/language-builtin-functions/language-function-if.md) or
[`{section}{/section}`](../designers/language-builtin-functions/language-function-section.md),
or syntax of logic within an `{if}` tag. If you can\'t find the error, you might have to
open the compiled PHP file and go to the line number to figure out where
the corresponding error is in the template.
```
Warning: Smarty error: unable to read resource: "index.tpl" in...
```
or
```
Warning: Smarty error: unable to read resource: "site.conf" in...
```
- The [`$template_dir`](../programmers/api-variables/variable-template-dir.md) is incorrect, doesn't
exist or the file `index.tpl` is not in the `templates/` directory
- A [`{config_load}`](../designers/language-builtin-functions/language-function-config-load.md) function is
within a template (or [`configLoad()`](../programmers/api-functions/api-config-load.md) has been
called) and either [`$config_dir`](../programmers/api-variables/variable-config-dir.md) is
incorrect, does not exist or `site.conf` is not in the directory.
```
Fatal error: Smarty error: the $compile_dir 'templates_c' does not exist,
or is not a directory...
```
- Either the [`$compile_dir`](../programmers/api-variables/variable-compile-dir.md)is incorrectly
set, the directory does not exist, or `templates_c` is a file and
not a directory.
```
Fatal error: Smarty error: unable to write to $compile_dir '....
```
- The [`$compile_dir`](../programmers/api-variables/variable-compile-dir.md) is not writable by the
web server. See the bottom of the [installing
smarty](../getting-started.md#installation) page for more about permissions.
```
Fatal error: Smarty error: the $cache_dir 'cache' does not exist,
or is not a directory. in /..
```
- This means that [`$caching`](../programmers/api-variables/variable-caching.md) is enabled and
either; the [`$cache_dir`](../programmers/api-variables/variable-cache-dir.md) is incorrectly set,
the directory does not exist, or `cache/` is a file and not a
directory.
```
Fatal error: Smarty error: unable to write to $cache_dir '/...
```
- This means that [`$caching`](../programmers/api-variables/variable-caching.md) is enabled and the
[`$cache_dir`](../programmers/api-variables/variable-cache-dir.md) is not writable by the web
server. See the bottom of the [installing
smarty](../getting-started.md#installation) page for permissions.
```
Warning: filemtime(): stat failed for /path/to/smarty/cache/3ab50a623e65185c49bf17c63c90cc56070ea85c.one.tpl.php
in /path/to/smarty/libs/sysplugins/smarty_resource.php
```
- This means that your application registered a custom error handler
(using [set_error_handler()](https://www.php.net/set_error_handler))
which is not respecting the given `$errno` as it should. If, for
whatever reason, this is the desired behaviour of your custom error
handler, please call
[`muteExpectedErrors()`](../programmers/api-functions/api-mute-expected-errors.md) after you've
registered your custom error handler.
See also [debugging](../designers/chapter-debugging-console.md).
@@ -1,39 +0,0 @@
# Debugging Console
There is a debugging console included with Smarty. The console informs
you of all the [included](./language-builtin-functions/language-function-include.md) templates,
[assigned](../programmers/api-functions/api-assign.md) variables and
[config](./language-variables/language-config-variables.md) file variables for the current
invocation of the template. A template file named `debug.tpl` is
included with the distribution of Smarty which controls the formatting
of the console.
Set [`$debugging`](../programmers/api-variables/variable-debugging.md) to TRUE in Smarty, and if needed
set [`$debug_tpl`](../programmers/api-variables/variable-debug-template.md) to the template resource
path to `debug.tpl`. When you load the page, a Javascript console window will pop
up and give you the names of all the included templates and assigned
variables for the current page.
To see the available variables for a particular template, see the
[`{debug}`](./language-builtin-functions/language-function-debug.md) template function. To disable the
debugging console, set [`$debugging`](../programmers/api-variables/variable-debugging.md) to FALSE. You
can also temporarily turn on the debugging console by putting
`SMARTY_DEBUG` in the URL if you enable this option with
[`$debugging_ctrl`](../programmers/api-variables/variable-debugging-ctrl.md).
> **Note**
>
> The debugging console does not work when you use the
> [`fetch()`](../programmers/api-functions/api-fetch.md) API, only when using
> [`display()`](../programmers/api-functions/api-display.md). It is a set of javascript statements
> added to the very bottom of the generated template. If you do not like
> javascript, you can edit the `debug.tpl` template to format the output
> however you like. Debug data is not cached and `debug.tpl` info is not
> included in the output of the debug console.
> **Note**
>
> The load times of each template and config file are in seconds, or
> fractions thereof.
See also [troubleshooting](../appendixes/troubleshooting.md).
-74
View File
@@ -1,74 +0,0 @@
# Config Files
Config files are handy for designers to manage global template variables
from one file. One example is template colors. Normally if you wanted to
change the color scheme of an application, you would have to go through
each and every template file and change the colors. With a config file,
the colors can be kept in one place, and only one file needs to be
updated.
```ini
# global variables
pageTitle = "Main Menu"
bodyBgColor = #000000
tableBgColor = #000000
rowBgColor = #00ff00
[Customer]
pageTitle = "Customer Info"
[Login]
pageTitle = "Login"
focus = "username"
Intro = """This is a value that spans more
than one line. you must enclose
it in triple quotes."""
# hidden section
[.Database]
host=my.example.com
db=ADDRESSBOOK
user=php-user
pass=foobar
```
Values of [config file variables](./language-variables/language-config-variables.md) can be in
quotes, but not necessary. You can use either single or double quotes.
If you have a value that spans more than one line, enclose the entire
value with triple quotes \("""\). You can put comments into config
files by any syntax that is not a valid config file syntax. We recommend
using a `#` (hash) at the beginning of the line.
The example config file above has two sections. Section names are
enclosed in \[brackets\]. Section names can be arbitrary strings not
containing `[` or `]` symbols. The four variables at the top are global
variables, or variables not within a section. These variables are always
loaded from the config file. If a particular section is loaded, then the
global variables and the variables from that section are also loaded. If
a variable exists both as a global and in a section, the section
variable is used. If you name two variables the same within a section,
the last one will be used unless
[`$config_overwrite`](../programmers/api-variables/variable-config-overwrite.md) is disabled.
Config files are loaded into templates with the built-in template
function [`{config_load}`](./language-builtin-functions/language-function-config-load.md) or the API
[`configLoad()`](../programmers/api-functions/api-config-load.md) function.
You can hide variables or entire sections by prepending the variable
name or section name with a period(.) eg `[.hidden]`. This is useful if
your application reads the config files and gets sensitive data from
them that the template engine does not need. If you have third parties
doing template editing, you can be certain that they cannot read
sensitive data from the config file by loading it into the template.
Config files (or resources) are loaded by the same resource facilities
as templates. That means that a config file can also be loaded from a db
`$smarty->configLoad("db:my.conf")`.
See also [`{config_load}`](./language-builtin-functions/language-function-config-load.md),
[`$config_overwrite`](../programmers/api-variables/variable-config-overwrite.md),
[`$default_config_handler_func`](../programmers/api-variables/variable-default-config-handler-func.md),
[`getConfigVars()`](../programmers/api-functions/api-get-config-vars.md),
[`clearConfig()`](../programmers/api-functions/api-clear-config.md) and
[`configLoad()`](../programmers/api-functions/api-config-load.md)
@@ -1,33 +0,0 @@
# Basic Syntax
A simple Smarty template could look like this:
```smarty
<h1>{$title|escape}</h1>
<ul>
{foreach $cities as $city}
<li>{$city.name|escape} ({$city.population})</li>
{foreachelse}
<li>no cities found</li>
{/foreach}
</ul>
```
All Smarty template tags are enclosed within delimiters. By default
these are `{` and `}`, but they can be
[changed](../../designers/language-basic-syntax/language-escaping.md).
For the examples in this manual, we will assume that you are using the
default delimiters. In Smarty, all content outside of delimiters is
displayed as static content, or unchanged. When Smarty encounters
template tags, it attempts to interpret them, and displays the
appropriate output in their place.
The basic components of the Smarty syntax are:
- [Comments](language-syntax-comments.md)
- [Variables](language-syntax-variables.md)
- [Operators](language-syntax-operators.md)
- [Tags](language-syntax-tags.md)
- [Attributes](language-syntax-attributes.md)
- [Quotes](language-syntax-quotes.md)
- [Escaping](language-escaping.md)
@@ -1,78 +0,0 @@
# Escaping Smarty parsing
It is sometimes desirable or even necessary to have Smarty ignore
sections it would otherwise parse. A classic example is embedding
Javascript or CSS code in a template. The problem arises as those
languages use the { and } characters which are also the default
[delimiters](../language-builtin-functions/language-function-ldelim.md) for Smarty.
> **Note**
>
> A good practice for avoiding escapement altogether is by separating
> your Javascript/CSS into their own files and use standard HTML methods
> to access them. This will also take advantage of browser script
> caching. When you need to embed Smarty variables/functions into your
> Javascript/CSS, then the following applies.
In Smarty templates, the { and } braces will be ignored so long as they
are surrounded by white space. This behavior can be disabled by setting
the Smarty class variable [`$auto_literal`](../../programmers/api-variables/variable-auto-literal.md) to
false.
## Examples
```smarty
<script>
// the following braces are ignored by Smarty
// since they are surrounded by whitespace
function foobar {
alert('foobar!');
}
// this one will need literal escapement
{literal}
function bazzy {alert('foobar!');}
{/literal}
</script>
```
[`{literal}..{/literal}`](../language-builtin-functions/language-function-literal.md) blocks are used
for escaping blocks of template logic. You can also escape the braces
individually with
[`{ldelim}`, `{rdelim}`](../language-builtin-functions/language-function-ldelim.md) tags or
[`{$smarty.ldelim}`,`{$smarty.rdelim}`](../language-variables/language-variables-smarty.md#smartyldelim-smartyrdelim-languagevariablessmartyldelim)
variables.
Smarty's default delimiters { and } cleanly represent presentational
content. However, if another set of delimiters suit your needs better,
you can change them with Smarty's
`setLeftDelimiter()` and `setRightDelimiter()` methods.
> **Note**
>
> Changing delimiters affects ALL template syntax and escapement. Be
> sure to clear out cache and compiled files if you decide to change
> them.
```php
<?php
$smarty->setLeftDelimiter('<!--{');
$smarty->setRightDelimiter('}-->');
$smarty->assign('foo', 'bar');
$smarty->assign('name', 'Albert');
$smarty->display('example.tpl');
```
Where the template is:
```smarty
Welcome <!--{$name}--> to Smarty
<script>
var foo = <!--{$foo}-->;
function dosomething() {
alert("foo is " + foo);
}
dosomething();
</script>
```
@@ -1,49 +0,0 @@
# Attributes
Most of the [tags](./language-syntax-tags.md) take attributes that
specify or modify their behavior. Attributes to Smarty functions are
much like HTML attributes. Static values don't have to be enclosed in
quotes, but it is required for literal strings. Variables with or
without modifiers may also be used, and should not be in quotes. You can
even use PHP function results, plugin results and complex expressions.
Some attributes require boolean values (TRUE or FALSE). These can be
specified as `true` and `false`. If an attribute has no value assigned
it gets the default boolean value of true.
## Examples
```smarty
{include file="header.tpl"}
{include file="header.tpl" nocache} // is equivalent to nocache=true
{include file="header.tpl" attrib_name="attrib value"}
{include file=$includeFile}
{include file=#includeFile# title="My Title"}
{assign var=foo value={counter}} // plugin result
{assign var=foo value=substr($bar,2,5)} // PHP function result
{assign var=foo value=$bar|strlen} // using modifier
{assign var=foo value=$buh+$bar|strlen} // more complex expression
{html_select_date display_days=true}
{mailto address="smarty@example.com"}
<select name="company_id">
{html_options options=$companies selected=$company_id}
</select>
```
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
@@ -1,69 +0,0 @@
# Comments
Template comments are surrounded by asterisks, and that is surrounded by
the [delimiter](../../designers/language-basic-syntax/language-escaping.md) tags like so:
## Examples
```smarty
{* this is a comment *}
```
Smarty comments are NOT displayed in the final output of the template,
unlike `<!-- HTML comments -->`. These are useful for making internal
notes in the templates which no one will see ;-)
```smarty
{* I am a Smarty comment, I don't exist in the compiled output *}
<html>
<head>
<title>{$title}</title>
</head>
<body>
{* another single line smarty comment *}
<!-- HTML comment that is sent to the browser -->
{* this multiline smarty
comment is
not sent to browser
*}
{*********************************************************
Multi line comment block with credits block
@ author: bg@example.com
@ maintainer: support@example.com
@ para: var that sets block style
@ css: the style output
**********************************************************}
{* The header file with the main logo and stuff *}
{include file='header.tpl'}
{* Dev note: the $includeFile var is assigned in foo.php script *}
<!-- Displays main content block -->
{include file=$includeFile}
{* this <select> block is redundant *}
{*
<select name="company">
{html_options options=$vals selected=$selected_id}
</select>
*}
<!-- Show header from affiliate is disabled -->
{* $affiliate|upper *}
{* you cannot nest comments *}
{*
<select name="company">
{* <option value="0">-- none -- </option> *}
{html_options options=$vals selected=$selected_id}
</select>
*}
</body>
</html>
```
@@ -1,64 +0,0 @@
# Operators
## Basic
Various basic operators can be applied directly to variable values.
## Examples
```smarty
{$foo + 1}
{$foo * $bar}
{$foo->bar - $bar[1] * $baz->foo->bar() -3 * 7}
{if ($foo + $bar.test % $baz * 134232 + 10 + $b + 10)}
...
{/if}
{$foo = $foo + $bar}
```
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
## Ternary
You can use the `?:` (or ternary) operator to test one expression and present the value
of the second or third expression, based on the result of the test.
In other words:
```smarty
{$test ? "OK" : "FAIL"}
```
will result in OK if `$test` is set to true, and in FAIL otherwise.
There is also a shorthand `?:` operator:
```smarty
{$myVar ?: "empty"}
```
will result in 'empty' if `$myVar` is not set or set to something that evaluates to false, such as an empty string.
If `$myVar` is set to something that evaluates to true, the value of `$myVar` is returned. So, the following will
return 'hello':
```smarty
{$myVar="hello"}
{$myVar ?: "empty"}
```
## Testing for null
If "something that evaluates to false" is to broad a test for you, you can use the `??` (or null coalescing) operator
to trigger only if the tested value is undefined or set to null.
```smarty
{$myVar ?? "empty"}
```
will result in 'empty' if `$myVar` is not set or set to null.
If `$myVar` is set to something that evaluates to anything else, the value of `$myVar` is returned. So, the following will
return an empty string (''):
```smarty
{$myVar=""}
{$myVar ?: "this is not shown"}
```
@@ -1,54 +0,0 @@
# Embedding Vars in Double Quotes
- Smarty will recognize [assigned](../../programmers/api-functions/api-assign.md)
[variables](./language-syntax-variables.md) embedded in "double
quotes" so long as the variable name contains only numbers, letters
and under_scores. See [naming](https://www.php.net/language.variables)
for more detail.
- With any other characters, for example a period(.) or
`$object->reference`, then the variable must be surrounded by `` `backticks` ``.
- In addition, Smarty does allow embedded Smarty tags in double-quoted
strings. This is useful if you want to include variables with
modifiers, plugin or PHP function results.
## Examples
```smarty
{func var="test $foo test"} // sees $foo
{func var="test $foo_bar test"} // sees $foo_bar
{func var="test `$foo[0]` test"} // sees $foo[0]
{func var="test `$foo[bar]` test"} // sees $foo[bar]
{func var="test $foo.bar test"} // sees $foo (not $foo.bar)
{func var="test `$foo.bar` test"} // sees $foo.bar
{func var="test `$foo.bar` test"|escape} // modifiers outside quotes!
{func var="test {$foo|escape} test"} // modifiers inside quotes!
{func var="test {time()} test"} // PHP function result
{func var="test {counter} test"} // plugin result
{func var="variable foo is {if !$foo}not {/if} defined"} // Smarty block function
{* will replace $tpl_name with value *}
{include file="subdir/$tpl_name.tpl"}
{* does NOT replace $tpl_name *}
{include file='subdir/$tpl_name.tpl'} // vars require double quotes!
{* must have backticks as it contains a dot "." *}
{cycle values="one,two,`$smarty.config.myval`"}
{* must have backticks as it contains a dot "." *}
{include file="`$module.contact`.tpl"}
{* can use variable with dot syntax *}
{include file="`$module.$view`.tpl"}
```
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
See also [`escape`](../language-modifiers/language-modifier-escape.md).
@@ -1,39 +0,0 @@
# Tags
Every Smarty tag either prints a [variable](./language-syntax-variables.md) or
invokes some sort of function. These are processed and displayed by
enclosing the function and its [attributes](./language-syntax-attributes.md)
within delimiters like so: `{funcname attr1="val1" attr2="val2"}`.
## Examples
```smarty
{config_load file="colors.conf"}
{include file="header.tpl"}
{if $logged_in}
Welcome, <span style="color:{#fontColor#}">{$name}!</span>
{else}
hi, {$name}
{/if}
{include file="footer.tpl"}
```
- Both [built-in functions](../language-builtin-functions/index.md) and [custom
functions](../language-custom-functions/index.md) have the same syntax within
templates.
- Built-in functions are the **inner** workings of Smarty, such as
[`{if}`](../language-builtin-functions/language-function-if.md),
[`{section}`](../language-builtin-functions/language-function-section.md) and
[`{strip}`](../language-builtin-functions/language-function-strip.md). There should be no need to
change or modify them.
- Custom tags are **additional** tags implemented via
[plugins](../../api/extending/introduction.md). They can be modified to your liking, or you can
create new ones. [`{html_options}`](../language-custom-functions/language-function-html-options.md)
is an example of a custom function.
See also [`registerPlugin()`](../../programmers/api-functions/api-register-plugin.md)
@@ -1,106 +0,0 @@
# Variables
Template variables start with the $dollar sign. They can contain
numbers, letters and underscores, much like a [PHP
variable](https://www.php.net/language.variables). You can reference arrays
by index numerically or non-numerically. Also reference object
properties and methods.
[Config file variables](../language-variables/language-config-variables.md) are an exception to
the \$dollar syntax and are instead referenced with surrounding
\#hashmarks\#, or via the [`$smarty.config`](../language-variables/language-variables-smarty.md#smartyconfig-languagevariablessmartyconfig) variable.
## Examples
```smarty
{$foo} <-- displaying a simple variable (non array/object)
{$foo[4]} <-- display the 5th element of a zero-indexed array
{$foo.bar} <-- display the "bar" key value of an array, similar to PHP $foo['bar']
{$foo.$bar} <-- display variable key value of an array, similar to PHP $foo[$bar]
{$foo->bar} <-- display the object property "bar"
{$foo->bar()} <-- display the return value of object method "bar"
{#foo#} <-- display the config file variable "foo"
{$smarty.config.foo} <-- synonym for {#foo#}
{$foo[bar]} <-- syntax only valid in a section loop, see {section}
{assign var=foo value='baa'}{$foo} <-- displays "baa", see {assign}
Many other combinations are allowed
{$foo.bar.baz}
{$foo.$bar.$baz}
{$foo[4].baz}
{$foo[4].$baz}
{$foo.bar.baz[4]}
{$foo->bar($baz,2,$bar)} <-- passing parameters
{"foo"} <-- static values are allowed
{* display the server variable "SERVER_NAME" ($_SERVER['SERVER_NAME'])*}
{$smarty.server.SERVER_NAME}
Math and embedding tags:
{$x+$y} // will output the sum of x and y.
{assign var=foo value=$x+$y} // in attributes
{$foo[$x+3]} // as array index
{$foo={counter}+3} // tags within tags
{$foo="this is message {counter}"} // tags within double quoted strings
Defining Arrays:
{assign var=foo value=[1,2,3]}
{assign var=foo value=['y'=>'yellow','b'=>'blue']}
{assign var=foo value=[1,[9,8],3]} // can be nested
Short variable assignment:
{$foo=$bar+2}
{$foo = strlen($bar)} // function in assignment
{$foo = myfunct( ($x+$y)*3 )} // as function parameter
{$foo.bar=1} // assign to specific array element
{$foo.bar.baz=1}
{$foo[]=1} // appending to an array
Smarty "dot" syntax (note: embedded {} are used to address ambiguities):
{$foo.a.b.c} => $foo['a']['b']['c']
{$foo.a.$b.c} => $foo['a'][$b]['c'] // with variable index
{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] // with expression as index
{$foo.a.{$b.c}} => $foo['a'][$b['c']] // with nested index
PHP-like syntax, alternative to "dot" syntax:
{$foo[1]} // normal access
{$foo['bar']}
{$foo['bar'][1]}
{$foo[$x+$x]} // index may contain any expression
{$foo[$bar[1]]} // nested index
{$foo[section_name]} // smarty {section} access, not array access!
Variable variables:
$foo // normal variable
$foo_{$bar} // variable name containing other variable
$foo_{$x+$y} // variable name containing expressions
$foo_{$bar}_buh_{$blar} // variable name with multiple segments
{$foo_{$x}} // will output the variable $foo_1 if $x has a value of 1.
Object chaining:
{$object->method1($x)->method2($y)}
```
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
Request variables such as `$_GET`, `$_SESSION`, etc are available via
the reserved [`$smarty`](../language-variables/language-variables-smarty.md) variable.
See also [`$smarty`](../language-variables/language-variables-smarty.md), [config
variables](../language-variables/language-config-variables.md)
[`{assign}`](../language-builtin-functions/language-function-assign.md) and [`assign()`](../../programmers/api-functions/api-assign.md).
@@ -1,35 +0,0 @@
# Built-in Functions
Smarty comes with several built-in functions. These built-in functions
are the integral part of the smarty template engine. They are compiled
into corresponding inline PHP code for maximum performance.
You cannot create your own [custom tags](../language-custom-functions/index.md) with the same name; and you
should not need to modify the built-in functions.
A few of these functions have an `assign` attribute which collects the
result the function to a named template variable instead of being
output; much like the [`{assign}`](language-function-assign.md) function.
- [{append}](language-function-append.md)
- [{assign} or {$var=...}](language-function-assign.md)
- [{block}](language-function-block.md)
- [{call}](language-function-call.md)
- [{capture}](language-function-capture.md)
- [{config_load}](language-function-config-load.md)
- [{debug}](language-function-debug.md)
- [{extends}](language-function-extends.md)
- [{for}](language-function-for.md)
- [{foreach}, {foreachelse}](language-function-foreach.md)
- [{function}](language-function-function.md)
- [{if}, {elseif}, {else}](language-function-if.md)
- [{include}](language-function-include.md)
- [{insert}](language-function-insert.md)
- [{ldelim}, {rdelim}](language-function-ldelim.md)
- [{literal}](language-function-literal.md)
- [{nocache}](language-function-nocache.md)
- [{section}, {sectionelse}](language-function-section.md)
- [{setfilter}](language-function-setfilter.md)
- [{strip}](language-function-strip.md)
- [{while}](language-function-while.md)
@@ -1,49 +0,0 @@
# {append}
`{append}` is used for creating or appending template variable arrays
**during the execution of a template**.
## Attributes
| Attribute | Required | Description |
|-----------|------------|----------------------------------------------------------------------------------------------------|
| var | | The name of the variable being assigned |
| value | | The value being assigned |
| index | (optional) | The index for the new array element. If not specified the value is append to the end of the array. |
| scope | (optional) | The scope of the assigned variable: parent, root or global. Defaults to local if omitted. |
## Option Flags
| Name | Description |
|---------|-----------------------------------------------------|
| nocache | Assigns the variable with the 'nocache' attribute |
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
## Examples
```smarty
{append var='name' value='Bob' index='first'}
{append var='name' value='Meyer' index='last'}
// or
{append 'name' 'Bob' index='first'} {* short-hand *}
{append 'name' 'Meyer' index='last'} {* short-hand *}
The first name is {$name.first}.<br>
The last name is {$name.last}.
```
The above example will output:
The first name is Bob.
The last name is Meyer.
See also [`append()`](#api.append) and
[`getTemplateVars()`](#api.get.template.vars).
@@ -1,148 +0,0 @@
# {assign}, {$var=...}
`{assign}` or `{$var=...}` is used for assigning template variables **during the
execution of a template**.
## Attributes of the {assign} syntax
| Attribute Name | Required | Description |
|----------------|------------|-----------------------------------------------------------------------|
| var | | The name of the variable being assigned |
| value | | The value being assigned |
| scope | (optional) | The scope of the assigned variable: 'parent','root' or 'global' |
## Attributes of the {$var=...} syntax
| Attribute Name | Required | Description |
|----------------|------------|-----------------------------------------------------------------------|
| scope | (optional) | The scope of the assigned variable: 'parent','root' or 'global' |
## Option Flags
| Name | Description |
|---------|---------------------------------------------------|
| nocache | Assigns the variable with the 'nocache' attribute |
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
## Examples
```smarty
{assign var="name" value="Bob"} {* or *}
{assign "name" "Bob"} {* short-hand, or *}
{$name='Bob'}
The value of $name is {$name}.
```
The above example will output:
```
The value of $name is Bob.
```
```smarty
{assign var="name" value="Bob" nocache} {* or *}
{assign "name" "Bob" nocache} {* short-hand, or *}
{$name='Bob' nocache}
The value of $name is {$name}.
```
The above example will output:
```
The value of $name is Bob.
```
```smarty
{assign var=running_total value=$running_total+$some_array[$row].some_value} {* or *}
{$running_total=$running_total+$some_array[row].some_value}
```
Variables assigned in the included template will be seen in the
including template.
```smarty
{include file="sub_template.tpl"}
{* display variable assigned in sub_template *}
{$foo}<br>
```
The template above includes the example `sub_template.tpl` below:
```smarty
{* foo will be known also in the including template *}
{assign var="foo" value="something" scope=parent}
{$foo="something" scope=parent}
{* bar is assigned only local in the including template *}
{assign var="bar" value="value"} {* or *}
{$var="value"}
```
You can assign a variable to root of the current root tree. The variable
is seen by all templates using the same root tree.
```smarty
{assign var=foo value="bar" scope="root"}
```
A global variable is seen by all templates.
```smarty
{assign var=foo value="bar" scope="global"} {* or *}
{assign "foo" "bar" scope="global"} {* short-hand, or *}
{$foo="bar" scope="global"}
```
For more information on variable scope, please read the page on [variable scopes](../language-variables/language-variable-scopes.md).
To access `{assign}` variables from a php script use
[`getTemplateVars()`](../../programmers/api-functions/api-get-template-vars.md).
Here's the template that creates the variable `$foo`.
```smarty
{assign var="foo" value="Smarty"} {* or *}
{$foo="Smarty"}
```
The template variables are only available after/during template
execution as in the following script.
```php
<?php
// this will output nothing as the template has not been executed
echo $smarty->getTemplateVars('foo');
// fetch the template to a variable
$whole_page = $smarty->fetch('index.tpl');
// this will output 'smarty' as the template has been executed
echo $smarty->getTemplateVars('foo');
$smarty->assign('foo','Even smarter');
// this will output 'Even smarter'
echo $smarty->getTemplateVars('foo');
```
The following functions can also *optionally* assign template variables: [`{capture}`](#language.function.capture),
[`{include}`](#language.function.include),
[`{counter}`](#language.function.counter),
[`{cycle}`](#language.function.cycle),
[`{eval}`](#language.function.eval),
[`{fetch}`](#language.function.fetch),
[`{math}`](#language.function.math) and
[`{textformat}`](#language.function.textformat).
See also [`{append}`](./language-function-append.md),
[`assign()`](#api.assign) and
[`getTemplateVars()`](#api.get.template.vars).
@@ -1,201 +0,0 @@
# {block}
`{block}` is used to define a named area of template source for template
inheritance. For details see section of [Template
Inheritance](../../api/inheritance.md).
The `{block}` template source area of a child template will replace the
corresponding areas in the parent template(s).
Optionally `{block}` areas of child and parent templates can be merged
into each other. You can append or prepend the parent `{block}` content
by using the `append` or `prepend` option flag with the child's `{block}`
definition. With `{$smarty.block.parent}` the `{block}` content of
the parent template can be inserted at any location of the child
`{block}` content. `{$smarty.block.child}` inserts the `{block}` content
of the child template at any location of the parent `{block}`.
`{blocks}'s` can be nested.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|----------------------------------------------------------------------------------------------------------------------|
| name | yes | The name of the template source block |
| assign | no | The name of variable to assign the output of the block to. |
> **Note**
>
> The assign attribute only works on the block that actually gets executed, so you may need
> to add it to each child block as well.
## Option Flags (in child templates only):
| Name | Description |
|---------|-----------------------------------------------------------------------------------------|
| append | The `{block}` content will be appended to the content of the parent template `{block}` |
| prepend | The `{block}` content will be prepended to the content of the parent template `{block}` |
| hide | Ignore the block content if no child block of same name is existing. |
| nocache | Disables caching of the `{block}` content |
## Examples
parent.tpl
```smarty
<html>
<head>
<title>{block name="title"}Default Title{/block}</title>
<title>{block "title"}Default Title{/block}</title> {* short-hand *}
</head>
</html>
```
child.tpl
```smarty
{extends file="parent.tpl"}
{block name="title"}
Page Title
{/block}
```
The result would look like
```html
<html>
<head>
<title>Page Title</title>
</head>
</html>
```
parent.tpl
```smarty
<html>
<head>
<title>{block name="title"}Title - {/block}</title>
</head>
</html>
```
child.tpl
```smarty
{extends file="parent.tpl"}
{block name="title" append}
Page Title
{/block}
```
The result would look like
```html
<html>
<head>
<title>Title - Page Title</title>
</head>
</html>
```
parent.tpl
```smarty
<html>
<head>
<title>{block name="title"} is my title{/block}</title>
</head>
</html>
```
child.tpl
```smarty
{extends file="parent.tpl"}
{block name="title" prepend}
Page Title
{/block}
```
The result would look like
```html
<html>
<head>
<title>Page title is my titel</title>
</head>
</html>
```
parent.tpl
```smarty
<html>
<head>
<title>{block name="title"}The {$smarty.block.child} was inserted here{/block}</title>
</head>
</html>
```
child.tpl
```smarty
{extends file="parent.tpl"}
{block name="title"}
Child Title
{/block}
```
The result would look like
```html
<html>
<head>
<title>The Child Title was inserted here</title>
</head>
</html>
```
parent.tpl
```smarty
<html>
<head>
<title>{block name="title"}Parent Title{/block}</title>
</head>
</html>
```
child.tpl
```smarty
{extends file="parent.tpl"}
{block name="title"}
You will see now - {$smarty.block.parent} - here
{/block}
```
The result would look like
```html
<html>
<head>
<title>You will see now - Parent Title - here</title>
</head>
</html>
```
See also [Template
Inheritance](../../api/inheritance.md),
[`$smarty.block.parent`](../language-variables/language-variables-smarty.md#smartyblockparent-languagevariablessmartyblockparent),
[`$smarty.block.child`](../language-variables/language-variables-smarty.md#smartyblockchild-languagevariablessmartyblockchild), and
[`{extends}`](./language-function-extends.md)
@@ -1,77 +0,0 @@
# {call}
`{call}` is used to call a template function defined by the
[`{function}`](./language-function-function.md) tag just like a plugin
function.
> **Note**
>
> Template functions are defined global. Since the Smarty compiler is a
> single-pass compiler, The `{call}` tag must
> be used to call a template function defined externally from the given
> template. Otherwise you can directly use the function as
> `{funcname ...}` in the template.
- The `{call}` tag must have the `name` attribute which contains the
name of the template function.
- Values for variables can be passed to the template function as
[attributes](../language-basic-syntax/language-syntax-attributes.md).
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|------------------------------------------------------------------------------------------|
| name | Yes | The name of the template function |
| assign | No | The name of the variable that the output of called template function will be assigned to |
| [var ...] | No | variable to pass local to template function |
## Option Flags
| Name | Description |
|---------|--------------------------------------------|
| nocache | Call the template function in nocache mode |
## Examples
```smarty
{* define the function *}
{function name=menu level=0}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{call name=menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{* create an array to demonstrate *}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{* run the array through the function *}
{call name=menu data=$menu}
{call menu data=$menu} {* short-hand *}
```
Will generate the following output
```
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
```
See also [`{function}`](./language-function-function.md).
@@ -1,75 +0,0 @@
# {capture}
`{capture}` is used to collect the output of the template between the
tags into a variable instead of displaying it. Any content between
`{capture name='foo'}` and `{/capture}` is collected into the variable
specified in the `name` attribute.
The captured content can be used in the template from the variable
[`$smarty.capture.foo`](../language-variables/language-variables-smarty.md#smartycapture-languagevariablessmartycapture) where "foo"
is the value passed in the `name` attribute. If you do not supply the
`name` attribute, then "default" will be used as the name ie
`$smarty.capture.default`.
`{capture}'s` can be nested.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|----------------------------------------------------------------------|
| name | Yes | The name of the captured block |
| assign | No | The variable name where to assign the captured output to |
| append | No | The name of an array variable where to append the captured output to |
## Option Flags
| Name | Description |
|---------|-----------------------------------------|
| nocache | Disables caching of this captured block |
## Examples
```smarty
{* we don't want to print a div tag unless content is displayed *}
{capture name="banner"}
{capture "banner"} {* short-hand *}
{include file="get_banner.tpl"}
{/capture}
{if $smarty.capture.banner ne ""}
<div id="banner">{$smarty.capture.banner}</div>
{/if}
```
This example demonstrates the capture function.
```smarty
{capture name=some_content assign=popText}
{capture some_content assign=popText} {* short-hand *}
The server is {$my_server_name|upper} at {$my_server_addr}<br>
Your ip is {$my_ip}.
{/capture}
<a href="#">{$popText}</a>
```
This example also demonstrates how multiple calls of capture can be used
to create an array with captured content.
```smarty
{capture append="foo"}hello{/capture}I say just {capture append="foo"}world{/capture}
{foreach $foo as $text}{$text} {/foreach}
```
The above example will output:
```
I say just hello world
```
See also [`$smarty.capture`](../language-variables/language-variables-smarty.md#smartycapture-languagevariablessmartycapture),
[`{eval}`](../language-custom-functions/language-function-eval.md),
[`{fetch}`](../language-custom-functions/language-function-fetch.md), [`fetch()`](../../programmers/api-functions/api-fetch.md) and
[`{assign}`](./language-function-assign.md).
@@ -1,88 +0,0 @@
# {config_load}
`{config_load}` is used for loading config
[`#variables#`](#language.config.variables) from a [configuration file](#config.files) into the template.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| file | Yes | The name of the config file to include |
| section | No | The name of the section to load |
| scope | no | How the scope of the loaded variables are treated, which must be one of local, parent or global. local means variables are loaded into the local template context. parent means variables are loaded into both the local context and the parent template that called it. global means variables are available to all templates. |
## Examples
The `example.conf` file.
```ini
#this is config file comment
# global variables
pageTitle = "Main Menu"
bodyBgColor = #000000
tableBgColor = #000000
rowBgColor = #00ff00
#customer variables section
[Customer]
pageTitle = "Customer Info"
```
and the template
```smarty
{config_load file="example.conf"}
{config_load "example.conf"} {* short-hand *}
<html>
<title>{#pageTitle#|default:"No title"}</title>
<body bgcolor="{#bodyBgColor#}">
<table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}">
<tr bgcolor="{#rowBgColor#}">
<td>First</td>
<td>Last</td>
<td>Address</td>
</tr>
</table>
</body>
</html>
```
[Config Files](#config.files) may also contain sections. You can load
variables from within a section with the added attribute `section`. Note
that global config variables are always loaded along with section
variables, and same-named section variables overwrite the globals.
> **Note**
>
> Config file *sections* and the built-in template function called
> [`{section}`](../language-builtin-functions/language-function-section.md) have nothing to do with each
> other, they just happen to share a common naming convention.
```smarty
{config_load file='example.conf' section='Customer'}
{config_load 'example.conf' 'Customer'} {* short-hand *}
<html>
<title>{#pageTitle#}</title>
<body bgcolor="{#bodyBgColor#}">
<table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}">
<tr bgcolor="{#rowBgColor#}">
<td>First</td>
<td>Last</td>
<td>Address</td>
</tr>
</table>
</body>
</html>
```
See [`$config_overwrite`](../../programmers/api-variables/variable-config-overwrite.md) to create arrays
of config file variables.
See also the [config files](../config-files.md) page, [config variables](../language-variables/language-config-variables.md) page,
[`$config_dir`](../../programmers/api-variables/variable-config-dir.md),
[`getConfigVars()`](../../programmers/api-functions/api-get-config-vars.md) and
[`configLoad()`](../../programmers/api-functions/api-config-load.md).
@@ -1,17 +0,0 @@
# {debug}
`{debug}` dumps the debug console to the page. This works regardless of
the [debug](../chapter-debugging-console.md) settings in the php script.
Since this gets executed at runtime, this is only able to show the
[assigned](../../programmers/api-functions/api-assign.md) variables; not the templates that are in use.
However, you can see all the currently available variables within the
scope of a template.
If caching is enabled and a page is loaded from cache `{debug}` does
show only the variables which assigned for the cached page.
In order to see also the variables which have been locally assigned
within the template it does make sense to place the `{debug}` tag at the
end of the template.
See also the [debugging console page](../chapter-debugging-console.md).
@@ -1,37 +0,0 @@
# {extends}
`{extends}` tags are used in child templates in template inheritance for
extending parent templates. For details see section of [Template
Inheritance](../../api/inheritance.md).
- The `{extends}` tag must be on the first line of the template.
- If a child template extends a parent template with the `{extends}`
tag it may contain only `{block}` tags. Any other template content
is ignored.
- Use the syntax for [template resources](../../api/resources.md) to extend files
outside the [`$template_dir`](../../programmers/api-variables/variable-template-dir.md) directory.
## Attributes
| Attribute | Required | Description |
|-----------|----------|-------------------------------------------------|
| file | Yes | The name of the template file which is extended |
> **Note**
>
> When extending a variable parent like `{extends file=$parent_file}`,
> make sure you include `$parent_file` in the
> [`$compile_id`](../../programmers/api-variables/variable-compile-id.md). Otherwise, Smarty cannot
> distinguish between different `$parent_file`s.
## Examples
```smarty
{extends file='parent.tpl'}
{extends 'parent.tpl'} {* short-hand *}
```
See also [Template Inheritance](../../api/inheritance.md)
and [`{block}`](./language-function-block.md).
@@ -1,91 +0,0 @@
# {for}
The `{for}{forelse}` tag is used to create simple loops. The following different formats are supported:
- `{for $var=$start to $end}` simple loop with step size of 1.
- `{for $var=$start to $end step $step}` loop with individual step
size.
`{forelse}` is executed when the loop is not iterated.
## Attributes
| Attribute | Required | Description |
|-----------|----------|--------------------------------|
| max | No | Limit the number of iterations |
## Option Flags
| Name | Description |
|---------|--------------------------------------|
| nocache | Disables caching of the `{for}` loop |
## Examples
```smarty
<ul>
{for $foo=1 to 3}
<li>{$foo}</li>
{/for}
</ul>
```
The above example will output:
```html
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
```
```php
<?php
$smarty->assign('to',10);
```
```smarty
<ul>
{for $foo=3 to $to max=3}
<li>{$foo}</li>
{/for}
</ul>
```
The above example will output:
```html
<ul>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
```
```php
<?php
$smarty->assign('start',10);
$smarty->assign('to',5);
```
```smarty
<ul>
{for $foo=$start to $to}
<li>{$foo}</li>
{forelse}
no iteration
{/for}
</ul>
```
The above example will output:
```
no iteration
```
See also [`{foreach}`](./language-function-foreach.md),
[`{section}`](./language-function-section.md) and
[`{while}`](./language-function-while.md)
@@ -1,389 +0,0 @@
# {foreach},{foreachelse}
`{foreach}` is used for looping over arrays of data. `{foreach}` has a
simpler and cleaner syntax than the
[`{section}`](./language-function-section.md) loop, and can also loop over
associative arrays.
## Option Flags
| Name | Description |
|---------|------------------------------------------|
| nocache | Disables caching of the `{foreach}` loop |
## Examples
```smarty
{foreach $arrayvar as $itemvar}
{$itemvar|escape}
{/foreach}
{foreach $arrayvar as $keyvar=>$itemvar}
{$keyvar}: {$itemvar|escape}
{/foreach}
```
> **Note**
>
> This foreach syntax does not accept any named attributes. This syntax
> is new to Smarty 3, however the Smarty 2.x syntax
> `{foreach from=$myarray key="mykey" item="myitem"}` is still
> supported.
- `{foreach}` loops can be nested.
- The `array` variable, usually an array of values, determines the
number of times `{foreach}` will loop. You can also pass an integer
for arbitrary loops.
- `{foreachelse}` is executed when there are no values in the `array`
variable.
- `{foreach}` properties are [`@index`](#index),
[`@iteration`](#iteration),
[`@first`](#first),
[`@last`](#last),
[`@show`](#show),
[`@total`](#total).
- `{foreach}` constructs are [`{break}`](#break),
[`{continue}`](#continue).
- Instead of specifying the `key` variable you can access the current
key of the loop item by `{$item@key}` (see examples below).
> **Note**
>
> The `$var@property` syntax is new to Smarty 3, however when using the
> Smarty 2 `{foreach from=$myarray key="mykey" item="myitem"}` style
> syntax, the `$smarty.foreach.name.property` syntax is still supported.
> **Note**
>
> Although you can retrieve the array key with the syntax
> `{foreach $myArray as $myKey => $myValue}`, the key is always
> available as `$myValue@key` within the foreach loop.
```php
<?php
$arr = array('red', 'green', 'blue');
$smarty->assign('myColors', $arr);
```
Template to output `$myColors` in an un-ordered list
```smarty
<ul>
{foreach $myColors as $color}
<li>{$color}</li>
{/foreach}
</ul>
```
The above example will output:
```html
<ul>
<li>red</li>
<li>green</li>
<li>blue</li>
</ul>
```
```php
<?php
$people = array('fname' => 'John', 'lname' => 'Doe', 'email' => 'j.doe@example.com');
$smarty->assign('myPeople', $people);
```
Template to output `$myArray` as key/value pairs.
```smarty
<ul>
{foreach $myPeople as $value}
<li>{$value@key}: {$value}</li>
{/foreach}
</ul>
```
The above example will output:
```html
<ul>
<li>fname: John</li>
<li>lname: Doe</li>
<li>email: j.doe@example.com</li>
</ul>
```
Assign an array to Smarty, the key contains the key for each looped
value.
```php
<?php
$smarty->assign(
'contacts',
[
['phone' => '555-555-1234', 'fax' => '555-555-5678', 'cell' => '555-555-0357'],
['phone' => '800-555-4444', 'fax' => '800-555-3333', 'cell' => '800-555-2222'],
]
);
```
The template to output `$contact`.
```smarty
{* key always available as a property *}
{foreach $contacts as $contact}
{foreach $contact as $value}
{$value@key}: {$value}
{/foreach}
{/foreach}
{* accessing key the PHP syntax alternate *}
{foreach $contacts as $contact}
{foreach $contact as $key => $value}
{$key}: {$value}
{/foreach}
{/foreach}
```
Either of the above examples will output:
```
phone: 555-555-1234
fax: 555-555-5678
cell: 555-555-0357
phone: 800-555-4444
fax: 800-555-3333
cell: 800-555-2222
```
A database (PDO) example of looping over search results. This example is
looping over a PHP iterator instead of an array().
```php
<?php
use Smarty\Smarty;
$smarty = new Smarty;
$dsn = 'mysql:host=localhost;dbname=test';
$login = 'test';
$passwd = 'test';
// setting PDO to use buffered queries in mysql is
// important if you plan on using multiple result cursors
// in the template.
$db = new PDO($dsn, $login, $passwd, array(
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true));
$res = $db->prepare("select * from users");
$res->execute();
$res->setFetchMode(PDO::FETCH_LAZY);
// assign to smarty
$smarty->assign('res',$res);
$smarty->display('index.tpl');?>
```
```smarty
{foreach $res as $r}
{$r.id}
{$r.name}
{foreachelse}
.. no results ..
{/foreach}
```
The above is assuming the results contain the columns named `id` and
`name`.
What is the advantage of an iterator vs. looping over a plain old array?
With an array, all the results are accumulated into memory before being
looped. With an iterator, each result is loaded/released within the
loop. This saves processing time and memory, especially for very large
result sets.
## @index
`index` contains the current array index, starting with zero.
```smarty
{* output empty row on the 4th iteration (when index is 3) *}
<table>
{foreach $items as $i}
{if $i@index eq 3}
{* put empty table row *}
<tr><td>nbsp;</td></tr>
{/if}
<tr><td>{$i.label}</td></tr>
{/foreach}
</table>
```
## @iteration
`iteration` contains the current loop iteration and always starts at
one, unlike [`index`](#index). It is incremented by one
on each iteration.
The *"is div by"* operator can be used to detect a specific iteration.
Here we bold-face the name every 4th iteration.
```smarty
{foreach $myNames as $name}
{if $name@iteration is div by 4}
<b>{$name}</b>
{/if}
{$name}
{/foreach}
```
The *"is even by"* and *"is odd by"* operators can be used to
alternate something every so many iterations. Choosing between even or
odd rotates which one starts. Here we switch the font color every 3rd
iteration.
```smarty
{foreach $myNames as $name}
{if $name@index is even by 3}
<span style="color: #000">{$name}</span>
{else}
<span style="color: #eee">{$name}</span>
{/if}
{/foreach}
```
This will output something similar to this:
```html
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
...
```
## @first
`first` is TRUE if the current `{foreach}` iteration is the initial one.
Here we display a table header row on the first iteration.
```smarty
{* show table header at first iteration *}
<table>
{foreach $items as $i}
{if $i@first}
<tr>
<th>key</td>
<th>name</td>
</tr>
{/if}
<tr>
<td>{$i@key}</td>
<td>{$i.name}</td>
</tr>
{/foreach}
</table>
```
## @last
`last` is set to TRUE if the current `{foreach}` iteration is the final
one. Here we display a horizontal rule on the last iteration.
```smarty
{* Add horizontal rule at end of list *}
{foreach $items as $item}
<a href="#{$item.id}">{$item.name}</a>{if $item@last}<hr>{else},{/if}
{foreachelse}
... no items to loop ...
{/foreach}
```
## @show
The show `show` property can be used after the execution of a
`{foreach}` loop to detect if data has been displayed or not. `show` is
a boolean value.
```smarty
<ul>
{foreach $myArray as $name}
<li>{$name}</li>
{/foreach}
</ul>
{if $name@show} do something here if the array contained data {/if}
```
## @total
`total` contains the number of iterations that this `{foreach}` will
loop. This can be used inside or after the `{foreach}`.
```smarty
{* show number of rows at end *}
{foreach $items as $item}
{$item.name}<hr/>
{if $item@last}
<div id="total">{$item@total} items</div>
{/if}
{foreachelse}
... no items to loop ...
{/foreach}
```
See also [`{section}`](./language-function-section.md),
[`{for}`](./language-function-for.md) and
[`{while}`](./language-function-while.md)
## {break}
`{break}` aborts the iteration of the array
```smarty
{$data = [1,2,3,4,5]}
{foreach $data as $value}
{if $value == 3}
{* abort iterating the array *}
{break}
{/if}
{$value}
{/foreach}
{*
prints: 1 2
*}
```
## {continue}
`{continue}` leaves the current iteration and begins with the next
iteration.
```smarty
{$data = [1,2,3,4,5]}
{foreach $data as $value}
{if $value == 3}
{* skip this iteration *}
{continue}
{/if}
{$value}
{/foreach}
{*
prints: 1 2 4 5
*}
```
@@ -1,89 +0,0 @@
# {function}
`{function}` is used to create functions within a template and call them
just like a plugin function. Instead of writing a plugin that generates
presentational content, keeping it in the template is often a more
manageable choice. It also simplifies data traversal, such as deeply
nested menus.
> **Note**
>
> Template functions are defined global. Since the Smarty compiler is a
> single-pass compiler, The [`{call}`](#language.function.call) tag must
> be used to call a template function defined externally from the given
> template. Otherwise, you can directly use the function as
> `{funcname ...}` in the template.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|---------------------------------------------------------------|
| name | Yes | The name of the template function |
| \[var \...\] | No | default variable value to pass local to the template function |
- The `{function}` tag must have the `name` attribute which contains
the name of the template function. A tag with this name can be
used to call the template function.
- Default values for variables can be passed to the template function
as [attributes](../language-basic-syntax/language-syntax-attributes.md). Like in PHP function
declarations you can only use scalar values as default. The default
values can be overwritten when the template function is being
called.
- You can use all variables from the calling template inside the
template function. Changes to variables or new created variables
inside the template function have local scope and are not visible
inside the calling template after the template function is executed.
> **Note**
>
> You can pass any number of parameter to the template function when it
> is called. The parameter variables must not be declared in the
> `{funcname ...}` tag unless you what to use default values. Default
> values must be scalar and can not be variable. Variables must be
> passed when the template is called.
## Examples
```smarty
{* define the function *}
{function name=menu level=0}
{function menu level=0} {* short-hand *}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{* create an array to demonstrate *}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{* run the array through the function *}
{menu data=$menu}
```
Will generate the following output
```
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
```
See also [`{call}`](./language-function-call.md)
@@ -1,116 +0,0 @@
# {if},{elseif},{else}
`{if}` statements in Smarty have much the same flexibility as PHP
[if](https://www.php.net/if) statements, with a few added features for the
template engine. Every `{if}` must be paired with a matching `{/if}`.
`{else}` and `{elseif}` are also permitted. All PHP conditionals and
functions are recognized, such as *\|\|*, *or*, *&&*, *and*,
*is_array()*, etc.
The following is a list of recognized qualifiers, which must be
separated from surrounding elements by spaces. Note that items listed in
\[brackets\] are optional. PHP equivalents are shown where applicable.
## Qualifiers
| Qualifier | Alternates | Syntax Example | Meaning | PHP Equivalent |
|--------------------|------------|----------------------|--------------------------------|--------------------|
| == | eq | $a eq $b | equals | == |
| != | ne, neq | $a neq $b | not equals | != |
| > | gt | $a gt $b | greater than | > |
| < | lt | $a lt $b | less than | < |
| >= | gte, ge | $a ge $b | greater than or equal | >= |
| <= | lte, le | $a le $b | less than or equal | <= |
| === | | $a === 0 | check for identity | === |
| ! | not | not $a | negation (unary) | ! |
| % | mod | $a mod $b | modulo | % |
| is \[not\] div by | | $a is not div by 4 | divisible by | $a % $b == 0 |
| is \[not\] even | | $a is not even | \[not\] an even number (unary) | $a % 2 == 0 |
| is \[not\] even by | | $a is not even by $b | grouping level \[not\] even | ($a / $b) % 2 == 0 |
| is \[not\] odd | | $a is not odd | \[not\] an odd number (unary) | $a % 2 != 0 |
| is \[not\] odd by | | $a is not odd by $b | \[not\] an odd grouping | ($a / $b) % 2 != 0 |
## Examples
```smarty
{if $name eq 'Fred'}
Welcome Sir.
{elseif $name eq 'Wilma'}
Welcome Ma'am.
{else}
Welcome, whatever you are.
{/if}
{* an example with "or" logic *}
{if $name eq 'Fred' or $name eq 'Wilma'}
...
{/if}
{* same as above *}
{if $name == 'Fred' || $name == 'Wilma'}
...
{/if}
{* parenthesis are allowed *}
{if ( $amount < 0 or $amount > 1000 ) and $volume >= #minVolAmt#}
...
{/if}
{* you can also embed php function calls *}
{if count($var) gt 0}
...
{/if}
{* check for array. *}
{if is_array($foo) }
.....
{/if}
{* check for not null. *}
{if isset($foo) }
.....
{/if}
{* test if values are even or odd *}
{if $var is even}
...
{/if}
{if $var is odd}
...
{/if}
{if $var is not odd}
...
{/if}
{* test if var is divisible by 4 *}
{if $var is div by 4}
...
{/if}
{*
test if var is even, grouped by two. i.e.,
0=even, 1=even, 2=odd, 3=odd, 4=even, 5=even, etc.
*}
{if $var is even by 2}
...
{/if}
{* 0=even, 1=even, 2=even, 3=odd, 4=odd, 5=odd, etc. *}
{if $var is even by 3}
...
{/if}
{if isset($name) && $name == 'Blog'}
{* do something *}
{elseif $name == $foo}
{* do something *}
{/if}
{if is_array($foo) && count($foo) > 0}
{* do a foreach loop *}
{/if}
```
@@ -1,187 +0,0 @@
# {include}
`{include}` tags are used for including other templates in the current
template. Any variables available in the current template are also
available within the included template.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|--------------------------------------------------------------------------------------------|
| file | Yes | The name of the template file to include |
| assign | No | The name of the variable that the output of include will be assigned to |
| cache_lifetime | No | Enable caching of this subtemplate with an individual cache lifetime |
| compile_id | No | Compile this subtemplate with an individual compile_id |
| cache_id | No | Enable caching of this subtemplate with an individual cache_id |
| scope | No | Define the scope of all in the subtemplate assigned variables: 'parent','root' or 'global' |
| \[var \...\] | No | variable to pass local to template |
- The `{include}` tag must have the `file` attribute which contains
the template resource path.
- Setting the optional `assign` attribute specifies the template
variable that the output of `{include}` is assigned to, instead of
being displayed. Similar to [`{assign}`](./language-function-assign.md).
- Variables can be passed to included templates as
[attributes](../language-basic-syntax/language-syntax-attributes.md). Any variables explicitly
passed to an included template are only available within the scope
of the included file. Attribute variables override current template
variables, in the case when they are named the same.
- You can use all variables from the including template inside the
included template. But changes to variables or new created variables
inside the included template have local scope and are not visible
inside the including template after the `{include}` statement. This
default behaviour can be changed for all variables assigned in the
included template by using the scope attribute at the `{include}`
statement or for individual variables by using the scope attribute
at the [`{assign}`](./language-function-assign.md) statement. The later
is useful to return values from the included template to the
including template.
- Use the syntax for [template resources](../../api/resources.md) to `{include}`
files outside of the [`$template_dir`](../../programmers/api-variables/variable-template-dir.md)
directory.
## Option Flags
| Name | Description |
|---------|--------------------------------------------------------------------------------------|
| nocache | Disables caching of this subtemplate |
| caching | Enable caching of this subtemplate |
| inline | If set, merge the compile-code of the subtemplate into the compiled calling template |
## Examples
```smarty
<html>
<head>
<title>{$title}</title>
</head>
<body>
{include file='page_header.tpl'}
{* body of template goes here, the $tpl_name variable
is replaced with a value eg 'contact.tpl'
*}
{include file="$tpl_name.tpl"}
{* using shortform file attribute *}
{include 'page_footer.tpl'}
</body>
</html>
```
```smarty
{include 'links.tpl' title='Newest links' links=$link_array}
{* body of template goes here *}
{include 'footer.tpl' foo='bar'}
```
The template above includes the example `links.tpl` below
```smarty
<div id="box">
<h3>{$title}</h3>
<ul>
{foreach from=$links item=l}
.. do stuff ...
{/foreach}
</ul>
</div>
```
Variables assigned in the included template will be seen in the
including template.
```smarty
{include 'sub_template.tpl' scope=parent}
...
{* display variables assigned in sub_template *}
{$foo}<br>
{$bar}<br>
...
```
The template above includes the example `sub_template.tpl` below
```smarty
...
{assign var=foo value='something'}
{assign var=bar value='value'}
...
```
The included template will not be cached.
```smarty
{include 'sub_template.tpl' nocache}
...
```
In this example included template will be cached with an individual
cache lifetime of 500 seconds.
```smarty
{include 'sub_template.tpl' cache_lifetime=500}
...
```
In this example included template will be cached independent of the
global caching setting.
```smarty
{include 'sub_template.tpl' caching}
...
```
This example assigns the contents of `nav.tpl` to the `$navbar`
variable, which is then output at both the top and bottom of the page.
```smarty
<body>
{include 'nav.tpl' assign=navbar}
{include 'header.tpl' title='Smarty is cool'}
{$navbar}
{* body of template goes here *}
{$navbar}
{include 'footer.tpl'}
</body>
```
This example includes another template relative to the directory of the
current template.
```smarty
{include 'template-in-a-template_dir-directory.tpl'}
{include './template-in-same-directory.tpl'}
{include '../template-in-parent-directory.tpl'}
```
```smarty
{* absolute filepath *}
{include file='/usr/local/include/templates/header.tpl'}
{* absolute filepath (same thing) *}
{include file='file:/usr/local/include/templates/header.tpl'}
{* windows absolute filepath (MUST use "file:" prefix) *}
{include file='file:C:/www/pub/templates/header.tpl'}
{* include from template resource named "db" *}
{include file='db:header.tpl'}
{* include a $variable template - eg $module = 'contacts' *}
{include file="$module.tpl"}
{* wont work as its single quotes ie no variable substitution *}
{include file='$module.tpl'}
{* include a multi $variable template - eg amber/links.view.tpl *}
{include file="$style_dir/$module.$view.tpl"}
```
See also [template resources](../../api/resources.md) and
[componentized templates](../../appendixes/tips.md#componentized-templates).
@@ -1,51 +0,0 @@
# {ldelim}, {rdelim}
`{ldelim}` and `{rdelim}` are used for [escaping](../language-basic-syntax/language-escaping.md)
template delimiters, by default **{** and **}**. You can also use
[`{literal}{/literal}`](./language-function-literal.md) to escape blocks of
text eg Javascript or CSS. See also the complementary
[`{$smarty.ldelim}`](../../designers/language-basic-syntax/language-escaping.md).
```smarty
{* this will print literal delimiters out of the template *}
{ldelim}funcname{rdelim} is how functions look in Smarty!
```
The above example will output:
```
{funcname} is how functions look in Smarty!
```
Another example with some Javascript
```smarty
<script>
function foo() {ldelim}
... code ...
{rdelim}
</script>
```
will output
```html
<script>
function foo() {
.... code ...
}
</script>
```
```smarty
<script>
function myJsFunction(){ldelim}
alert("The server name\n{$smarty.server.SERVER_NAME|escape:javascript}\n{$smarty.server.SERVER_ADDR|escape:javascript}");
{rdelim}
</script>
<a href="javascript:myJsFunction()">Click here for Server Info</a>
```
See also [`{literal}`](./language-function-literal.md) and [escaping Smarty
parsing](../language-basic-syntax/language-escaping.md).
@@ -1,34 +0,0 @@
# {literal}
`{literal}` tags allow a block of data to be taken literally. This is
typically used around Javascript or stylesheet blocks where {curly
braces} would interfere with the template
[delimiter](../../designers/language-basic-syntax/language-escaping.md) syntax. Anything within
`{literal}{/literal}` tags is not interpreted, but displayed as-is. If
you need template tags embedded in a `{literal}` block, consider using
[`{ldelim}{rdelim}`](./language-function-ldelim.md) to escape the individual
delimiters instead.
> **Note**
>
> `{literal}{/literal}` tags are normally not necessary, as Smarty
> ignores delimiters that are surrounded by whitespace. Be sure your
> javascript and CSS curly braces are surrounded by whitespace. This is
> new behavior to Smarty 3.
```smarty
<script>
// the following braces are ignored by Smarty
// since they are surrounded by whitespace
function myFoo {
alert('Foo!');
}
// this one will need literal escapement
{literal}
function myBar {alert('Bar!');}
{/literal}
</script>
```
See also [`{ldelim} {rdelim}`](./language-function-ldelim.md) and the
[escaping Smarty parsing](../language-basic-syntax/language-escaping.md) page.
@@ -1,20 +0,0 @@
# {nocache}
`{nocache}` is used to disable caching of a template section. Every
`{nocache}` must be paired with a matching `{/nocache}`.
> **Note**
>
> Be sure any variables used within a non-cached section are also
> assigned from PHP when the page is loaded from the cache.
```smarty
Today's date is
{nocache}
{$smarty.now|date_format}
{/nocache}
```
The above code will output the current date on a cached page.
See also the [caching section](../../api/caching/basics.md).
@@ -1,610 +0,0 @@
# {section}, {sectionelse}
A `{section}` is for looping over **sequentially indexed arrays of
data**, unlike [`{foreach}`](./language-function-foreach.md) which is used
to loop over a **single associative array**. Every `{section}` tag must
be paired with a closing `{/section}` tag.
> **Note**
>
> The [`{foreach}`](./language-function-foreach.md) loop can do everything a
> {section} loop can do, and has a simpler and easier syntax. It is
> usually preferred over the {section} loop.
> **Note**
>
> {section} loops cannot loop over associative arrays, they must be
> numerically indexed, and sequential (0,1,2,\...). For associative
> arrays, use the [`{foreach}`](./language-function-foreach.md) loop.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | Yes | The name of the section |
| loop | Yes | Value to determine the number of loop iterations |
| start | No | The index position that the section will begin looping. If the value is negative, the start position is calculated from the end of the array. For example, if there are seven values in the loop array and start is -2, the start index is 5. Invalid values (values outside of the length of the loop array) are automatically truncated to the closest valid value. Defaults to 0. |
| step | No | The step value that will be used to traverse the loop array. For example, step=2 will loop on index 0, 2, 4, etc. If step is negative, it will step through the array backwards. Defaults to 1. |
| max | No | Sets the maximum number of times the section will loop. |
| show | No | Determines whether to show this section (defaults to true) |
## Option Flags
| Name | Description |
|---------|------------------------------------------|
| nocache | Disables caching of the `{section}` loop |
- Required attributes are `name` and `loop`.
- The `name` of the `{section}` can be anything you like, made up of
letters, numbers and underscores, like [PHP
variables](https://www.php.net/language.variables).
- {section}'s can be nested, and the nested `{section}` names must be
unique from each other.
- The `loop` attribute, usually an array of values, determines the
number of times the `{section}` will loop. You can also pass an
integer as the loop value.
- When printing a variable within a `{section}`, the `{section}`
`name` must be given next to variable name within \[brackets\].
- `{sectionelse}` is executed when there are no values in the loop
variable.
- A `{section}` also has its own variables that handle `{section}`
properties. These properties are accessible as:
[`{$smarty.section.name.property}`](../language-variables/language-variables-smarty.md#smartysection-languagevariablessmartyloops)
where "name" is the attribute `name`.
- `{section}` properties are [`index`](#index),
[`index_prev`](#index_prev),
[`index_next`](#index_next),
[`iteration`](#iteration),
[`first`](#first),
[`last`](#last),
[`rownum`](#rownum),
[`loop`](#loop), [`show`](#show),
[`total`](#total).
[`assign()`](../../programmers/api-functions/api-assign.md) an array to Smarty
## Examples
```php
<?php
$data = [1000, 1001, 1002];
$smarty->assign('custid', $data);
```
The template that outputs the array
```smarty
{* this example will print out all the values of the $custid array *}
{section name=customer loop=$custid}
{section customer $custid} {* short-hand *}
id: {$custid[customer]}<br />
{/section}
<hr />
{* print out all the values of the $custid array reversed *}
{section name=foo loop=$custid step=-1}
{section foo $custid step=-1} {* short-hand *}
{$custid[foo]}<br />
{/section}
```
The above example will output:
```html
id: 1000<br />
id: 1001<br />
id: 1002<br />
<hr />
id: 1002<br />
id: 1001<br />
id: 1000<br />
```
```smarty
{section name=foo start=10 loop=20 step=2}
{$smarty.section.foo.index}
{/section}
<hr />
{section name=bar loop=21 max=6 step=-2}
{$smarty.section.bar.index}
{/section}
```
The above example will output:
```html
10 12 14 16 18
<hr />
20 18 16 14 12 10
```
The `name` of the `{section}` can be anything you like, see [PHP
variables](https://www.php.net/language.variables). It is used to reference
the data within the `{section}`.
```smarty
{section name=anything loop=$myArray}
{$myArray[anything].foo}
{$name[anything]}
{$address[anything].bar}
{/section}
```
This is an example of printing an associative array of data with a
`{section}`. Following is the php script to assign the `$contacts` array
to Smarty.
```php
<?php
$data = [
['name' => 'John Smith', 'home' => '555-555-5555',
'cell' => '666-555-5555', 'email' => 'john@myexample.com'],
['name' => 'Jack Jones', 'home' => '777-555-5555',
'cell' => '888-555-5555', 'email' => 'jack@myexample.com'],
['name' => 'Jane Munson', 'home' => '000-555-5555',
'cell' => '123456', 'email' => 'jane@myexample.com']
];
$smarty->assign('contacts',$data);
```
The template to output `$contacts`
```smarty
{section name=customer loop=$contacts}
<p>
name: {$contacts[customer].name}<br />
home: {$contacts[customer].home}<br />
cell: {$contacts[customer].cell}<br />
e-mail: {$contacts[customer].email}
</p>
{/section}
```
The above example will output:
```html
<p>
name: John Smith<br />
home: 555-555-5555<br />
cell: 666-555-5555<br />
e-mail: john@myexample.com
</p>
<p>
name: Jack Jones<br />
home phone: 777-555-5555<br />
cell phone: 888-555-5555<br />
e-mail: jack@myexample.com
</p>
<p>
name: Jane Munson<br />
home phone: 000-555-5555<br />
cell phone: 123456<br />
e-mail: jane@myexample.com
</p>
```
This example assumes that `$custid`, `$name` and `$address` are all
arrays containing the same number of values. First the php script that
assign's the arrays to Smarty.
```php
<?php
$id = [1001,1002,1003];
$smarty->assign('custid',$id);
$fullnames = ['John Smith','Jack Jones','Jane Munson'];
$smarty->assign('name',$fullnames);
$addr = ['253 Abbey road', '417 Mulberry ln', '5605 apple st'];
$smarty->assign('address',$addr);
```
The `loop` variable only determines the number of times to loop. You can
access ANY variable from the template within the `{section}`. This is
useful for looping multiple arrays. You can pass an array which will
determine the loop count by the array size, or you can pass an integer
to specify the number of loops.
```smarty
{section name=customer loop=$custid}
<p>
id: {$custid[customer]}<br />
name: {$name[customer]}<br />
address: {$address[customer]}
</p>
{/section}
```
The above example will output:
```html
<p>
id: 1000<br />
name: John Smith<br />
address: 253 Abbey road
</p>
<p>
id: 1001<br />
name: Jack Jones<br />
address: 417 Mulberry ln
</p>
<p>
id: 1002<br />
name: Jane Munson<br />
address: 5605 apple st
</p>
```
{section}'s can be nested as deep as you like. With nested
{section}'s, you can access complex data structures, such as
multidimensional arrays. This is an example `.php` script that
assigns the arrays.
```php
<?php
$id = [1001,1002,1003];
$smarty->assign('custid',$id);
$fullnames = ['John Smith','Jack Jones','Jane Munson'];
$smarty->assign('name',$fullnames);
$addr = ['253 N 45th', '417 Mulberry ln', '5605 apple st'];
$smarty->assign('address',$addr);
$types = [
[ 'home phone', 'cell phone', 'e-mail'],
[ 'home phone', 'web'],
[ 'cell phone']
];
$smarty->assign('contact_type', $types);
$info = [
['555-555-5555', '666-555-5555', 'john@myexample.com'],
[ '123-456-4', 'www.example.com'],
[ '0457878']
];
$smarty->assign('contact_info', $info);
```
In this template, *$contact_type\[customer\]* is an array of contact
types for the current customer.
```smarty
{section name=customer loop=$custid}
<hr>
id: {$custid[customer]}<br />
name: {$name[customer]}<br />
address: {$address[customer]}<br />
{section name=contact loop=$contact_type[customer]}
{$contact_type[customer][contact]}: {$contact_info[customer][contact]}<br />
{/section}
{/section}
```
The above example will output:
```html
<hr>
id: 1000<br />
name: John Smith<br />
address: 253 N 45th<br />
home phone: 555-555-5555<br />
cell phone: 666-555-5555<br />
e-mail: john@myexample.com<br />
<hr>
id: 1001<br />
name: Jack Jones<br />
address: 417 Mulberry ln<br />
home phone: 123-456-4<br />
web: www.example.com<br />
<hr>
id: 1002<br />
name: Jane Munson<br />
address: 5605 apple st<br />
cell phone: 0457878<br />
```
Results of a database search (eg ADODB or PEAR) are assigned to Smarty
```php
<?php
$sql = 'select id, name, home, cell, email from contacts '
."where name like '$foo%' ";
$smarty->assign('contacts', $db->getAll($sql));
```
The template to output the database result in a HTML table
```smarty
<table>
<tr><th>&nbsp;</th><th>Name</th><th>Home</th><th>Cell</th><th>Email</th></tr>
{section name=co loop=$contacts}
<tr>
<td><a href="view.php?id={$contacts[co].id}">view</a></td>
<td>{$contacts[co].name}</td>
<td>{$contacts[co].home}</td>
<td>{$contacts[co].cell}</td>
<td>{$contacts[co].email}</td>
<tr>
{sectionelse}
<tr><td colspan="5">No items found</td></tr>
{/section}
</table>
```
## .index
`index` contains the current array index, starting with zero or the
`start` attribute if given. It increments by one or by the `step`
attribute if given.
> **Note**
>
> If the `step` and `start` properties are not modified, then this works
> the same as the [`iteration`](#iteration) property,
> except it starts at zero instead of one.
> **Note**
>
> `$custid[customer.index]` and `$custid[customer]` are identical.
```smarty
{section name=customer loop=$custid}
{$smarty.section.customer.index} id: {$custid[customer]}<br />
{/section}
```
The above example will output:
```html
0 id: 1000<br />
1 id: 1001<br />
2 id: 1002<br />
```
## .index_prev
`index_prev` is the previous loop index. On the first loop, this is set to -1.
## .index_next
`index_next` is the next loop index. On the last loop, this is still one
more than the current index, respecting the setting of the `step`
attribute, if given.
```php
<?php
$data = [1001,1002,1003,1004,1005];
$smarty->assign('rows',$data);
```
Template to output the above array in a table
```smarty
{* $rows[row.index] and $rows[row] are identical in meaning *}
<table>
<tr>
<th>index</th><th>id</th>
<th>index_prev</th><th>prev_id</th>
<th>index_next</th><th>next_id</th>
</tr>
{section name=row loop=$rows}
<tr>
<td>{$smarty.section.row.index}</td><td>{$rows[row]}</td>
<td>{$smarty.section.row.index_prev}</td><td>{$rows[row.index_prev]}</td>
<td>{$smarty.section.row.index_next}</td><td>{$rows[row.index_next]}</td>
</tr>
{/section}
</table>
```
The above example will output a table containing the following:
```
index id index_prev prev_id index_next next_id
0 1001 -1 1 1002
1 1002 0 1001 2 1003
2 1003 1 1002 3 1004
3 1004 2 1003 4 1005
4 1005 3 1004 5
```
## .iteration
`iteration` contains the current loop iteration and starts at one.
> **Note**
>
> This is not affected by the `{section}` properties `start`, `step` and
> `max`, unlike the [`index`](#index) property.
> `iteration` also starts with one instead of zero unlike `index`.
> [`rownum`](#rownum) is an alias to `iteration`, they
> are identical.
```php
<?php
// array of 3000 to 3015
$id = range(3000,3015);
$smarty->assign('arr', $id);
```
Template to output every other element of the `$arr` array as `step=2`
```smarty
{section name=cu loop=$arr start=5 step=2}
iteration={$smarty.section.cu.iteration}
index={$smarty.section.cu.index}
id={$custid[cu]}<br />
{/section}
```
The above example will output:
```html
iteration=1 index=5 id=3005<br />
iteration=2 index=7 id=3007<br />
iteration=3 index=9 id=3009<br />
iteration=4 index=11 id=3011<br />
iteration=5 index=13 id=3013<br />
iteration=6 index=15 id=3015<br />
```
Another example that uses the `iteration` property to output a table
header block every five rows.
```smarty
<table>
{section name=co loop=$contacts}
{if $smarty.section.co.iteration is div by 5}
<tr><th>&nbsp;</th><th>Name</th><th>Home</th><th>Cell</th><th>Email</th></tr>
{/if}
<tr>
<td><a href="view.php?id={$contacts[co].id}">view<a></td>
<td>{$contacts[co].name}</td>
<td>{$contacts[co].home}</td>
<td>{$contacts[co].cell}</td>
<td>{$contacts[co].email}</td>
<tr>
{/section}
</table>
```
An example that uses the `index` property to alternate a text color every
third row.
```smarty
<table>
{section name=co loop=$contacts}
{if $smarty.section.co.index is even by 3}
<span style="color: #ffffff">{$contacts[co].name}</span>
{else}
<span style="color: #dddddd">{$contacts[co].name}</span>
{/if}
{/section}
</table>
```
> **Note**
>
> The *"is div by"* syntax is a simpler alternative to the PHP mod
> operator syntax. The mod operator is allowed:
> `{if $smarty.section.co.iteration % 5 == 1}` will work just the same.
> **Note**
>
> You can also use *"is odd by"* to reverse the alternating.
## .first
`first` is set to TRUE if the current `{section}` iteration is the initial one.
## .last
`last` is set to TRUE if the current section iteration is the final one.
This example loops the `$customers` array, outputs a header block on the
first iteration and on the last outputs the footer block. Also uses the
[`total`](#total) property.
```smarty
{section name=customer loop=$customers}
{if $smarty.section.customer.first}
<table>
<tr><th>id</th><th>customer</th></tr>
{/if}
<tr>
<td>{$customers[customer].id}}</td>
<td>{$customers[customer].name}</td>
</tr>
{if $smarty.section.customer.last}
<tr><td></td><td>{$smarty.section.customer.total} customers</td></tr>
</table>
{/if}
{/section}
```
## .rownum
`rownum` contains the current loop iteration, starting with one. It is
an alias to [`iteration`](#iteration), they work
identically.
## .loop
`loop` contains the last index number that this {section} looped. This
can be used inside or after the `{section}`.
```smarty
{section name=customer loop=$custid}
{$smarty.section.customer.index} id: {$custid[customer]}<br />
{/section}
There are {$smarty.section.customer.loop} customers shown above.
```
The above example will output:
```html
0 id: 1000<br />
1 id: 1001<br />
2 id: 1002<br />
There are 3 customers shown above.
```
## .show
`show` is used as a parameter to section and is a boolean value. If
FALSE, the section will not be displayed. If there is a `{sectionelse}`
present, that will be alternately displayed.
Boolean `$show_customer_info` has been passed from the PHP application,
to regulate whether this section shows.
```smarty
{section name=customer loop=$customers show=$show_customer_info}
{$smarty.section.customer.rownum} id: {$customers[customer]}<br />
{/section}
{if $smarty.section.customer.show}
the section was shown.
{else}
the section was not shown.
{/if}
```
The above example will output:
```html
1 id: 1000<br />
2 id: 1001<br />
3 id: 1002<br />
the section was shown.
```
## .total
`total` contains the number of iterations that this `{section}` will
loop. This can be used inside or after a `{section}`.
```smarty
{section name=customer loop=$custid step=2}
{$smarty.section.customer.index} id: {$custid[customer]}<br />
{/section}
There are {$smarty.section.customer.total} customers shown above.
```
See also [`{foreach}`](./language-function-foreach.md),
[`{for}`](./language-function-for.md), [`{while}`](./language-function-while.md)
and [`$smarty.section`](../language-variables/language-variables-smarty.md#smartysection-languagevariablessmartyloops).
@@ -1,43 +0,0 @@
# {setfilter}
The `{setfilter}...{/setfilter}` block tag allows the definition of
template instance's variable filters.
SYNTAX: `{setfilter filter1\|filter2\|filter3\....}\...{/setfilter}`
The filter can be:
- A variable filter plugin specified by it's name.
- A modifier specified by it's name and optional additional
parameter.
`{setfilter}...{/setfilter}` blocks can be nested. The filter definition
of inner blocks does replace the definition of the outer block.
Template instance filters run in addition to other modifiers and
filters. They run in the following order: modifier, default_modifier,
$escape_html, registered variable filters, autoloaded variable
filters, template instance's variable filters. Everything after
default_modifier can be disabled with the `nofilter` flag.
> **Note**
>
> The setting of template instance filters does not affect the output of
> included subtemplates.
## Examples
```smarty
<script>
{setfilter filter1}
{$foo} {* filter1 runs on output of $foo *}
{setfilter filter2|mod:true}
{$bar} {* filter2 and modifier mod runs on output of $bar *}
{/setfilter}
{$buh} {* filter1 runs on output of $buh *}
{/setfilter}
{$blar} {* no template instance filter runs on output of $blar}
</script>
```
@@ -1,45 +0,0 @@
# {strip}
Many times web designers run into the issue where white space and
carriage returns affect the output of the rendered HTML (browser
"features"), so you must run all your tags together in the template to
get the desired results. This usually ends up in unreadable or
unmanageable templates.
Anything within `{strip}{/strip}` tags are stripped of the extra spaces
or carriage returns at the beginnings and ends of the lines before they
are displayed. This way you can keep your templates readable, and not
worry about extra white space causing problems.
> **Note**
>
> `{strip}{/strip}` does not affect the contents of template variables,
> see the [strip modifier](../language-modifiers/language-modifier-strip.md) instead.
```smarty
{* the following will be all run into one line upon output *}
{strip}
<table>
<tr>
<td>
<a href="#">
This is a test
</a>
</td>
</tr>
</table>
{/strip}
```
The above example will output:
```html
<table><tr><td><a href="#">This is a test</a></td></tr></table>
```
Notice that in the above example, all the lines begin and end with HTML
tags. Be aware that all the lines are run together. If you have plain
text at the beginning or end of any line, they will be run together, and
may not be desired results.
See also the [`strip`](../language-modifiers/language-modifier-strip.md) modifier.
@@ -1,43 +0,0 @@
# {while}
`{while}` loops in Smarty have much the same flexibility as PHP
[while](https://www.php.net/while) statements, with a few added features for
the template engine. Every `{while}` must be paired with a matching
`{/while}`. All PHP conditionals and functions are recognized, such as
*\|\|*, *or*, *&&*, *and*, *is_array()*, etc.
The following is a list of recognized qualifiers, which must be
separated from surrounding elements by spaces. Note that items listed in
\[brackets\] are optional. PHP equivalents are shown where applicable.
## Qualifiers
| Qualifier | Alternates | Syntax Example | Meaning | PHP Equivalent |
|--------------------|------------|----------------------|--------------------------------|--------------------|
| == | eq | $a eq $b | equals | == |
| != | ne, neq | $a neq $b | not equals | != |
| > | gt | $a gt $b | greater than | > |
| < | lt | $a lt $b | less than | < |
| >= | gte, ge | $a ge $b | greater than or equal | >= |
| <= | lte, le | $a le $b | less than or equal | <= |
| === | | $a === 0 | check for identity | === |
| ! | not | not $a | negation (unary) | ! |
| % | mod | $a mod $b | modulo | % |
| is \[not\] div by | | $a is not div by 4 | divisible by | $a % $b == 0 |
| is \[not\] even | | $a is not even | \[not\] an even number (unary) | $a % 2 == 0 |
| is \[not\] even by | | $a is not even by $b | grouping level \[not\] even | ($a / $b) % 2 == 0 |
| is \[not\] odd | | $a is not odd | \[not\] an odd number (unary) | $a % 2 != 0 |
| is \[not\] odd by | | $a is not odd by $b | \[not\] an odd grouping | ($a / $b) % 2 != 0 |
## Examples
```smarty
{while $foo > 0}
{$foo--}
{/while}
```
The above example will count down the value of $foo until 1 is reached.
See also [`{foreach}`](./language-function-foreach.md),
[`{for}`](./language-function-for.md) and
[`{section}`](./language-function-section.md).
@@ -1,32 +0,0 @@
# Combining Modifiers
You can apply any number of modifiers to a variable. They will be
applied in the order they are combined, from left to right. They must be
separated with a `|` (pipe) character.
```php
<?php
$smarty->assign('articleTitle', 'Smokers are Productive, but Death Cuts Efficiency.');
```
where template is:
```smarty
{$articleTitle}
{$articleTitle|upper|spacify}
{$articleTitle|lower|spacify|truncate}
{$articleTitle|lower|truncate:30|spacify}
{$articleTitle|lower|spacify|truncate:30:". . ."}
```
The above example will output:
```
Smokers are Productive, but Death Cuts Efficiency.
S M O K E R S A R ....snip.... H C U T S E F F I C I E N C Y .
s m o k e r s a r ....snip.... b u t d e a t h c u t s...
s m o k e r s a r e p r o d u c t i v e , b u t . . .
s m o k e r s a r e p. . .
```
@@ -1,19 +0,0 @@
# Custom Tags
Smarty comes with several custom plugin functions that you can use in
the templates.
- [{counter}](language-function-counter.md)
- [{cycle}](language-function-cycle.md)
- [{eval}](language-function-eval.md)
- [{fetch}](language-function-fetch.md)
- [{html_checkboxes}](language-function-html-checkboxes.md)
- [{html_image}](language-function-html-image.md)
- [{html_options}](language-function-html-options.md)
- [{html_radios}](language-function-html-radios.md)
- [{html_select_date}](language-function-html-select-date.md)
- [{html_select_time}](language-function-html-select-time.md)
- [{html_table}](language-function-html-table.md)
- [{mailto}](language-function-mailto.md)
- [{math}](language-function-math.md)
- [{textformat}](language-function-textformat.md)
@@ -1,45 +0,0 @@
# {counter}
`{counter}` is used to print out a count. `{counter}` will remember the
count on each iteration. You can adjust the number, the interval and the
direction of the count, as well as determine whether to print the
value. You can run multiple counters concurrently by supplying a unique
name for each one. If you do not supply a name, the name "default" will
be used.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|-----------------------------------------------------------|
| name | No | The name of the counter |
| start | No | The initial number to start counting from (defaults to 1) |
| skip | No | The interval to count by (defaults to 1) |
| direction | No | The direction to count (up/down) (defaults to 'up') |
| print | No | Whether or not to print the value (defaults to true) |
| assign | No | the template variable the output will be assigned to |
If you supply the `assign` attribute, the output of the `{counter}`
function will be assigned to this template variable instead of being
output to the template.
## Examples
```smarty
{* initialize the count *}
{counter start=0 skip=2}<br />
{counter}<br />
{counter}<br />
{counter}<br />
```
this will output:
```html
0<br />
2<br />
4<br />
6<br />
```
@@ -1,55 +0,0 @@
# {cycle}
`{cycle}` is used to alternate a set of values. This makes it easy to
for example, alternate between two or more colors in a table, or cycle
through an array of values.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|-------------------------------------------------------------------------------------------------------------|
| name | No | The name of the cycle |
| values | Yes | The values to cycle through, either a comma delimited list (see delimiter attribute), or an array of values |
| print | No | Whether to print the value or not (defaults to true) |
| advance | No | Whether or not to advance to the next value (defaults to true) |
| delimiter | No | The delimiter to use in the values attribute (defaults to ',') |
| assign | No | The template variable the output will be assigned to |
| reset | No | The cycle will be set to the first value and not advanced (defaults to false) |
- You can `{cycle}` through more than one set of values in a template
by supplying a `name` attribute. Give each `{cycle}` a unique
`name`.
- You can force the current value not to print with the `print`
attribute set to FALSE. This would be useful for silently skipping a
value.
- The `advance` attribute is used to repeat a value. When set to
FALSE, the next call to `{cycle}` will print the same value.
- If you supply the `assign` attribute, the output of the `{cycle}`
function will be assigned to a template variable instead of being
output to the template.
## Examples
```smarty
{section name=rows loop=$data}
<tr class="{cycle values="odd,even"}">
<td>{$data[rows]}</td>
</tr>
{/section}
```
The above template would output:
```html
<tr class="odd">
<td>1</td>
</tr>
<tr class="even">
<td>2</td>
</tr>
<tr class="odd">
<td>3</td>
</tr>
```
@@ -1,14 +0,0 @@
# {debug}
`{debug}` dumps the debug console to the page. This works regardless of
the [debug](../chapter-debugging-console.md) settings in the php script.
Since this gets executed at runtime, this is only able to show the
[assigned](../../programmers/api-functions/api-assign.md) variables; not the templates that are in use.
However, you can see all the currently available variables within the
scope of a template.
| Attribute Name | Required | Description |
|----------------|----------|------------------------------------------------------------|
| output | No | output type, html or javascript (defaults to 'javascript') |
See also the [debugging console page](../chapter-debugging-console.md).
@@ -1,81 +0,0 @@
# {eval}
`{eval}` is used to evaluate a variable as a template. This can be used
for things like embedding template tags/variables into variables or
tags/variables into config file variables.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|------------------------------------------------------|
| var | Yes | Variable (or string) to evaluate |
| assign | No | The template variable the output will be assigned to |
If you supply the `assign` attribute, the output of the `{eval}`
function will be assigned to this template variable instead of being
output to the template.
> **Note**
>
> - Evaluated variables are treated the same as templates. They follow
> the same escapement and security features just as if they were
> templates.
>
> - Evaluated variables are compiled on every invocation, the compiled
> versions are not saved! However, if you have [caching](../../api/caching/basics.md)
> enabled, the output will be cached with the rest of the template.
>
> - If the content to evaluate doesn't change often, or is used
> repeatedly, consider using
> `{include file="string:{$template_code}"}` instead. This may cache
> the compiled state and thus doesn't have to run the (comparably
> slow) compiler on every invocation.
## Examples
The contents of the config file, `setup.conf`.
```ini
emphstart = <strong>
emphend = </strong>
title = Welcome to {$company}'s home page!
ErrorCity = You must supply a {#emphstart#}city{#emphend#}.
ErrorState = You must supply a {#emphstart#}state{#emphend#}.
```
Where the template is:
```smarty
{config_load file='setup.conf'}
{eval var=$foo}
{eval var=#title#}
{eval var=#ErrorCity#}
{eval var=#ErrorState# assign='state_error'}
{$state_error}
```
The above template will output:
```html
This is the contents of foo.
Welcome to Foobar Pub & Grill's home page!
You must supply a <strong>city</strong>.
You must supply a <strong>state</strong>.
```
This outputs the server name (in uppercase) and IP. The assigned
variable `$str` could be from a database query.
```php
<?php
$str = 'The server name is {$smarty.server.SERVER_NAME|upper} '
.'at {$smarty.server.SERVER_ADDR}';
$smarty->assign('foo',$str);
```
Where the template is:
```smarty
{eval var=$foo}
```
@@ -1,61 +0,0 @@
# {fetch}
`{fetch}` is used to retrieve files from the local file system, http, or
ftp and display the contents.
## Attributes
| Attribute | Required | Description |
|-----------|----------|------------------------------------------------------|
| file | Yes | The file, http or ftp site to fetch |
| assign | No | The template variable the output will be assigned to |
- If the file name begins with `http://`, the website page will be
fetched and displayed.
> **Note**
>
> This will not support http redirects, be sure to include a
> trailing slash on your web page fetches where necessary.
- If the file name begins with `ftp://`, the file will be downloaded
from the ftp server and displayed.
- For local files, either a full system file path must be given, or a
path relative to the executed php script.
> **Note**
>
> If security is enabled, and you are fetching a file from the local
> file system, `{fetch}` will only allow files from within the
> `$secure_dir` path of the security policy. See the
> [Security](../../api/security.md) section for details.
- If the `assign` attribute is set, the output of the `{fetch}`
function will be assigned to this template variable instead of being
output to the template.
## Examples
```smarty
{* include some javascript in your template *}
{fetch file='/export/httpd/www.example.com/docs/navbar.js'}
{* embed some weather text in your template from another web site *}
{fetch file='http://www.myweather.com/68502/'}
{* fetch a news headline file via ftp *}
{fetch file='ftp://user:password@ftp.example.com/path/to/currentheadlines.txt'}
{* as above but with variables *}
{fetch file="ftp://`$user`:`$password`@`$server`/`$path`"}
{* assign the fetched contents to a template variable *}
{fetch file='http://www.myweather.com/68502/' assign='weather'}
{if $weather ne ''}
<div id="weather">{$weather}</div>
{/if}
```
See also [`{capture}`](../language-builtin-functions/language-function-capture.md),
[`{eval}`](language-function-eval.md),
[`{assign}`](../language-builtin-functions/language-function-assign.md) and [`fetch()`](../../programmers/api-functions/api-fetch.md).
@@ -1,102 +0,0 @@
# {html_checkboxes}
`{html_checkboxes}` is a [custom function](index.md)
that creates an html checkbox group with provided data. It takes care of
which item(s) are selected by default as well.
## Attributes
| Attribute Name | Required | Description |
|----------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | No | Name of checkbox list (defaults to 'checkbox') |
| values | Yes, unless using options attribute | An array of values for checkbox buttons |
| output | Yes, unless using options attribute | An array of output for checkbox buttons |
| selected | No | The selected checkbox element(s) as a string or array |
| options | Yes, unless using values and output | An associative array of values and output |
| separator | No | String of text to separate each checkbox item |
| assign | No | Assign checkbox tags to an array instead of output |
| labels | No | Add <label\>-tags to the output (defaults to true) |
| label\_ids | No | Add id-attributes to <label\> and <input\> to the output (defaults to false) |
| escape | No | Escape the output / content (values are always escaped) (defaults to true) |
| strict | No | Will make the "extra" attributes *disabled* and *readonly* only be set, if they were supplied with either boolean *TRUE* or string *"disabled"* and *"readonly"* respectively (defaults to false) |
- Required attributes are `values` and `output`, unless you use `options` instead.
- All output is XHTML compliant.
- All parameters that are not in the list above are printed as
name/value-pairs inside each of the created <input\>-tags.
## Examples
```php
<?php
$smarty->assign('cust_ids', array(1000,1001,1002,1003));
$smarty->assign('cust_names', array(
'Joe Schmoe',
'Jack Smith',
'Jane Johnson',
'Charlie Brown')
);
$smarty->assign('customer_id', 1001);
```
where template is
```smarty
{html_checkboxes name='id' values=$cust_ids output=$cust_names selected=$customer_id separator='<br />'}
```
or where PHP code is:
```php
<?php
$smarty->assign(
'cust_checkboxes',
[
1000 => 'Joe Schmoe',
1001 => 'Jack Smith',
1002 => 'Jane Johnson',
1003 => 'Charlie Brown',
]
);
$smarty->assign('customer_id', 1001);
```
and the template is
```smarty
{html_checkboxes name='id' options=$cust_checkboxes selected=$customer_id separator='<br />'}
```
both examples will output:
```html
<label><input type="checkbox" name="id[]" value="1000" />Joe Schmoe</label><br />
<label><input type="checkbox" name="id[]" value="1001" checked="checked" />Jack Smith</label>
<br />
<label><input type="checkbox" name="id[]" value="1002" />Jane Johnson</label><br />
<label><input type="checkbox" name="id[]" value="1003" />Charlie Brown</label><br />
```
```php
<?php
$sql = 'select type_id, types from contact_types order by type';
$smarty->assign('contact_types',$db->getAssoc($sql));
$sql = 'select contact_id, contact_type_id, contact '
.'from contacts where contact_id=12';
$smarty->assign('contact',$db->getRow($sql));
```
The results of the database queries above would be output with.
```smarty
{html_checkboxes name='contact_type_id' options=$contact_types selected=$contact.contact_type_id separator='<br />'}
```
See also [`{html_radios}`](./language-function-html-radios.md) and
[`{html_options}`](./language-function-html-options.md)
@@ -1,58 +0,0 @@
# {html_image}
`{html_image}` is a [custom function](index.md) that
generates an HTML `<img>` tag. The `height` and `width` are
automatically calculated from the image file if they are not supplied.
## Attributes
| Attribute Name | Required | Description |
|----------------|----------|-------------------------------------------------------------------------|
| file | Yes | name/path to image |
| height | No | Height to display image (defaults to actual image height) |
| width | No | Width to display image (defaults to actual image width) |
| basedir | no | Directory to base relative paths from (defaults to web server doc root) |
| alt | no | Alternative description of the image |
| href | no | href value to link the image to |
| path\_prefix | no | Prefix for output path |
- `basedir` is the base directory that relative image paths are based
from. If not given, the web server's document root
`$_ENV['DOCUMENT_ROOT']` is used as the base. If security is
enabled, then the image must be located in the `$secure_dir` path of
the security policy. See the [Security](../../api/security.md)
section for details.
- `href` is the href value to link the image to. If link is supplied,
an `<a href="LINKVALUE"><a>` tag is placed around the image tag.
- `path_prefix` is an optional prefix string you can give the output
path. This is useful if you want to supply a different server name
for the image.
- All parameters that are not in the list above are printed as
name/value-pairs inside the created `<img>` tag.
> **Note**
>
> `{html_image}` requires a hit to the disk to read the image and
> calculate the height and width. If you don't use template
> [caching](../../api/caching/basics.md), it is generally better to avoid `{html_image}`
> and leave image tags static for optimal performance.
## Examples
```smarty
{html_image file='pumpkin.jpg'}
{html_image file='/path/from/docroot/pumpkin.jpg'}
{html_image file='../path/relative/to/currdir/pumpkin.jpg'}
```
Example output of the above template would be:
```html
<img src="pumpkin.jpg" alt="" width="44" height="68" />
<img src="/path/from/docroot/pumpkin.jpg" alt="" width="44" height="68" />
<img src="../path/relative/to/currdir/pumpkin.jpg" alt="" width="44" height="68" />
```
@@ -1,146 +0,0 @@
# {html_options}
`{html_options}` is a [custom function](index.md) that
creates the html `<select><option>` group with the assigned data. It
takes care of which item(s) are selected by default as well.
## Attributes
| Attribute Name | Required | Description |
|----------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| values | Yes, unless using options attribute | An array of values for dropdown |
| output | Yes, unless using options attribute | An array of output for dropdown |
| selected | No | The selected option element(s) as a string or array |
| options | Yes, unless using values and output | An associative array of values and output |
| name | No | Name of select group |
| strict | No | Will make the "extra" attributes *disabled* and *readonly* only be set, if they were supplied with either boolean *TRUE* or string *"disabled"* and *"readonly"* respectively (defaults to false) |
- Required attributes are `values` and `output`, unless you use the
combined `options` instead.
- If the optional `name` attribute is given, the `<select></select>`
tags are created, otherwise ONLY the `<option>` list is generated.
- If a given value is an array, it will treat it as an html
`<optgroup>`, and display the groups. Recursion is supported with
`<optgroup>`.
- All parameters that are not in the list above are printed as
name/value-pairs inside the `<select>` tag. They are ignored if the
optional `name` is not given.
- All output is XHTML compliant.
## Examples
```php
<?php
$smarty->assign('myOptions', [
1800 => 'Joe Schmoe',
9904 => 'Jack Smith',
2003 => 'Charlie Brown']
);
$smarty->assign('mySelect', 9904);
```
The following template will generate a drop-down list. Note the presence
of the `name` attribute which creates the `<select>` tags.
```smarty
{html_options name=foo options=$myOptions selected=$mySelect}
```
Output of the above example would be:
```html
<select name="foo">
<option value="1800">Joe Schmoe</option>
<option value="9904" selected="selected">Jack Smith</option>
<option value="2003">Charlie Brown</option>
</select>
```
```php
<?php
$smarty->assign('cust_ids', [56,92,13]);
$smarty->assign('cust_names', [
'Joe Schmoe',
'Jane Johnson',
'Charlie Brown']);
$smarty->assign('customer_id', 92);
```
The above arrays would be output with the following template (note the
use of the php [`count()`](https://www.php.net/function.count) function as a
modifier to set the select size).
```smarty
<select name="customer_id" size="{$cust_names|@count}">
{html_options values=$cust_ids output=$cust_names selected=$customer_id}
</select>
```
The above example would output:
```html
<select name="customer_id" size="3">
<option value="56">Joe Schmoe</option>
<option value="92" selected="selected">Jane Johnson</option>
<option value="13">Charlie Brown</option>
</select>
```
```php
<?php
$sql = 'select type_id, types from contact_types order by type';
$smarty->assign('contact_types',$db->getAssoc($sql));
$sql = 'select contact_id, name, email, contact_type_id
from contacts where contact_id='.$contact_id;
$smarty->assign('contact',$db->getRow($sql));
```
Where a template could be as follows. Note the use of the
[`truncate`](../language-modifiers/language-modifier-truncate.md) modifier.
```smarty
<select name="type_id">
<option value='null'>-- none --</option>
{html_options options=$contact_types|truncate:20 selected=$contact.type_id}
</select>
```
```php
<?php
$arr['Sport'] = array(6 => 'Golf', 9 => 'Cricket',7 => 'Swim');
$arr['Rest'] = array(3 => 'Sauna',1 => 'Massage');
$smarty->assign('lookups', $arr);
$smarty->assign('fav', 7);
```
The script above and the following template
```smarty
{html_options name=foo options=$lookups selected=$fav}
```
would output:
```html
<select name="foo">
<optgroup label="Sport">
<option value="6">Golf</option>
<option value="9">Cricket</option>
<option value="7" selected="selected">Swim</option>
</optgroup>
<optgroup label="Rest">
<option value="3">Sauna</option>
<option value="1">Massage</option>
</optgroup>
</select>
```
See also [`{html_checkboxes}`](./language-function-html-checkboxes.md) and
[`{html_radios}`](./language-function-html-radios.md)
@@ -1,104 +0,0 @@
# {html_radios}
`{html_radios}` is a [custom function](index.md) that
creates an HTML radio button group. It also takes care of which item is
selected by default as well.
## Attributes
| Attribute Name | Required | Description |
|----------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | No | Name of radio list |
| values | Yes, unless using options attribute | An array of values for radio buttons |
| output | Yes, unless using options attribute | An array of output for radio buttons |
| selected | No | The selected radio element |
| options | Yes, unless using values and output | An associative array of values and output |
| separator | No | String of text to separate each radio item |
| assign | No | Assign radio tags to an array instead of output |
| labels | No | Add <label>-tags to the output (defaults to true) |
| label\_ids | No | Add id-attributes to <label\> and <input\> to the output (defaults to false) |
| escape | No | Escape the output / content (values are always escaped) (defaults to true) |
| strict | No | Will make the "extra" attributes *disabled* and *readonly* only be set, if they were supplied with either boolean *TRUE* or string *"disabled"* and *"readonly"* respectively (defaults to false) |
- Required attributes are `values` and `output`, unless you use
`options` instead.
- All output is XHTML compliant.
- All parameters that are not in the list above are output as
name/value-pairs inside each of the created `<input>`-tags.
## Examples
```php
<?php
$smarty->assign('cust_ids', array(1000,1001,1002,1003));
$smarty->assign('cust_names', array(
'Joe Schmoe',
'Jack Smith',
'Jane Johnson',
'Charlie Brown')
);
$smarty->assign('customer_id', 1001);
```
Where template is:
```smarty
{html_radios name='id' values=$cust_ids output=$cust_names
selected=$customer_id separator='<br />'}
```
```php
<?php
$smarty->assign('cust_radios', array(
1000 => 'Joe Schmoe',
1001 => 'Jack Smith',
1002 => 'Jane Johnson',
1003 => 'Charlie Brown'));
$smarty->assign('customer_id', 1001);
```
Where template is:
```smarty
{html_radios name='id' options=$cust_radios
selected=$customer_id separator='<br />'}
```
Both examples will output:
```html
<label><input type="radio" name="id" value="1000" />Joe Schmoe</label><br />
<label><input type="radio" name="id" value="1001" checked="checked" />Jack Smith</label><br />
<label><input type="radio" name="id" value="1002" />Jane Johnson</label><br />
<label><input type="radio" name="id" value="1003" />Charlie Brown</label><br />
```
```php
<?php
$sql = 'select type_id, types from contact_types order by type';
$smarty->assign('contact_types',$db->getAssoc($sql));
$sql = 'select contact_id, name, email, contact_type_id '
.'from contacts where contact_id='.$contact_id;
$smarty->assign('contact',$db->getRow($sql));
```
The variable assigned from the database above would be output with the
template:
```smarty
{html_radios name='contact_type_id' options=$contact_types
selected=$contact.contact_type_id separator='<br />'}
```
See also [`{html_checkboxes}`](language-function-html-checkboxes.md) and
[`{html_options}`](language-function-html-options.md)

Some files were not shown because too many files have changed in this diff Show More