.. include:: /Includes.rst.txt .. _creating-expressionnodes: ======================== Creating ExpressionNodes ======================== The :php:`ExpressionNode` concept is the most profound way you can manipulate the Fluid language itself, adding to it new syntax options that can be used inside the shorthand `{...}` syntax. Normally you are confined to using ViewHelpers when you want such special processing in your templates - but using ExpressionNodes allows you to add these processings as actual parts of the templating language itself; avoiding the need to include a ViewHelper namespace. Fluid itself provides the following types of `ExpressionNodes`: 1. :php:`MathExpressionNode` which scans for and evaluates simple mathematical expressions like `{variable + 1}`. 2. :php:`TernaryExpressionNode` which implements a ternary condition in Fluid syntax like `{ifsomething ? thenoutputthis : elsethis}` 3. :php:`CastingExpressionNode` which casts variables to a certain type, e.g. `{suspectType as integer}`, `{myInteger as boolean}`. An :php:`ExpressionNode` basically consists of one an expression matching pattern (regex), one non-static method to evaluate the expression :php:`public function evaluate(RenderingContextInterface $renderingContext)` and a mirror of this function which can be called statically: :php:`public static evaluteExpression(RenderingContextInterface $renderingContext, $expression)`. The non-static method should then simply delegate to the static method and use the expression stored in `$this->expression` as second parameter for the static method call. ExpressionNodes automatically support compilation and will generate compiled code which stores the expression and calls the static :php:`evaluateExpression()` method with the rendering context and the stored expression. You should create your own ExpressionNodes if: 1. You want a custom syntax in your Fluid templates (theoretical example: casting variables using `{(integer)variablename}`). 2. You want to replace either of the above mentioned :php:`ExpressionNodes` with ones using the same, or an expanded version of their regular expression patterns to further extend the strings they capture and process. .. _creating-expressionnodes-implementation: Implementation ============== An ExpressionNode is always one PHP class. Where you place it is completely up to you - but to have the class actually be detected and used by Fluid, it needs to be added to the rendering context by calling :php:`setExpressionNodeTypes()`. In Fluid's default :php:`RenderingContext`, the following code is responsible for returning expression node class names: .. code-block:: php /** * List of class names implementing ExpressionNodeInterface * which will be consulted when an expression does not match * any built-in parser expression types. * * @var string */ protected $expressionNodeTypes = [ 'TYPO3Fluid\\Fluid\\Core\\Parser\\SyntaxTree\\Expression\\CastingExpressionNode', 'TYPO3Fluid\\Fluid\\Core\\Parser\\SyntaxTree\\Expression\\MathExpressionNode', 'TYPO3Fluid\\Fluid\\Core\\Parser\\SyntaxTree\\Expression\\TernaryExpressionNode', ]; /** * @return string */ public function getExpressionNodeTypes() { return $this->expressionNodeTypes; } You may or may not want the listed expression nodes included, but if you change the available expression types you should of course document this difference about your implementation. The following class is the math ExpressionNode from Fluid itself which detects the `{a + 1}` and other simple mathematical operations. To get this behavior, we need a (relatively simple) regular expression and one method to evaluate the expression while being aware of the rendering context (which stores all variables, controller name, action name etc). .. code-block:: php