Form 类

Form 类是一个注解类,一般情况下 我们不要直接使用 new Form() 去创建一个表单,如果用new Form() 去创建表单类不会初始化任何东西。
我们需要使用的是 Form::create()  去创建表单。


静态方法:

Form::create(object|string $object, string $type = '', string $tabIndex = ''): ?static


$object 是一个被 #[Form()]  修饰过的Model 对象,或者 该对象的类名。
$type 是表单类型,一般为  add 或者 edit  也可以是其他的比如 search  delete 等等。对于 add 和 edit 有相应的逻辑约束,其他则无逻辑约束。
如果当表单类型为 edit 时,如果字段中有属性是 offEdit 为真的时候,将不会对该字段进行赋值,和修改。
而如果 表单类型为 add 是,如果字段null 将使用默认值。
$tabIndex 对于的表单标签归组,如果表单使用标签的情况下。

要创建表单我们需要先有一个model

/app/home/model/UserModel.php

namespace app\home\model;

use beacon\core\Form;
use beacon\widget\Password;
use beacon\widget\Text;

#注意 这里需要使用表单注解
#[Form(title: '用户表单', table: '@pf_user', template: 'user.form.tpl')]
class UserModel
{
    #[Text(label: '用户名')]
    public string $username = '';
    #[Password(label: '用户密码')]
    public string $password = '';
}


因为我们的model 表单注解种使用到了  user.form.tpl 文件 ,所以我们也创建一个简单的视图

/app/home/view/user.form.tpl

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>{$form->title}</title>
</head>
<body>
<div>
    <form method="post">
        <div>
            表单标题:{$form->title}
        </div>
        {foreach from=$form->getFields() item=field}
            <div id="{$field->boxId}-row">
                <div>{$field->label}:</div>
                <div>{input field=$field}</div>
            </div>
        {/foreach}
        <div style="margin-top: 10px"><input type="submit" value="提交"></div>
    </form>
</div>
</html>


接着我在控制器中创建表单并显示表单

namespace app\home\controller;


use app\home\model\UserModel;
use beacon\core\Controller;
use beacon\core\Form;
use beacon\core\Method;

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');
        $this->displayForm($form);
    }
}


也可以直接使用 类名类创建

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $this->displayForm($form);
    }
}


表单创建就可以显示了。


我们在创建一个用于接收数据的 操作

namespace app\home\controller;


use app\home\model\UserModel;
use beacon\core\Controller;
use beacon\core\Form;
use beacon\core\Method;

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $this->displayForm($form);
    }

    #[Method(act: 'index', method: Method::POST)]
    public function login()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');
        //也可以使用下面的创建,如果你不需要关系 $user 这个模型的情况下。
        //$form = Form::create(UserModel::class, 'add');
        $input = $this->completeForm($form);
        print_r($input); #input 可以用用于插入或者更新数据库。
        print_r($user);
    }
}


填写表单提交后显示数据如下:

Array
(
    [username] => wj008
    [password] => e10adc3949ba59abbe56e057f20f883e
)
app\home\model\UserModel Object
(
    [username] => wj008
    [password] => 123456
)



getType(): string

获取表单类型
返回创建时填写的类型

    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        #debug 输出表单类型。
        Logger::log($form->getType());
        $this->displayForm($form);
    }
#运行debug.php 页面 将打印出 add



比如在上例子模板中代码

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>{$form->title}</title>
</head>
<body>
<div>
    <form method="post">
        <div>
            表单标题:{if $form->getType()=='add'}添加{elseif $form->getType()=='edit'}编辑{/if}{$form->title}
        </div>
        {foreach from=$form->getFields() item=field}
            <div id="{$field->boxId}-row">
                <div>{$field->label}:</div>
                <div>{input field=$field}</div>
            </div>
        {/foreach}
        <div style="margin-top: 10px"><input type="submit" value="提交"></div>
    </form>
</div>
</html>

 

isEdit(): bool

表单类型是否是 edit 类型。

isAdd(): bool

表单类型是否是 add 类型。

 

getField(string $name): ?Field

获取某个字段,可以用于更改相应的属性。

    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $nameField = $form->getField('username');
        $nameField->setAttr('style', 'width:300px');
        $nameField->label = '账号';

        $passField = $form->getField('password');
        $passField->setAttr('style', 'background:#cef3e2;');
        $passField->label = '口令';

        $this->displayForm($form);
    }

 

