WebForms.php 2.1 Released - DeepSeek Converted and Qwen Evaluated
Elanat FrameworkDEV Community
1 views
WebForms.php 2.1 has been released as the PHP back-end implementation of WebForms Core 2.1.
This release is different from a typical porting story.
The PHP implementation was converted from the C# implementation of WebForms Core using DeepSeek, and then independently evaluated with Qwen.
The process was not simply:
C# → PHP
It was:
C# → DeepSeek conversion → manual review → Qwen evaluation → corrections → testing → release
This article explains that process and some of the interesting problems that appeared during the conversion.
What is WebForms.php?
WebForms.php is the PHP back-end part of WebForms Core.
WebForms Core is a server-driven web technology based on the Commander–Executor concept.
The server generates commands that describe UI operations and execution flow. WebFormsJS, running in the browser, interprets and executes those commands.
The WebForms class itself does not manipulate the browser DOM directly.
It generates the WebForms Core command structure.
This makes the WebForms class particularly suitable for implementation in multiple programming languages.
The PHP implementation provides the same WebForms Core programming model for PHP applications.
Why Convert the C# Implementation?
WebForms Core already has implementations for multiple programming languages.
The C# implementation is the primary reference implementation and contains a large number of methods for:
DOM manipulation
event management
Fetch operations
conditions
loops
state management
storage
browser history
WebSockets
SSE
templates
selectors
Action Controls
and other WebForms Core operations
The WebForms class mainly generates command strings.
Because of this architecture, the fundamental logic does not need to be redesigned for every language.
The objective of the PHP implementation was therefore to preserve the behavior and output of the C# implementation while adapting the code to PHP conventions and language capabilities.
DeepSeek Conversion
I provided the C# implementation and related helper classes to DeepSeek.
The instructions were intentionally strict.
DeepSeek was asked to first analyze the structure and explain the conversion approach.
The important requirement was that the conversion should preserve the behavior of the C# implementation.
However, the PHP implementation should not simply look like C# code written with PHP syntax.
The destination language's conventions were explicitly required.
For example, PHP naming conventions should be used where appropriate.
A C# method such as:
SetWidth(...)
should become:
setWidth(...)
and parameters should follow PHP naming conventions:
$inputPlace
$width
rather than preserving C#-style parameter names such as:
$InputPlace
$Width
The same principle applied to language features.
If C# used a feature that did not exist in PHP, the conversion needed to use an appropriate PHP equivalent rather than attempting to reproduce the syntax literally.
Overloading Was One of the Interesting Problems
C# supports method overloading.
PHP does not support traditional method overloading based on parameter signatures in the same way.
Therefore, overloaded C# methods needed to be represented using PHP language features where possible.
For example, instead of creating unnecessary methods for different parameter types, PHP Union Types can be used.
A method can accept:
string|int
and determine the appropriate behavior internally.
For example:
public function setWidth(string $inputPlace, string|int $width): void
{
if (is_int($width)) {
$width .= 'px';
}
$this->add('sw' . $inputPlace, $width);
}
This keeps the public API compact while preserving the behavior expected from the overloaded C# methods.
Nullable parameters were also handled using PHP's nullable types and default values.
For example:
?int $second = null
can represent an optional second argument when converting an overloaded method such as a random-number operation.
The important point is that the goal was not to reproduce the C# method signatures.
The goal was to preserve their behavior using the capabilities of PHP.
The First Review
After the DeepSeek conversion, the generated code was reviewed manually.
This was necessary because syntactically valid PHP does not necessarily mean behaviorally compatible PHP.
The two languages have important differences in:
type conversion
null handling
method overloading
string conversion
arrays
optional parameters
naming conventions
object handling
A port can therefore compile and run while still producing a different WebForms Core command.
This is particularly important for WebForms Core because the generated command is effectively part of the protocol between the WebForms class and WebFormsJS.
A small difference in generated output can therefore become a functional difference.
Qwen Evaluation
After the initial conversion, I gave the PHP implementation to Qwen for an independent evaluation.
The purpose was not to ask Qwen to rewrite the entire implementation.
It was asked to evaluate the conversion and look for incompatibilities between the PHP implementation and the original C# behavior.
This produced several useful findings.
Two of them were particularly important.
Issue 1: implode() and Mixed-Type Arguments
The C# implementation could use:
string.Join(US, Args)
where Args could contain objects or values of different types.
C# converts the values to their string representation when joining them.
The corresponding PHP implementation initially used:
implode(self::US, $Args)
This is not equivalent for arbitrary mixed values.
PHP's behavior around non-string values passed to implode() is different, particularly with newer PHP versions.
Qwen therefore identified the need to explicitly convert the values:
implode(
self::US,
array_map('strval', $Args)
)
This makes the intended conversion explicit and avoids relying on PHP's implicit behavior.
The important lesson was that a direct API-to-API translation is not always a semantic translation.
The C# expression and the PHP expression may look equivalent while behaving differently with real input types.
Issue 2: null and Empty String Behavior
Another issue involved the internal add() method.
The C# implementation uses StringBuilder.Append().
Appending a null value does not insert the four characters "null" and does not remove the preceding structure. It effectively contributes an empty string.
This distinction matters when generating WebForms Core commands.
The PHP implementation initially treated a null value differently.
For methods such as:
deleteState(?string $path = null)
the generated command could therefore differ from the C# implementation.
Qwen identified this difference and suggested explicitly normalizing the null value:
$this->add('DS', $path ?? '');
The result preserves the command structure expected from the C# implementation.
This was not a syntax error.
Both versions were valid PHP.
It was a cross-language semantic difference.
Other Findings
Qwen also identified several other areas that required attention during the conversion.
These included handling overloaded methods using PHP Union Types, optional and nullable parameters, and type-based routing in helper methods.
For example, the InputPlace::attribute implementation can use the PHP type system to distinguish different forms of the original overloaded API.
Qwen also identified corrections related to specific converted values, including the CPP value in WasmLanguage and the prefix generated by SetMaxLength.
These findings were reviewed against the intended WebForms Core behavior before being incorporated.
The purpose of this process was not to assume that every suggestion from an AI evaluator was automatically correct.
Each finding still had to be compared with the original implementation and the intended protocol.
AI Did Not Replace Testing
This is probably the most important part of this release.
DeepSeek was useful for producing the initial PHP implementation.
Qwen was useful as an independent reviewer.
But neither replaced testing.
The final implementation was reviewed against the original C# implementation and tested for compatibility with WebFormsJS.
This distinction matters.
AI can identify a large number of repetitive transformations very quickly.
It can also identify subtle differences that are easy to miss during manual review.
However, the final authority is still the actual behavior of the software.
The workflow therefore became:
C# Reference Implementation
↓
DeepSeek
↓
PHP Conversion
↓
Manual Review
↓
Qwen
↓
Semantic Corrections
↓
Testing
↓
WebForms.php 2.1
PHP Conventions
One of the goals of the conversion was to make WebForms.php feel like PHP code rather than C# code translated into PHP syntax.
This includes method naming, parameter naming, type declarations, nullable parameters, Union Types, arrays, and other language-specific constructs.
For example, PHP should use:
$inputPlace
$width
$maxValue
rather than carrying C# naming conventions into the PHP API.
At the same time, the generated WebForms Core commands must remain compatible with the existing WebFormsJS runtime.
This creates an important separation:
The implementation follows PHP conventions.
The generated protocol follows WebForms Core conventions.
That separation is fundamental to a multi-language implementation.
Using WebForms.php
WebForms.php can be used directly by including the PHP class:
<?php
include 'WebForms.php';
use WebFormsCore\WebForms;
use WebFormsCore\Fetch;
$form = new WebForms();
$form->setText("message", "Hello from PHP!");
echo $form->response();
It can also be installed as a Composer package.
After installing the package, the Composer autoloader can be included:
require __DIR__ . '/vendor/autoload.php';
and the WebForms Core classes can be used normally.
A Small PHP Example
A simple example can use WebForms.php to create an interactive game without writing JavaScript business logic.
For example, a small "Flower or Empty" game can be implemented with HTML containing only the interface:
<button value="0" win-with="1">
🌹 Flower
</button>
<button value="1" win-with="0">
✊ Empty
</button>
<p id="computer">
Computer choice:<span></span>
</p>
<p id="result"></p>
The PHP code then defines the behavior:
<?php
require __DIR__ . '/vendor/autoload.php';
use WebFormsCore\WebForms;
use WebFormsCore\Fetch;
?>
<!DOCTYPE html>
<html>
<head>
<title>Gol Ya Pooch - WebForms Core</title>
<script type="module" src="/script/web-forms.js"></script>
</head>
<body>
<h1>🌹 Gol Ya Pooch ✊</h1>
<p>Choose one:</p>
<button value="0" win-with="1" id="flower">
🌹 Flower
</button>
<button value="1" win-with="0" id="empty">
✊ Empty
</button>
<p id="computer">
Computer choice:<span></span>
</p>
<p id="result"></p>
<p>
Games:
<span id="counter">0</span>
</p>
<p>
Wins:
<span id="win-counter">0</span>
</p>
</body>
</html>
<?php
$form = new WebForms();
$form->setCommentEvent("<button>*", "onclick", "play");
$form->setFontSize("<button>*?.<p>*", 40);
$form->startIndex("play");
// Increase game counter
$form->increase("counter", 1);
// Generate and save computer choice
// 0 = Flower, 1 = Empty hand
$form->addSaveValue("random", Fetch::random(0, 2));
// Player wins
$form->isEqualTo(Fetch::getAttribute("$", "win-with"), Fetch::save("random"));
$form->startBracket();
$form->setText("result", "😀 You win!");
$form->increase("win-counter", 1);
$form->endBracket();
$form->else(); // Equal
$form->setText("result", "😢 You lose!");
// Show computer choice
$form->isEqualTo("0", Fetch::save("random"));
$form->setText("computer|<>", "🌹 Flower");
$form->else();
$form->setText("computer|<>", "✊ Empty");
echo $form->exportToHtmlComment();
?>
The example demonstrates an important property of WebForms Core.
The PHP code describes the behavior.
The browser executes the resulting WebForms Core commands through WebFormsJS.
No JavaScript business logic is required for the game.
Game screenshot
WebForms.php 2.1 and WebFormsJS 2.1
WebForms.php 2.1 is designed for WebFormsJS 2.1.
The two components work together as the server-side command generator and client-side executor.
WebForms Core 2.1 introduced a large number of new capabilities, including nested conditions, Then, Repeat, ForEach, advanced element selection, WPC criteria, State improvements, template rendering, debugging, improved history management, and other runtime improvements.
The PHP implementation exposes the corresponding server-side API for PHP applications.
WebForms Core 2.1 was also extensively tested for compatibility between its WebForms classes and WebFormsJS. The main 2.1 release went through more than three months of compatibility testing and reported a greater than 99% test success rate.
Package Distribution
WebForms.php is distributed as a Composer package.
The package name is:
webforms-core/php
It can be installed with:
composer require webforms-core/php
The package uses Composer autoloading so that the WebForms.php implementation is loaded through:
require __DIR__ . '/vendor/autoload.php';
This makes WebForms.php available through the standard PHP package ecosystem.
Conclusion
WebForms.php 2.1 is not simply a translation of C# code into PHP syntax.
It is a PHP implementation of the WebForms Core 2.1 server-side programming model.
The development process was also an experiment in AI-assisted multi-language development.
DeepSeek performed the initial conversion.
Manual review identified language-specific differences.
Qwen independently evaluated the result and identified semantic compatibility problems that were not obvious from the syntax alone.
The final implementation was then corrected and tested.
The experience demonstrated something important about using AI for software porting:
AI can significantly accelerate a language conversion, but successful porting requires more than generating syntactically valid code.
The difficult part is preserving behavior across languages.
C# and PHP have different type systems, different conventions, different overload mechanisms, and different runtime behavior.
A reliable port therefore needs to preserve the protocol and semantics while allowing the implementation to become native to its destination language.
You can use the PHP version with complete confidence. If there is any problem, it will be fixed very soon by Elanat.
That is the approach used for WebForms.php 2.1.
DeepSeek converted it.
Qwen evaluated it.
Testing validated it.
WebForms.php 2.1 is now released.
Over the past few days, I was trying out gov.uk prototype system for my static website. Like every night owl, the unbranded template's white background was hurting my eyes. I googled for some sort of dark mode, found The National Archives Design System. It suits my purpose, has the dark mode, and i
When working with JavaScript functions, you will often hear two terms: parameters and arguments.
They are closely related, but they have different meanings.
What is a Parameter?
A parameter is a variable that we define inside the function's parentheses when creating a function.
It acts
I used Codex to its fullest potential as a research partner—for code mapping, source comparison, evidence organization, consistency checks, editorial control, and deliverable preparation. I formulated the intent, defined the scope, interpreted the results, arbitrated the conclusions, and preserved e