In traditional web application development, input has been treated as merely a "transit point." Ray.InputQuery introduces a revolutionary approach that recognizes input as an independent domain deserving its own abstraction.
class User {
private $id;
private $name;
public function changeName($name) { ... } // Business logic
}Persisted business objects with identity and behavior.
class UserDto {
public $id;
public $name;
// No logic, used for both input and output
}Data carriers that don't express structure or intent.
final class UserRegistrationInput {
public function __construct(
#[Input] public readonly string $name,
#[Input] public readonly string $email,
#[Input] public readonly PasswordInput $password,
#[Input] public readonly bool $agreeToTerms // UI state included!
) {}
}From external sources (forms, APIs) to internal application only. Never used for output.
final class CheckoutInput {
public function __construct(
#[Input] public readonly CartInput $cart,
#[Input] public readonly ShippingAddressInput $shipping,
#[Input] public readonly PaymentMethodInput $payment,
#[Input] public readonly ?string $couponCode = null
) {}
}This mirrors the checkout screen structure exactly!
Not persisted. Exists only at the entry point and disappears after processing.
final class PasswordInput {
public function __construct(
#[Input] public readonly string $password,
#[Input] public readonly string $passwordConfirm // Only needed during input
) {}
}passwordConfirm is unnecessary in entities but essential during input. This distinction is naturally expressed.
Traditional:
[Untyped Zone] → Manual Conversion → [Typed Zone]
$_POST Validation Entity
Ray.InputQuery:
[Typed Zone ←→ Typed Zone ←→ Typed Zone]
Form Input Class Entity
Type safety extended to the system's outermost edges!
Imperative (Traditional):
$title = $_POST['title'] ?? '';
$authorName = $_POST['author_name'] ?? '';
if (empty($title)) {
throw new ValidationException('Title required');
}
$author = new Author($authorName, $_POST['author_email']);
$todo = new Todo($title, $author);Declarative (Ray.InputQuery):
final class TodoInput {
public function __construct(
#[Input] public readonly string $title,
#[Input] public readonly AuthorInput $author
) {}
}From "how to transform" to "what it should be"
HTTP Request:
POST /articles/123/comments
author_name=John&author_email=john@example.com&content=Great!
Input Class:
final class CommentInput {
public function __construct(
#[Input] public readonly string $content,
#[Input] public readonly AuthorInput $author
) {}
}Web's fundamental structure (query/form data) directly becomes objects!
HTML:
<form>
<fieldset>
<legend>Shipping Address</legend>
<input name="shipping_street">
<input name="shipping_city">
</fieldset>
</form>PHP:
final class OrderInput {
public function __construct(
#[Input] public readonly ShippingAddressInput $shipping
) {}
}HTML structure and PHP structure match perfectly!
Input Class (PHP)
/ \
/ \
Form JSON Schema
(HTML) (Specification)
- Input Class: Type-safe implementation
- HTML Form: User interface
- JSON Schema: Specification and validation
All express the same structure in different formats.
Developer looks at form
↓
Manually writes validation code
↓
Manually writes mapping code
Define form
↓
Define Input class (declare structure)
↓
Automatically transformed
HTML Form
↓
AI: "Generate Input class for this form"
↓
Done!
final class OrderProcessInput {
public function __construct(
// Data (external input)
#[Input] public readonly string $orderId,
#[Input] public readonly CustomerInput $customer,
#[Input] public readonly ?string $couponCode,
// Services (internal capabilities)
private OrderService $orderService,
private NotificationService $notifier
) {}
public function process(): OrderResult {
// Combining input data with services
$order = $this->orderService->create($this->orderId, $this->customer);
if ($this->couponCode) {
$order->applyCoupon($this->couponCode);
}
$this->notifier->notify($order);
return $order;
}
}Treating input not just as data, but as objects with processing capabilities!
Ray.InputQuery fundamentally changes traditional development approaches in the following ways:
- Input Independence: Recognizing input as an independent domain
- Structural Alignment: Forms, code, and specifications share the same structure
- Type Extension: Extending type safety to external boundaries
- Declarative Design: Focus on "what" and automate "how"
This is not just a convenient tool, but a proposal for a new way of thinking in web application development.
The shift from "getting data from forms" to "defining input structure" opens the path to better web application development.