Dough is a very small templating language for strings written by your users rather than by your developers.
Mail merges are the motivating case. When a non-technical user composes an email and drops {{ first_name }} into it, handing that string to a general-purpose template engine gives them a large and difficult-to-secure surface area. Dough gives them placeholders and nothing else: no loops, no conditionals, no includes, no function calls, no arbitrary code.
composer require piestar/doughNo runtime dependencies.
Supported on PHP 8.2 and newer, which is what CI covers. The code itself carries no dependencies and runs on PHP 5.4 and up, so it will install on older runtimes, but those are untested and unsupported.
use Piestar\Dough\DoughMixer;
DoughMixer::mix('Eat more {{ pie }}', ['pie' => 'apple']); // "Eat more apple"{{ }} escapes its value on output. {!! !!} does not.
DoughMixer::mix('pie is {{ pie }}', ['pie' => '<good>']); // "pie is <good>"
DoughMixer::mix('pie is {!! pie !!}', ['pie' => '<good>']); // "pie is <good>"Objects implementing a toHtml() method (such as Laravel's Illuminate\Contracts\Support\Htmlable) are rendered via that method instead of being escaped.
Reach into nested arrays with dot notation.
DoughMixer::mix('Eat {{ pie.name }}!', ['pie' => ['name' => 'Apple Pie']]); // "Eat Apple Pie!"Follow a path with or and a quoted string to supply a fallback. The default is used when the path is unresolved, null, or an empty string. Either quote style works, and the default may contain spaces.
DoughMixer::mix('Hi {{ user.name or "Member" }}', ['user' => []]); // "Hi Member"
DoughMixer::mix('Hi {{ user.name or "Member" }}', ['user' => ['name' => null]]); // "Hi Member"
DoughMixer::mix('Hi {{ user.name or "Member" }}', ['user' => ['name' => 'Smith']]); // "Hi Smith"
DoughMixer::mix("{!! greeting or '<b>Member</b>' !!}", []); // "<b>Member</b>"
DoughMixer::mix('{{ x or "A & B" }}', []); // "A & B"A default is escaped or left raw according to the tag that contains it, exactly like a resolved value. A value of '0' is kept rather than treated as empty.
A placeholder with no matching data and no default is left in the output verbatim rather than replaced with an empty string.
DoughMixer::mix('Eat more {{ type }}', []); // "Eat more {{ type }}"This is deliberate. In a mail merge, a visible {{ type }} tells the author they referenced something that does not exist; a silent blank does not.
Dough escapes with htmlentities() using ENT_QUOTES. That is the whole of its output filtering.
It does not sanitize HTML or JavaScript, and {!! !!} performs no filtering at all by design. If the values you pass in are themselves untrusted, or if your users may write raw placeholders, run the output through a dedicated HTML sanitizer before displaying it.
composer install
composer testMIT. See LICENSE.