getFields(string $tabIndex = ''): array

 

获取所有字段

$tabIndex 所在的标签分组。

为了演示标签分组 我们先把 UserModel 改成如下:

namespace app\home\model;

use beacon\core\Form;
use beacon\widget\Password;
use beacon\widget\Text;
use beacon\widget\Textarea;

#注意 这里需要使用表单注解
#[Form(title: '用户表单', table: '@pf_user', template: 'user.form.tpl')]
class UserModel
{
    #[Text(label: '用户名', tabIndex: 'base')]
    public string $username = '';
    #[Password(label: '用户密码', tabIndex: 'base')]
    public string $password = '';

    #[Textarea(label: '介绍', tabIndex: 'other')]
    public string $intro = '';
}

 

在控制器中获取所有字段:

 #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        #获取所有字段
        $fields = $form->getFields();
        foreach ($fields as $field) {
            Logger::log($field->name, $field->label);
        }
        $this->displayForm($form);
    }

debug.php 输出的内容如下:

username    用户名
password    用户密码
intro    介绍

现在我们需要获取不同标签分组的字段:

#[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        #获取所有字段
        $fields = $form->getFields('base');
        Logger::log('===标签分组 base===');
        foreach ($fields as $field) {
            Logger::log($field->name, $field->label);
        }
        #获取所有字段
        $fields = $form->getFields('other');
        Logger::log('===标签分组 other===');
        foreach ($fields as $field) {
            Logger::log($field->name, $field->label);
        }
        $this->displayForm($form);
    }

输出如下:

===标签分组 base===
username    用户名
password    用户密码
===标签分组 other===
intro    介绍

 

getFirstError(): string

获取第一条验证错误信息。
在我们表单自动完成提交后,如果有错误信息,我们可以使用 getFirstError() 获取第一条错误信息。

为了演示效果 ,我们先把UserModel 添加验证

namespace app\home\model;

use beacon\core\Form;
use beacon\widget\Password;
use beacon\widget\Text;
use beacon\widget\Textarea;

#注意 这里需要使用表单注解
#[Form(title: '用户表单', table: '@pf_user', template: 'user.form.tpl')]
class UserModel
{
    #[Text(
        label: '用户名',
        tabIndex: 'base',
        validRule: ['r' => '请输入用户名']
    )]
    public string $username = '';
    #[Password(
        label: '用户密码',
        tabIndex: 'base',
        validRule: ['r' => '请输入用户密码', 'minLen' => [6, '用户密码长度至少是6位以上']]
    )]
    public string $password = '';

    #[Textarea(
        label: '介绍',
        tabIndex: 'other',
        validRule: ['r' => '请输入介绍信息']
    )]
    public string $intro = '';
}


控制器代码如下:

namespace app\home\controller;


use app\home\model\UserModel;
use beacon\core\Controller;
use beacon\core\Form;
use beacon\core\Logger;
use beacon\core\Method;

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $this->displayForm($form);
    }

    #[Method(act: 'index', method: Method::POST)]
    public function login()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');

        //完成表单
        $input = $form->autoComplete();
        //验证表单
        $form->validate();
        //获取第一个错误
        $firstError = $form->getFirstError();
        if (!empty($firstError)) {
            Logger::log($firstError);
            $this->error($firstError);
        }
        print_r($input); #input 可以用用于插入或者更新数据库。
        print_r($user);
    }
}

debug.php 如果什么都没填写就提交 将打印出

请输入用户名

如果我填写了用户名 ,提交则会打印  请输入用户密码,以此类推。打印第一个报错的信息。

getErrors(): array

获取所有验证错误信息。
同上例子

#[Method(act: 'index', method: Method::POST)]
    public function login()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');

        //完成表单
        $input = $form->autoComplete();
        //验证表单
        $form->validate();
        //获取所有错误
        $error = $form->getErrors();
        if (!empty($error)) {
            Logger::log($error);
            $this->error($error);
        }
        print_r($input); #input 可以用用于插入或者更新数据库。
        print_r($user);
    }

 

如果什么都没有填写,就提交 则 debug.php 打印

{
    "username": "请输入用户名",
    "password": "请输入用户密码",
    "intro": "请输入介绍信息"
}



clearErrors()

