adachsoft / prompt-template-lib
PHP library for rendering function-based prompt templates with extensible SPI and safe file access
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Forks: 0
pkg:composer/adachsoft/prompt-template-lib
Requires
- php: >=8.3
- adachsoft/normalized-safe-path: ^0.1.0
Requires (Dev)
- adachsoft/php-code-style: ^0.2.1
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^12.0
This package is not auto-updated.
Last update: 2025-12-16 08:46:06 UTC
README
Small PHP library for rendering function-based prompt templates with a clear, layered architecture (PublicApi / Spi / Internal). It lets you define template tags that call PHP functions (SPI implementations) with arguments, for example:
Hello <user_name>, today is <datetime('Y-m-d')>.
Please analyze: <file_read('docs/task.md')>
The engine parses the template, resolves tags using registered functions, and returns the rendered string. File-based operations are secured with normalized, safe paths to protect against directory traversal.
Requirements
- PHP >= 8.3
- Composer (for installation and autoloading)
Dev tools (optional, already declared in composer.json):
phpunit/phpunitphpstan/phpstanfriendsofphp/php-cs-fixer
Installation
composer require adachsoft/prompt-template-lib
The package is framework-agnostic and can be used in any PHP application that supports Composer autoloading.
Core concepts
1. Public API
Public entry point is the engine interface and its default implementation:
AdachSoft\PromptTemplateLib\PublicApi\PromptEngineInterface– public contract used in type hints.AdachSoft\PromptTemplateLib\PublicApi\PromptEngine– default implementation of the interface.
You normally do not instantiate this class manually. Use the factory instead:
AdachSoft\PromptTemplateLib\PublicApi\PromptEngineFactory
use AdachSoft\PromptTemplateLib\PublicApi\PromptEngineFactory;
use AdachSoft\PromptTemplateLib\PublicApi\PromptEngineInterface;
$engine = PromptEngineFactory::createDefault(__DIR__); // PromptEngineInterface
createDefault() wires all internal components and registers standard functions (see below).
2. SPI (Service Provider Interface)
To add your own function (tag), implement the SPI interface:
AdachSoft\PromptTemplateLib\Spi\PromptFunctionInterface
use AdachSoft\PromptTemplateLib\Spi\PromptFunctionInterface;
final class UserNameFunction implements PromptFunctionInterface
{
public function getName(): string
{
// Name must follow the engine naming rules (see below).
return 'user_name';
}
public function execute(array $arguments): string
{
// In a real application this could read from a user context, session, etc.
return 'Example User';
}
}
Then register the function in the engine:
$engine->registerFunction(new UserNameFunction());
You can now use <user_name> in templates.
Function naming rules
Every implementation of PromptFunctionInterface must return a name that satisfies the following rules:
- at least 3 characters long,
- contains only lowercase letters
a-z, digits0-9and underscore (_), - cannot start or end with underscore (
_).
If a function is registered with a name that violates these rules, the engine throws
InvalidFunctionNameException.
3. Internal layer (implementation details)
The Internal layer is not part of the public contract and may change between versions. It contains:
Internal\Registry\FunctionRegistry– registry that maps function names toPromptFunctionInterfaceimplementations.Internal\Core\TemplateParser– parser responsible for finding tags in the template, parsing arguments and delegating calls to registered functions.
These classes are marked as @internal and should not be used directly from client code.
Standard functions
The library ships with two example functions, registered automatically by PromptEngineFactory::createDefault():
DateTimeFunction– tag:<datetime>or<datetime('Y-m-d')>- Without arguments it returns the current date/time in
DATE_ATOMformat. - With a single argument it uses that argument as the format string for
DateTimeImmutable::format().
- Without arguments it returns the current date/time in
FileReadFunction– tag:<file_read('relative/path.txt')>- Reads contents of a file from a base directory configured in the factory.
- Uses
adachsoft/normalized-safe-pathunder the hood to normalize and validate paths. - Any attempt to escape the base directory (path traversal such as
../..) results in an exception.
Quick start
1. Basic usage
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use AdachSoft\PromptTemplateLib\PublicApi\PromptEngineFactory;
use AdachSoft\PromptTemplateLib\Spi\PromptFunctionInterface;
// Create engine with standard functions <datetime> and <file_read(...)>
$engine = PromptEngineFactory::createDefault(__DIR__);
// Register custom function <user_name>
$engine->registerFunction(new class implements PromptFunctionInterface {
public function getName(): string
{
return 'user_name';
}
public function execute(array $arguments): string
{
return 'Example User';
}
});
$template = "Hello <user_name>, today is <datetime('Y-m-d')>.\n" .
"Prompt: <file_read('README.md')>";
echo $engine->render($template);
2. Using in your application
In a real project you would typically:
- Configure the base directory for
file_readvia configuration/env. - Use dependency injection to construct
PromptEngineInterface(or callPromptEngineFactory::createDefault()at your composition root). - Register your own
PromptFunctionInterfaceimplementations during bootstrap.
Error handling
The library uses a focused set of dedicated exceptions in the PublicApi\Exception namespace:
PromptTemplateException– base class for all library-specific errors.InvalidFunctionNameException– a prompt function was registered with a name that violates the naming rules.InvalidFunctionArgumentException– a prompt function received invalid arguments (wrong count, type or value).UnknownFunctionException– template references a tag name that is not registered in the engine.TemplateSyntaxException– syntax error in template tags or arguments.FunctionExecutionException– wrapper thrown by the engine when a function throws an unexpected exception.
Implementations of PromptFunctionInterface SHOULD:
- throw
InvalidFunctionArgumentExceptionwhen the parsed arguments coming from a template tag are invalid, - throw other
PromptTemplateExceptionsubclasses for domain-specific problems (I/O errors, missing resources, security violations), - let unexpected
Throwablebubble up; it will be wrapped inFunctionExecutionExceptionby the parser.
Testing
The repository includes a PHPUnit test suite covering:
- Public API (
PromptEngineInterface,PromptEngine,PromptEngineFactory) - Internal parser (
TemplateParser) and registry (FunctionRegistry) - Standard functions (
DateTimeFunction,FileReadFunction)
Run tests with:
vendor/bin/phpunit
License
This library is released under the MIT License.