tobento / service-form
轻松构建HTML表单。
Requires
- php: >=8.0
- tobento/service-collection: ^1.0
- tobento/service-message: ^1.0
Requires (Dev)
- nyholm/psr7: ^1.4
- nyholm/psr7-server: ^1.0
- phpunit/phpunit: ^9.5
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- tobento/service-container: ^1.0
- tobento/service-middleware: ^1.0
- tobento/service-requester: ^1.0
- tobento/service-responser: ^1.0
- tobento/service-session: ^1.0
- vimeo/psalm: ^4.0
Suggests
- psr/http-message: Required for using middleware
- psr/http-server-handler: Required for using middleware
- psr/http-server-middleware: Required for using middleware
- tobento/service-requester: Required for using middleware
- tobento/service-responser: Required for using ResponserFormFactory
- tobento/service-session: Required for using session tokenizer
README
构建HTML表单。
目录
入门
使用以下命令添加运行此项目的html服务项目的最新版本。
composer require tobento/service-form
要求
- PHP 8.0或更高版本
亮点
- 框架无关,适用于任何项目
- 解耦设计
文档
创建表单
use Tobento\Service\Form\Form; use Tobento\Service\Form\InputInterface; use Tobento\Service\Form\TokenizerInterface; use Tobento\Service\Form\ActiveElementsInterface; use Tobento\Service\Message\MessagesInterface; $form = new Form( input: null, // null|InputInterface tokenizer: null, // null|TokenizerInterface activeElements: null, // null|ActiveElementsInterface messages: null // null|MessagesInterface );
参数说明
表单工厂
您可以使用表单工厂创建表单类。
ResponserFormFactory
首先,请确保您已安装了responser服务
composer require tobento/service-responser
查看Responser服务以了解更多信息。
use Tobento\Service\Form\FormFactoryInterface; use Tobento\Service\Form\ResponserFormFactory; use Tobento\Service\Form\ActiveElementsInterface; use Tobento\Service\Form\Form; use Tobento\Service\Responser\ResponserInterface; $formFactory = new ResponserFormFactory( responser: $responser, // ResponserInterface tokenizer: null, // null|TokenizerInterface activeElements: null, // null|ActiveElementsInterface ); var_dump($formFactory instanceof FormFactoryInterface); // bool(true) $form = $formFactory->createForm(); var_dump($form instanceof Form); // bool(true)
表单元素
表单
<?= $form->form() ?> // <form method="POST"> <?= $form->close() ?> // </form>
表单属性
<?= $form->form(attributes: ['method' => 'GET']) ?> // <form method="GET">
输入
<?= $form->input( name: 'name', type: 'text', value: 'value', attributes: [], selected: null, withInput: true, ) ?> // <input name="name" id="name" type="text" value="value">
参数说明
复选框类型
<?= $form->input( name: 'colors[]', type: 'checkbox', value: 'red', attributes: ['id' => 'colors_red'], selected: ['red'], // or 'red' ) ?> // <input id="colors_red" name="colors[]" type="checkbox" value="red" checked>
复选框
您可以使用复选框方法创建带有其标签的多个复选框输入元素。
<?= $form->checkboxes( name: 'colors', items: ['red' => 'Red', 'blue' => 'Blue'], selected: ['blue'], attributes: [], labelAttributes: [], withInput: true, wrapClass: 'form-wrap-checkbox' ) ?> /* <span class="form-wrap-checkbox"> <input id="colors_1" name="colors[]" type="checkbox" value="red"> <label for="colors_1">Red</label> </span> <span class="form-wrap-checkbox"> <input id="colors_2" name="colors[]" type="checkbox" value="blue" checked> <label for="colors_2">Blue</label> </span> */
参数说明
带有每个的复选框
如果您有一个对象数组或只想对复选框的值、标签和名称的数组键有更多控制,您可以使用each方法。
$items = ['red' => 'Red', 'blue' => 'Blue']; <?= $form->checkboxes( name: 'colors', items: $form->each(items: $items, callback: function($item, $key): array { // value:string, label:string|null, array-key:string|null return [$key, strtoupper($item), $key]; }), selected: ['blue'], ) ?> /* <span class="form-wrap-checkbox"> <input id="colors_red" name="colors[red]" type="checkbox" value="red"> <label for="colors_red">RED</label> </span> <span class="form-wrap-checkbox"> <input id="colors_blue" name="colors[blue]" type="checkbox" value="blue" checked> <label for="colors_blue">BLUE</label> </span> */
单选框类型
<?= $form->input( name: 'colors', type: 'radio', value: 'red', attributes: ['id' => 'colors_red'], selected: 'red', ) ?> // <input id="colors_red" name="colors" type="radio" value="red" checked>
单选框
您可以使用单选框方法创建带有其标签的多个单选框输入元素。
<?= $form->radios( name: 'colors', items: ['red' => 'Red', 'blue' => 'Blue'], selected: 'blue', attributes: [], labelAttributes: [], withInput: true, wrapClass: 'form-wrap-radio' ) ?> /* <span class="form-wrap-radio"> <input id="colors_1" name="colors[]" type="radio" value="red"> <label for="colors_1">Red</label> </span> <span class="form-wrap-radio"> <input id="colors_2" name="colors[]" type="radio" value="blue" checked> <label for="colors_2">Blue</label> </span> */
参数说明
带有每个的单选框
如果您有一个对象数组或只想对值和标签有更多控制,您可以使用each方法。
$items = ['red' => 'Red', 'blue' => 'Blue']; <?= $form->radios( name: 'colors', items: $form->each(items: $items, callback: function($item, $key): array { // value:string, label:string|null return [$key, strtoupper($item)]; }), selected: 'blue', ) ?> /* <span class="form-wrap-radio"> <input id="colors_red" name="colors" type="radio" value="red"> <label for="colors_red">RED</label> </span> <span class="form-wrap-radio"> <input id="colors_blue" name="colors" type="radio" value="blue" checked> <label for="colors_blue">BLUE</label> </span> */
标签
<?= $form->label( text: 'Text', for: 'colors', attributes: [], requiredText: '', optionalText: '', ) ?> // <label for="colors">Text</label>
参数说明
带有必填文本
<?= $form->label( text: 'Text', requiredText: 'required', ) ?> // <label>Text<span class="required">required</span></label>
带有可选文本
<?= $form->label( text: 'Text', optionalText: 'optional', ) ?> // <label>Text<span class="optional">optional</span></label>
选择
<?= $form->select( name: 'colors[]', items: ['red' => 'Red', 'blue' => 'Blue'], selected: ['blue'], selectAttributes: ['multiple'], optionAttributes: [], optgroupAttributes: [], emptyOption: null, withInput: true, ) ?> /* <select multiple name="colors" id="colors"> <option value="red">Red</option> <option value="blue" selected>Blue</option> </select> */
参数说明
带有optgroup元素
<?= $form->select( name: 'roles', items: [ 'Frontend' => [ 'guest' => 'Guest', 'registered' => 'Registered', ], 'Backend' => [ 'editor' => 'Editor', 'administrator' => 'Aministrator', ], ], ) ?> /* <select name="roles" id="roles"> <optgroup label="Frontend"> <option value="guest">Guest</option> <option value="registered">Registered</option> </optgroup> <optgroup label="Backend"> <option value="editor">Editor</option> <option value="administrator">Aministrator</option> </optgroup> </select> */
使用每个方法
如果您有一个对象数组或只想对值、标签和单选框名称的数组键有更多控制,您可以使用each方法。
$items = ['red' => 'Red', 'blue' => 'Blue']; <?= $form->select( name: 'colors', items: $form->each(items: $items, callback: function($item, $key): array { // value:string, label:string|null return [$key, strtoupper($item)]; }), selected: 'blue', ) ?> /* <select name="colors" id="colors"> <option value="red">RED</option> <option value="blue" selected>BLUE</option> </select> */
带有空选项
<?= $form->select( name: 'colors', items: ['red' => 'Red', 'blue' => 'Blue'], emptyOption: ['none', '---'], ) ?> /* <select name="colors" id="colors"> <option value="none">---</option> <option value="red">Red</option> <option value="blue">Blue</option> </select> */
文本区域
<?= $form->textarea( name: 'description', value: 'Lorem ipsum', attributes: [], withInput: true, ) ?> // <textarea name="description" id="description">Lorem ipsum</textarea>
参数说明
按钮
<?= $form->button( text: 'Submit Text', attributes: [], escText: true, ) ?> // <button type="submit">Submit Text</button>
参数说明
字段集和说明
<?= $form->fieldset( legend: 'Legend', attributes: [], legendAttributes: [], ) ?> // <fieldset><legend>Legend</legend> <?= $form->fieldsetClose() ?> // </fieldset>
参数说明
数据列表
<?= $form->datalist( name: 'colors', items: ['red', 'blue'], attributes: [], ) ?> /* <datalist id="colors"> <option value="red"></option> <option value="blue"></option> </datalist> */
参数说明
使用每个方法
如果您有一个对象数组或只想对值有更多控制,您可以使用each方法。
$items = ['red' => 'Red', 'blue' => 'Blue']; <?= $form->datalist( name: 'colors', items: $form->each(items: $items, callback: function($item, $key): array { // value:string return [strtoupper($item)]; }) ) ?> /* <datalist id="colors"> <option value="RED"></option> <option value="BLUE"></option> </datalist> */
选项
<?= $form->option( value: 'red', text: 'Red', attributes: [], selected: ['red'], // or 'red' ) ?> // <option value="red" selected>Red</option>
参数说明
输入数据
输入数据用于重新填充表单元素的值。
创建输入
use Tobento\Service\Form\InputInterface; use Tobento\Service\Form\Input; $input = new Input(array_merge( $_GET ?? [], $_POST ?? [], )); var_dump($input instanceof InputInterface); // bool(true)
现在,如果存在指定元素的输入数据,表单元素的值将自动重新填充。
表单输入方法
您可以使用以下方法访问表单类上的输入数据。
getInput
use Tobento\Service\Form\Form; use Tobento\Service\Form\Input; $form = new Form( input: new Input(['color' => 'red']), ); $value = $form->getInput( name: 'color', default: 'blue', withInput: true, // default ); var_dump($value); // string(3) "red" $value = $form->getInput( name: 'color', default: 'blue', withInput: false, ); var_dump($value); // string(4) "blue"
hasInput
use Tobento\Service\Form\Form; use Tobento\Service\Form\Input; $form = new Form( input: new Input(['color' => 'red']), ); var_dump($form->hasInput('color')); // bool(true)
withInput
返回具有指定输入的新表单实例。
use Tobento\Service\Form\Form; use Tobento\Service\Form\Input; use Tobento\Service\Form\InputInterface; $form = new Form( input: new Input(['color' => 'red']), ); $form = $form->withInput( input: null, // null|InputInterface );
标记器
标记器用于生成和验证令牌,以保护您的应用程序免受跨站请求伪造攻击。
会话标记器
首先,请确保您已安装会话服务
composer require tobento/service-session
查看会话服务以了解更多信息。
use Tobento\Service\Form\TokenizerInterface; use Tobento\Service\Form\SessionTokenizer; use Tobento\Service\Session\SessionInterface; use Tobento\Service\Session\Session; $session = new Session(name: 'sess'); $tokenizer = new SessionTokenizer( session: $session, // SessionInterface tokenName: 'csrf', // default tokenInputName: '_token' // default ); var_dump($tokenizer instanceof TokenizerInterface); // bool(true)
标记器方法
setTokenName
$tokenizer->setTokenName('csrf');
getTokenName
var_dump($tokenizer->getTokenName()); // string(4) "csrf"
setTokenInputName
$tokenizer->setTokenInputName('_token');
getTokenInputName
var_dump($tokenizer->getTokenInputName()); // string(6) "_token"
get
返回指定名称的令牌。
var_dump($tokenizer->get('csrf')); // Null or string
generate
生成并返回指定名称的新令牌。
var_dump($tokenizer->generate('csrf')); // string(40) "token-string..."
delete
删除指定名称的令牌。
$tokenizer->delete('csrf');
verifyToken
$isValid = $tokenizer->verifyToken( inputToken: 'input token string', // string name: 'csrf', // null|string The name of the token to verify. ); // or set a token. $isValid = $tokenizer->verifyToken( inputToken: 'input token string', // string token: 'token string' // null|string );
标记器PSR-15中间件
您还可以使用VerifyCsrfToken::class中间件验证表单令牌。
如果令牌无效,将抛出InvalidTokenException异常。
use Tobento\Service\Form\Middleware\VerifyCsrfToken; use Tobento\Service\Form\InvalidTokenException; $middleware = new VerifyCsrfToken( tokenizer: $tokenizer, // TokenizerInterface name: 'csrf', // default inputName: '_token', // default headerTokenName: 'X-Csrf-Token', // default. Null if not to use at all. onetimeToken: false, // default );
您可能希望排除一组URI从CSRF保护
$request = $request->withAttribute( VerifyCsrfToken::EXCLUDE_URIS_KEY, [ 'http://example.com/foo/bar', ] );
表单标记器方法
标记器
use Tobento\Service\Form\Form; use Tobento\Service\Form\TokenizerInterface; $form = new Form( tokenizer: $tokenizer, ); var_dump($form->tokenizer() instanceof TokenizerInterface); // bool(true)
generateToken
use Tobento\Service\Form\Form; $form = new Form( tokenizer: $tokenizer, ); var_dump($form->generateToken()); // string(40) "token string..."
generateTokenInput
use Tobento\Service\Form\Form; $form = new Form( tokenizer: $tokenizer, ); echo $form->generateTokenInput(); // <input name="_token" type="hidden" value="token string...">
消息
消息用于在表单元素上显示任何类型的消息。
查看消息服务以了解更多相关信息。
use Tobento\Service\Message\MessagesInterface; use Tobento\Service\Message\Messages; $messages = new Messages(); var_dump($messages instanceof MessagesInterface); // bool(true)
表单消息方法
messages
use Tobento\Service\Form\Form; use Tobento\Service\Message\MessagesInterface; $form = new Form(); var_dump($form->messages() instanceof MessagesInterface); // bool(true)
withMessages
返回一个带有指定消息的新实例。
use Tobento\Service\Form\Form; use Tobento\Service\Message\MessagesInterface; $form = new Form(); $form = $form->withMessages( input: null, // null|MessagesInterface );
getMessage
返回指定键的消息。
use Tobento\Service\Form\Form; $form = new Form(); var_dump($form->getMessage('key')); // string(0) ""
getRenderedMessageKeys
返回已渲染的消息键。
use Tobento\Service\Form\Form; $form = new Form(); var_dump($form->getRenderedMessageKeys()); // array(0) { }
添加消息
如何为特定表单元素添加消息的示例。
use Tobento\Service\Form\Form; $form = new Form(); $form->messages()->add( level: 'error', message: 'Please accept our terms.', key: 'terms', ); <?= $form->input('terms', 'checkbox', 'terms') ?> // <span class="form-message error">Please accept our terms.</span> // <input name="terms" id="terms" type="checkbox">
您可以通过查看验证服务来验证表单并将验证器消息传递到表单。
CSRF保护
如果您在表单类中指定了分词器,表单方法将自动添加一个带有标记的隐藏输入元素。
<?= $form->form() ?> // <form method="POST"> // <input name="_token" type="hidden" value="generated-token-string">
方法欺骗
如果您将PUT、PATCH或DELETE设置为方法,将自动添加一个名为_method的隐藏输入元素以进行欺骗。
<?= $form->form(['method' => 'PUT']) ?> // <form method="POST"> // <input name="_method" type="hidden" value="PUT">
活动表单元素
getActiveElements
返回活动元素。
use Tobento\Service\Form\Form; use Tobento\Service\Form\ActiveElements; use Tobento\Service\Form\ActiveElementsInterface; $form = new Form( activeElements: new ActiveElements(), ); var_dump($form->getActiveElements() instanceof ActiveElementsInterface); // bool(true)
isActive
如果元素是活动的。
use Tobento\Service\Form\Form; $form = new Form(); $isActive = $form->isActive( name: 'colors', value: 'red', // the value to be active. default: null, );
表单辅助方法
nameToArray
如果名称包含表示法语法,则将指定的名称生成到数组字符串。
use Tobento\Service\Form\Form; $form = new Form(); var_dump($form->nameToArray('user.firstname')); // string(15) "user[firstname]"
nameToNotation
将指定的名称从数组字符串生成到基于表示法的名称。
use Tobento\Service\Form\Form; $form = new Form(); var_dump($form->nameToNotation('user[firstname]')); // string(14) "user.firstname"
nameToId
将指定的名称生成到一个有效的id。
use Tobento\Service\Form\Form; $form = new Form(); var_dump($form->nameToId('user[firstname]')); // string(14) "user_firstname"
hasArrayNotation
检查指定的名称是否包含表示法。
use Tobento\Service\Form\Form; $form = new Form(); var_dump($form->hasArrayNotation('user.firstname')); // bool(true)