清除所有错误信息,如果有一些数据验证错误了,在某些情况下我们可以相应的清理错误。

 

setHideBox(string $name, mixed $value)

添加一个隐藏域 ,需要再模板中 使用 fetchHideBox() 输出。

修改模板:

/app/home/view/user.form.tpl

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>{$form->title}</title>
</head>
<body>
<div>
    <form method="post">
        <div>
            表单标题:{if $form->getType()=='add'}添加{elseif $form->getType()=='edit'}编辑{/if}{$form->title}
        </div>
        {foreach from=$form->getFields() item=field}
            <div id="{$field->boxId}-row">
                <div>{$field->label}:</div>
                <div>{input field=$field}</div>
            </div>
        {/foreach}
        <div style="margin-top: 10px">
            
            {$form->fetchHideBox()|raw}
{*输出隐藏域,raw 修饰器是使用html 源码输出,不进行文本处理*}
            <input type="submit" value="提交">
        </div>
    </form>
</div>
</html>


控制器代码:

namespace app\home\controller;


use app\home\model\UserModel;
use beacon\core\Controller;
use beacon\core\Form;
use beacon\core\Logger;
use beacon\core\Method;

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $form->setHideBox('pid', 30);
        $this->displayForm($form);
    }

    #[Method(act: 'index', method: Method::POST)]
    public function login()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');
        $pid = $this->post('pid:i', 0);
        //打印来自隐藏提交的pid值。
        Logger::log('pid:', $pid);
        //完成表单
        $input = $this->completeForm($form);
        Logger::log($input); #input 可以用用于插入或者更新数据库。
        Logger::log($user);
    }
}


提交数据后打印结果:

pid:    30

{
    "username": "wj008",
    "password": "e10adc3949ba59abbe56e057f20f883e",
    "intro": "我是一个程序员"
}

{
    "___class_name": "app\\home\\model\\UserModel",
    "username": "wj008",
    "password": "123456",
    "intro": "我是一个程序员"
}

 

fetchHideBox(string $tabIndex = ''): string

输出隐藏域的代码
一般配合 setHideBox() 方法使用,如果字段中被设置 hidden 属性为 true 也会被加入到隐藏字段中。
需要在模板中调用输出。

 

getData(bool $anew = false): array

获取值,以数组形式返回,一般获取的值可以用于插入或者更新数据表的值。
默认情况下  控制器 调用 $this->completeForm($form); 会自动调用该方法获取值并返回。
但是在一些情况下我们修改了关联的model 我们可以使用该方法重新获取。
$anew 如果为 true 则重新获取,如果为false 将返回上次获取的值。
接上面示例:

class User extends Controller
{
    #[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        $form->setHideBox('pid', 30);
        $this->displayForm($form);
    }

    #[Method(act: 'index', method: Method::POST)]
    public function login()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');
        //完成表单
        $input = $this->completeForm($form);
        Logger::log('第一次获取', $input); #input 可以用用于插入或者更新数据库。
        $user->password = '654321';
        $input = $form->getData(true);
        Logger::log('UserModel 修改后重新获取', $input); #第二次才重新获取
        Logger::log($user);
    }
}


debug.php 打印结果:

第一次获取    {
    "username": "wj008",
    "password": "e10adc3949ba59abbe56e057f20f883e",
    "intro": "我是一个程序员"
}

UserModel 修改后重新获取    {
    "username": "wj008",
    "password": "c33367701511b4f6020ec61ded352059",
    "intro": "我是一个程序员"
}

{
    "___class_name": "app\\home\\model\\UserModel",
    "username": "wj008",
    "password": "654321",
    "intro": "我是一个程序员"
}

 

setData(array|int|null $data = null)

给表单赋值

$data  以数组的形式给表单赋值。

如果是 int 类型 ,将从 Model 注解Form 的 table 表中 取id= $data 的一行数据用于赋值。

#[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'add');
        #由于 UserModel 的#[Form(table:'@pf_user')] 的表示 @pf_user 所以将去 @pf_user 表中 id=1 的一行记录作为赋值
        $form->setData(1);
        $this->displayForm($form);
    }

使用数组赋值:

#[Method(act: 'index', method: Method::GET)]
    public function index()
    {
        $form = Form::create(UserModel::class, 'edit');
        $form->setData([
            'username' => 'wj008',
             #注意 因为 password 字段在 UserModel 中定义的是 Password 插件,插件中设置不会显示密码信息。
            'password' => 'e10adc3949ba59abbe56e057f20f883e',
            'intro' => '我是一个屌丝程序员',
        ]);
        $this->displayForm($form);
    }

