欢迎各位兄弟 发布技术文章
这里的技术是共享的
学习使用 Drupal 8 的表单接口,在模块或主题里创建或修改表单。
代码仓库:https://github.com/ninghao/drupal-8-dev-module-demo
创建表单use Drupal\Core\Form\Formbase 应该是 use Drupal\Core\Form\FormBase,注意 FormBase 的 Base 的第一个字母是大写的。
在 Drupal 8 里面创建一个表单,可以为它创建一个类 .. 在这个表单类里面包含了表单的创建,提交,验证等等。 Drupal 8 提供了几种基本的类我们可以去继承一下。
找到我们自己创建的这个模块 .. 我这里就是 modules 下面的 ninghao_demo .. 在它的 src 目录的下面,创建一个新的目录,名字是 Form .. 然后在它下面再创建一个表单类 .. 这个文件的名字可以是 NinghaoDemoForm.php ..
添加一个 php 的开始标记 .. 再设置一下这个类的命名空间 .. 用一个 namespace .. 这里设置成 Drupal\ninghao_demo\Form; .. 在我们自己的表单类里面需要用到核心带的表单相关的类,我们可以先使用一下它,这样在用到它的时候可以使用使用类的名字 .. use Drupal\Core\Form\Formbase; 这个 Formbase 是一种基本的表单 .. 在我们的类里面可以去继承一下它 ..
然后再用一下 Drupal\Core\Form\FormStateInterface;
下面再去定义一个类 .. 名字是 NinghaoDemoForm .. 注意这个类的名字要跟它所在的这个 php 文件的名字一致 .. 让它继承一下 Formbase ..
在我们的类里面必须要包含几个方法 .. 一个是 getFormID .. 这个方法需要返回表单的 id .. 比如我们可以把这个表单的 id 设置成 ninghao_demo_form ..
然后再定义一个 buildForm 这个方法 .. 它里面的东西就是表单上面包含的一些元素 .. 这个方法有两个参数 .. 一个是 $form ,它是一个数组 .. 还有一个是 $form_state .. 它属于 FormStateInterface 这个类 ..
验证表单的功能可以放在 validateForm 这个方法里面 .. 添加一个这样的方法 .. 它也包含两个参数 .. 一个是用引用的方式传递进来的 $form .. 它是一个数组 .. 还有就是 $form_state .. 它属于 FormStateInterface ..
最后再添加一个处理表单提交的方法 .. 名字是 submitForm .. 同样包含用引用方式传递的 $form,还有 $form_state 这个参数 ..
现在我们就定义好了一个基本的表单类 .. 下面我们再去给它添加几个表单元素 ...
现在我们已经定义了一个表单类,下面我们在这个表单里去添加两个表单元素。Drupal 支持很多种表单元素,你可以在 api.drupal.org 里面查看 Drupal 支持的所有的元素 ..
表单上的元素可以放在 buildForm 这个方法里面 ..
比如我现在要在表单里添加一个简单的文件框,可以把这个元素放在 $form 里面, 先给这个元素起个名字,比如 name .. 它的值是一个数组 .. 这个数组里的项目就是去描述一下这个表单元素,比如它的类型,标签等等 .. 先添加一个 #type 属性 .. 它的值是这个元素的类型 .. 文本框就是 textfield ..
再用一个 #title ,设置一下元素的标签 .. 这里我们可以使用一个可被翻译的字符 .. 使用 $this 的 t 这个方法 .. 它里面就是标签上的文字 .. 这个文字可以被翻译成多个语言的版本 ..
下面我们再去添加一个提交表单用的按钮 .. 名字可以是 submit .. 在它里面用一个 #type .. 这个元素的类型是 submit,意思就是这是一个提交表单用的东西 ..
然后再用一个 #value .. 设置一下按钮上的文字 .. 这里设置成 保存 ..
完成以后再返回这个 $form;
现在我们的表单里面就有了两个元素,一个是 name ,类型是一个文本框 .. 还有一个 submit ,类型是一个提交表单用的按钮 ..
下面我们去给创建好的这个表单添加一个路由,让用户可以访问到这个表单 .. 在我们自己定义的这个模块的根目录下面,有一个 ninghao_demo.routing.yml ,这个文件就是模块的路由,没有的话可以自己创建一个这样的文件 .. 先是模块的名字,后面加上 .routing.yml ..
在它里面添加一个新的路由 .. 名字可以是 ninghao_demo.form: 另起一行 .. 设置一下 path 的值 .. 也就是这个路由的地址 .. 这里设置成 /ninghao-demo-form
下面再用一个 defaults: .. 在它的下面再添加两个选项 .. 一个是 _title ,设置一下页面的标题 .. 表单的演示 .. 再用一个 _form .. 它可以告诉这个路由怎么样显示这个页面 .. _form .. 的意思就是这里需要使用一个表单类 ... 我们的这个表单类是在 \Drupal\ninghao_demo\Form\NinghaoDemoForm .. (类的名字)
然后是 requirements: .. 它的下面用一个 _access .. 把它的值设置成 TRUE .. 意思就是这个路由在任何情况下用户都有权限可以访问到 ...
保存一下这个文件 .. 再去重建一下 Drupal 的缓存 ...
回到 Drupal 的前台页面 .. 打开我们定义好的这个 ninghao-demo-form .. 在这个页面上你可以看到我们创建的这个表单 .. 上面有两个元素 .. 一个是这个文本框 .. 还有一个提交表单用的按钮 ...
提交表单的时候我们有方法可以检查表单里面的元素的数据,看看是不是符合我们的要求,如果不符合的话,我们可以提示用户哪里需要修改一下。表单提交以后,Drupal 会执行表单类里面的 validateForm 这个方法,在它里面可以去检查表单里的数据。
在这个方法里面,我们可以添加点代码去检查一下这个表单里的 name 元素 .. 先看一下这个元素里面是不是有数据,如果有就去检查它里面的数据 .. FormStateInterface 里面有一个 isValueEmpty 方法,可以使用它来检查元素里的值是不是空白的 ...
用一个 if .. 使用 $form_state 的 isValueEmpty 方法,检查一下 name 这个元素 .. 如果它里面的值是空白的,这个方法就会返回 true .. 前面加上一个 ! ,表示如果不是空白的,就执行 if 里面的代码 ..
在它里面,我们可以去判断一下 name 这个元素的值的长度,我要求它的长度必须大于 2 .. 同样使用一个 if 判断一下 .. 得到表单元素里的值可以这样 .. 使用 $form_state 里的 getValue 这个方法,要得到的是 name 这个表单元素的值 .. 然后我们用一个 Unicode::strlen 这个方法 . 它可以返回字符串的长度 .. 判断一下这个长度是不是
这个错误信息可以使用 $form_state 的 setErrorByName 方法 .. 出错的元素是 name .. 把它作为这个方法的第一个参数,第二个参数是显示的错误信息 .. 用一个 t 函数 .. 姓名 必须使用两个或以上的字符 ..
这里我们用到了 Drupal 的 Unicode 这个类 .. 在上面我们再使用一下它 .. use .. 它的位置是 Drupal\Component\Utility\Unicode;
保存 ... 回到前台去试一下 .. 在这个表单页面 .. 直接点击 保存 .. 没有反应 .. 再 输入一个字的姓名 .. 然后保存 .. 提示表单里的姓名这个字段出现了一个错误 ...
再输入两个字儿的姓名 .. 保存 ... 这次表单里的元素符合我们的要求,所以没有提示错误 ...
用户提交表单以后,Drupal 会使用表单在里面的 submitForm 这个方法去处理提交 .. 比如把表单里的数据放到数据库里,或者发送个邮件之类的 ... 得到表单元素里的值可以使用 $form_state 的 getValue 这个方法,把元素的名字告诉这个方法就可以了 ..
下面我们可以简单的在用户提交表单以后,把表单元素的数据输出到页面上显示出来 ..
找到这个 submitForm 方法 ... 在页面上显示信息可以使用 drupal_set_message .. 要显示的信息把它放在 $this 的 t 方法里面 .. 您的姓名是: 用一个 @name 来表示 .. 在第二个参数里面可以设置一下这个 name 的值 .. 它是一个数组 .. 里面添加一个 @name .. 它的值可以使用 $form_state 的 getValue 方法得到 .. 也就是表单里的 name 这个元素的值 ...
保存一下 ... 回到这个表单的页面 .. 在这个文本框里输入一个姓名 ... 然后点击保存提交一下这个表单 .. 在页面上会显示一条信息 .. 这个信息里面会包含用户在表单里填写的内容 ...
Drupal 给我们提供了两个钩子函数可以让我们去修改表单,用的就是 hook_form_alter ,还有一个是 hook_form_FORM_ID_alter .. 它们可以修改核心自带的或者其它的模块里面创建的表单 .. 要修改表单我们需要先知道这个表单的 id 号 .. 比如我要修改一下页面上的这个搜索框 ..
检查一下这个表单 .. 在 form 标签上的 id 这个属性里面的值就是这个表单的 id 号 .. 这里就是 search block form ..
另外我们也可以查看 Drupal 的源代码 .. 比如我知道这个区块是核心的 serach 模块提供的 .. 找开 core .. modules .. 找到 search 这个模块 .. 打开它的 src .. 这里的 Form 目录就是模块创建的一些表单 ... 在这里有一个 SearchBlookForm.php .. 它里面定义的就是我们刚才看到的那个搜索表单 ..
找到它的 getFormID 这个方法 .. 这里返回的就是表单的 id 号 .. 在修改表单的时候我们需要用到这个 id 来定位到这个表单 ..
这个表单里的元素,可以在 buildForm 这个方法里找到 .. 比如这个 keys .. 就是我们刚才在页面上看到的那个搜索表单里的那个文本框 .. 你可以看到,它的类型是 search .. 上面还有一些其它的属性 ..
你可以直接修改这个地方的源代码,不过在升级 Drupal 以后,我们做的修改就不见了 .. 所以正确的做法就是使用 hook ..
在我们自己定义的模块或者主题里面,可以使用 Drupal 提供的 hook .. 找到我们自己创建的这个模块 .. 在它的根目录下面创建一个新的文件 .. 文件的名字先用一下模块的名字 .. 后缀使用一个 .module .. 在这个文件里面我们就可以去实施一下想要用的 hook ..
我现在已经知道了自己想要修改的表单的名字,还有要修改的元素的名字 .. 下面我们可以使用一下 hook_form_FORM_ID_alter .. 使用这个 hook 可以这样 .. 把这个函数里面的 hook 替换成模块或主题的名字,中间的 FORM_ID 替换成要修改的表单的 ID 号 ..
在这个 module 文件里面,先添加一个 php 的开始标记 ..
然后去定义一个函数 .. 名字先用模块的名字或者主题的名字开头 .. 我这里就是 ninghao_demo ..
这个名字就代替了 hook 函数里面的那个 hook .. 然后是一个 form .. 接着是表单的 id 号,我要修改的表单的 id 是 search_block_form .. 后面再加上一个 alter ..
它有几个参数 .. 一个是用引用方式传递进来的 $form .. 还有一个是 $form_state .. 它是在 \Drupal\Core\Form\FormStateInterface ..
在这个函数里面我们可以修改一下 search_block_form 这个表单里的 keys 这个元素 .. 我想在它的上面添加一个 placeholder 属性 ... 可以这样 ..
$form['keys'] .. 要往这个数组里添加的属性是 #placeholder .. 属性的值是 t('搜索') ..
保存一下 ... 然后再去重建一下 Drupal 的缓存 ...
回到前台的页面 .. 注意这个搜索框的变化 .. 刷新一下 .. 现在你会看到它里面有了一个占位符的文字 .. 这是因为我们修改了这个表单,在它的搜索框元素上添加了一个 placeholder 属性 ...
它支持几个参数,一个是用引用方式传递进来的 $form .. 还有一个是 $form_state .. 它属于 \Drupal\Core\Form\FormStateInterface ..
还有一个参数是 $form_id .. 然后在这个函数里面,我们需要判断一下,可以判断一下表单的 id ,看看是不是我们需要修改的那个表单 .. 用一个 if .. 判断的条件就是看一下 $form_id 是不是等于 search_block_form .. 如果是,就是修改一下它里面的 keys 这个元素 ..
$form['keys'] .. 给它添加一个 #placeholder 属性 .. 它的值是 t('搜索') ... 保存一下文件 .. 再去重建一下 Drupal 的缓存 ...
回到前台页面 .. 刷新一下 .. 在这个文本框的上面同样会包含我们给它添加的 placeholder 这个属性 ...
来自 https://ninghao.net/course/3708