monolyth/formulaic
Composer 安装命令:
composer require monolyth/formulaic
包简介
Monolyth unframework object oriented form tools
README 文档
README
Object-oriented form utilities for PHP8.1+
HTML forms suck. Well, no, they're superduper handy, but writing them and validating them server-side can be a pain. Formulaic offers a set of utilities to ease that pain.
Basic usage
Define a form with some fields and other requirements:
<?php use Monolyth\Formulaic\Get; use Monolyth\Formulaic\Search; use Monolyth\Formulaic\Button\Submit; class MyForm extends Get { public function __construct() { $this[] = (new Search('q'))->isRequired(); $this[] = new Submit('Go!', 'submit'); } }
In your template, either use the API to manually tweak your output, or simply
__toString the form to use the defaults:
<?php $form = new MyForm; echo $form;
You can __toString individual fields:
<?php $form = new MyForm; ?> <form name="search" method="get"> <!-- These two yield identical output using MyForm above: --> <?=$form[0]?> <?=$form['q']?> </form>
To validate your form:
<?php $form = new MyForm; if ($form->valid()) { // ...Perform the search... }
To get a list of errors:
<?php $form = new MyForm; if ($errors = $form->errors()) { // ...Do error handling, or give feedback... }
Forms can contain fieldsets:
<?php use Monolyth\Formulaic\Get; use Monolyth\Formulaic\Fieldset; use Monolyth\Formulaic\Search; use Monolyth\Formulaic\Button\Submit; class MyForm extends Get { public function __construct() { $this[] = new Fieldset('Global search', function($fieldset) { $fieldset[] = new Search('q'); }); $this[] = new Fieldset('Search by ID', function($fieldset) { $fieldset[] = new Search('id'); }); $this[] = new Submit('Go!'); } }
And in your output:
<form method="get">
<?=$form['Global search']?>
<?=$form['Search by ID']?>
<?=$form['submit']?>
</form>
Custom elements in forms
Simply add strings to the form; they will be outputted verbatim:
<?php // ... class Form extends Get { public function __construct() { $this[] = new Radio('foo'); $this[] = '<h1>custom HTML element!</h1>'; } }
Under the hood
As you will have guessed, the Post and Get forms look at posted and get data
respectively. This means any matching data in the superglobal (which, for
Post, includes $_FILES) is automagically set on the form. For elements in
groups (excluding fieldsets), Formulaic assumes they will be in a sub-array:
<?php use Monolyth\Formulaic\{ Get, Element\Group, Text }; class Form extends Get { public function __construct() { $this[] = new Group('foo', function ($group) { $group[] = new Text('bar'); }); } }
This will match $_GET['foo']['bar'] for a value.
For checkbox groups (a set of related checkboxes, e.g. for settings), the values
are presumed to be in their own array. E.g. with a checkbox group named 'foo'
the values will be passed as $_POST['foo'] = [1, 2, 3].
Adding tests
Form elements can contain tests, which the vaild() and error() methods use
to produce output. A number of tests (like isRequired()) are pre-supplied, but
you can easily add your own via the addTest method on elements:
<?php $input = new Text('foo'); $input->addTest(fn ($value) => $value == 'bar');
The above test will fail unless the user enters "bar" into the text input.
Binding models
Where Formulaic also really shines is in propagating the form data to your
models. All the boilerplate code containing numerous isset calls? Gone!
Your model is an object. Literally any object. What you want is for any property's previously filled value to be automatically set on your form, and for any value entered by the user to be updated on the object (which you can then persist to a database or whatever, that's up to you). Guess what? It's easy!
<?php class MyFrom extends Post { //... define the form public function __construct() { $this[] = new Text('foo'); } } $model = new stdClass; $model->foo = 'bar'; $form = new MyForm; $form->bind($model);
In the above example, the form in question - when __toStringed - will have a
default value of "bar" for the foo input. If $_POST['foo'] happens to
contain "buzz", it will instead contain that. Even better, after the call to
bind it will also be so that $model->foo === 'buzz' equals true. Awesome!
That's a gazillion lines of code you no longer have to think about!
Binding can be done on any level, just remember that it needs to be on an object and that its (sub)properties must match the element's names.
You'll notice that this ties the model structure to the form buildup; however, that doesn't matter. The form elements are displayed "as is", it's just their names that need to match the model.
Transforming data
In the real world, model objects are often a lot more complicated than HTML forms, which basically deal with strings. Enter transformers: Formulaic's way of converting data to and from your models.
All elements support the withTransformer method, which basically accepts a
callable. The idea here is that the callable's argument is type hinted (so as to
determine which transformer to use) and it returns a suitable value based on
that type. An acceptable transformer for a certain situation might be:
<?php class MyModel { public Foo $foo; } class MyForm extends Post { public function __construct() { $this[] = (new Text('foo')) ->withTransformer(fn(string $value) => new Foo($value)); } } $model = new MyModel; $form = new MyForm; $form->bind($model); echo get_class($model->foo); // Foo
You can define multiple transformers in one go with the withTransformers
method (note the plural). Each argument is a callable.
Typically, you'll need two transformers: one from the model to the form, and one from the form back to the model. In some cases, the input may vary depending on the complexity of your project; define as many transformers as you need.
The input type hint may be a union in which case the transformer is valid for multiple types. Intersection type hints are not supported as they wouldn't really make sense in a transformation context.
GET forms gotcha!
In PHP, it is not possible to distinguish a "regular" page load from one
triggered by a submitted GET form (unlike POST requests). To determine whether
or not the user supplied values, Formulaic simply checks $_GET for truthiness.
Note that this may or may not be sufficient for your needs; theoretically, an
entirely empty form could be submitted which should still trigger this, or
the URL may already contain (unrelated) GET-parameters.
In these corner cases, extend the Get form and implement your own
wasSubmitted method doing an alternative check, e.g. for a hidden form field
or a named submit button.
For post forms, the user is assumed to have supplied values whenever
$_SERVER['REQUEST_METHOD'] == 'POST'. Again, situations may arise where this
check is not good enough for you - extend and override, again.
Other methods than GET or POST
In casu, PUT or DELETE may crop up. These are not supported out of the box, since Formulaic is an HTML form library, and HTML only supports GET and POST. However, it is not unthinkable you would like to use validation and binding logic in controllers handling AJAX calls for instance. In that case, feel free to extend your own form class.
Any extension will want to implement the getSource method, e.g. for PUT you
will manually parse file_get_contents('php://input'). Since we can't know what
that contains (likely JSON, but assumption is the mother of all fuckup...)
you'll need to write your own implementation suiting your needs.
Similarly, DELETE can contain GET data in the URL. We're not really sure when
this would be necessary, but there you have it - a custom Delete form would
likely extend GET.
monolyth/formulaic 适用场景与选型建议
monolyth/formulaic 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 786 次下载、GitHub Stars 达 0, 最近一次更新时间为 2016 年 07 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「form」 「HTML5」 「validation」 「oo」 「monolyth」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 monolyth/formulaic 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 monolyth/formulaic 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 monolyth/formulaic 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
HTML5 support for SilverStripe
HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.
Diese Contao 4 Erweiterung stellt Google reCAPTCHA V2 in Form eines neuen Formularfeldes im Formulargenerator bereit. This extension provides Google reCAPTCHA V2 in the form of a new form field in the form generator of Contao Open Source CMS.
The yii2-videojs-widget is a Yii 2 wrapper for the [video.js](http://www.videojs.com/). A JavaScript and CSS library that makes it easier to work with and build on HTML5 video. This is also known as an HTML5 Video Player.
A Laravel Filament Forms slug field.
A jQuery augmented PHP library for creating and validating HTML forms
统计信息
- 总下载量: 786
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 13
- 依赖项目数: 1
- 推荐数: 2
其他信息
- 授权协议: MIT
- 更新时间: 2016-07-16