页面效果如下:


clearData()


清空已经获得的数据,在某些情况下需要清空。


autoComplete(string $method = 'post'): array

 

自动完成表单填入,默认是从 post 提交中填入数值。
$method 从 提交方法类型中填入数值。
可以支持  post  get  param(即$_REQUEST)

返回值是一个数组,内部调用了 getData() 获取数据。


fillComplete(array $data)

根据自己提供的数组来完成表单,该函数不会主动调用 getData() 自己需要获取值这需要调用 getData() 获取;
在某些情况下 可能我们的表单 并不是从 $_GET  $_POST $_REQUEST  来的,可能是一个json数据。
所以需要我们先解析json 然后再完成表单。

#[Method(act: 'index', method: Method::POST)]
    public function login()
    {
        $user = new UserModel();
        $form = Form::create($user, 'add');
        //假设code是来自某个请求提交过来的数据
        $code = '{"username":"wj009","password":"123456","intro":"我是一个屌丝程序员"}';
        $data = json_decode($code, true);
        //完成表单
        $form->fillComplete($data);
        if (!$form->validate($error)) {
            $this->error($error);
        }
        $input = $form->getData();
        Logger::log($input); #input 可以用用于插入或者更新数据库。
    }

debug.php 输出结果:

{
    "username": "wj009",
    "password": "e10adc3949ba59abbe56e057f20f883e",
    "intro": "我是一个屌丝程序员"
}

 

validate(?array &$errors = []): bool

表单验证
如果表单中的字段设置了验证规则,则调用该方法可以处理验证信息。
如果全部验证通过 ,返回  true, 如果存在验证不通过的 返回 false ,并将验证错误的字段提示填入 $errors 数组。


getViewFields(string $tabIndex = ''): array

获取视图字段 受字段  viewMergeviewClose 限制。 如果是 viewClose 为 ture 则不加入到列表中
该方法 与 getFields()  不同在于,如果字段有向上或者向下合并后,该列表 返回结构是一个树状结构 可以使用 字段的 next 或者  prev 查看在在同一行中的 前面还是后面的字段。

假设 Model 有 6 个字段

username
password
sex
age  其中这个字段 的 viewMerge -1 即向上合并

intro 
allow  其中 viewClose = true

那么 getViewFields 展开是

|- username
|- password
|- sex   ->next = age
|- intro 

其中 age 放在了 sex 的 next 属性上。 而 allow 则不被加入。

如果是 getFields 则全部展示 包括  allow


Form表单的属性

public string $title = '';

表单标题
在Model 中使用 #[Form(title:'表单标题')  定义

public string $table = ''

当前相关的表名,在Model 中使用 #[Form(table:'数据库表名')  定义

string $template = '';

表单使用的默认模板
在Model 中使用 #[Form(template:'模板文件')  定义

 

 

配合 YeeUI 来使用表单布局
模板可调整为:

<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>{$form->title}</title>
    <link type="text/css" rel="stylesheet" href="/yeeui/css/yeeui.css"/>
    <link type="text/css" rel="stylesheet" href="/icofont/icofont.css"/>
    <script src="/yeeui/third/jquery-3.3.1.min.js"></script>
    <script src="/yeeui/yee.js"></script>
</head>
<body>
<div style="margin: 20px">
    <form method="post">
        <div class="yee-panel">
            <div class="panel-caption">
                {if $form->getType()=='add'}添加{elseif $form->getType()=='edit'}编辑{/if}{$form->title}
            </div>
            <div class="panel-content">
                {foreach from=$form->getViewFields() item=field}
                    {field_row field=$field}
                {/foreach}
            </div>
            <div class="yee-submit">
                <label class="submit-label"></label>
                <div class="submit-cell">
                    {*输出隐藏域*}
                    {$form->fetchHideBox()|raw}
                    <input type="submit" class="form-btn red" value="提交">
                </div>
            </div>
        </div>
    </form>
</div>
</html>
上一篇:Logger 类
下一篇:Field 类
Copyright © 2021 海南的叶子 All Rights Reserved 琼ICP备2021000725号

琼公网安备 46900702000037号