cosmira / lua-builder
Expressive, framework-independent Lua code generation for PHP.
Requires
- php: ^8.2
Requires (Dev)
- infection/infection: ^0.29.14 || ^0.32.4
- laravel/pint: ^1.27
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5
- rector/rector: ^2.5
- symfony/process: ^7.0 || ^8.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Generate Lua scripts from PHP.
Build configuration files and application-generated scripts from your PHP data. Compose functions, conditions, and loops while the builder takes care of quoting, expression grouping, and indentation.
use Cosmira\Lua\Lua; echo Lua::script()->return([ 'name' => 'Moonlight', 'enabled' => true, 'servers' => ['127.0.0.1', '192.168.1.1'], ]);
return {["name"] = "Moonlight", ["enabled"] = true, ["servers"] = {"127.0.0.1", "192.168.1.1"}};
Requires PHP 8.2+. No framework or runtime dependencies. Generated syntax targets Lua 5.1–5.4 and LuaJIT. The package generates source; your application decides where to save or execute it.
Installation
The development version is available directly from GitHub. In your PHP project:
composer config repositories.cosmira-lua vcs https://github.com/cosmira/lua-builder composer require cosmira/lua-builder:dev-main
Load vendor/autoload.php when running the examples outside a framework.
A stable Packagist release has not been published yet.
Three concepts
| Concept | Example | Meaning |
|---|---|---|
| PHP values | 'hello', 42, ['enabled' => true] |
Data, quoted and encoded automatically |
| Expressions | Lua::var('score')->greaterThan(80) |
A value Lua computes when the script runs |
| A script | Lua::script()->call('print', 'hello') |
Commands emitted in order |
Strings always mean data. Use Lua::var() for a variable and Lua::call() when
you need the result of a function call. The script's ->call() adds a standalone
call. Start an expression from a literal with Lua::value().
Lua::script() ->local('maximum', Lua::call('math.max', 10, 20)) ->call('print', Lua::var('maximum'));
Functions and conditions
Callbacks describe nested bodies using the same script API:
use Cosmira\Lua\Lua; use Cosmira\Lua\Script; $score = Lua::var('score'); echo Lua::script() ->localFunction('grade', ['score'], function (Script $lua) use ($score) { $lua->if( $score->greaterThanOrEqual(80), fn (Script $lua) => $lua->return('passed'), ); $lua->return('try again'); }) ->call('print', Lua::call('grade', 90));
local function grade(score) if (score >= 80) then return "passed"; end return "try again"; end print(grade(90));
->if($condition, $then, $otherwise) generates a Lua conditional. Both supplied
PHP callbacks run while constructing their branches; Lua evaluates the condition
when the generated program executes. The otherwise callback is optional.
Tables and loops
echo Lua::script() ->local('services', ['api', 'worker']) ->forEach( ['index', 'service'], Lua::call('ipairs', Lua::var('services')), fn (Script $lua) => $lua->call('print', Lua::var('index'), Lua::var('service')), );
local services = {"api", "worker"}; for index, service in ipairs(services) do print(index, service); end
Expressions are immutable. Scripts accumulate commands and can be cloned to create independent variants. Literal strings preserve arbitrary bytes, including quotes, UTF-8 emoji, Windows-1251, Japanese encodings, and NUL. No encoding conversion or Unicode normalization is performed. Names and operators are validated.
Lua's data model applies: lists start at 1, nil removes table entries, and numeric
precision depends on the Lua runtime. Raw source is an explicit escape hatch for
trusted code only. See the API reference for all operations,
value semantics, errors, and supported syntax.
Building rules from application data
The executable rules example combines nested filter tables, optional date bounds, generated callbacks, and ordered actions. PHP decides which rules to emit; Lua evaluates their conditions later. Opaque rule IDs are table keys, so they can contain punctuation or Japanese text without becoming function names. Runtime tests exercise matching, short-circuiting, date boundaries, and action order.
Keep model access, sorting, encoding conversion, and domain validation in your application. Pass plain arrays and values into the builder. The host supplies application behavior when Lua executes.
Development
git clone https://github.com/cosmira/lua-builder.git cd lua-builder composer install LUA_BIN=lua5.1 composer test LUA_BIN=lua5.1 composer check
Install PHP, Composer, and Lua first. Set LUA_BIN to your interpreter's name or
absolute path; it defaults to lua. Runtime tests require a working interpreter.
Coverage requires PCOV or an enabled Xdebug coverage driver.
composer check runs Pint, PHPStan, Rector, tests, 100% line coverage, and
100% mutation score gates. GitHub Actions tests PHP 8.2–8.5, Lua 5.1–5.4, and
LuaJIT. Reports are uploaded as CI artifacts. See CONTRIBUTING.md
for individual commands, project structure, and release conventions.
License
MIT. Maintained by Alexandr Chernyaev and Cosmira. See LICENSE.md.