andrewdanilov / yii2-feedback
反馈和回调表单
1.0.22
2023-07-06 12:37 UTC
Requires
- php: >=5.6.0
- andrewdanilov/yii2-fancybox: ~1.0.0
- yiisoft/yii2: ~2.0.0
README
组件,用于创建具有可自定义字段集、用户验证器、HTML 模板、文件上传和JavaScript 回调的反馈表单。
安装
安装此扩展的首选方式是通过 composer。
运行
composer require andrewdanilov/yii2-feedback "~1.0.0"
或将
"andrewdanilov/yii2-feedback": "~1.0.0"
添加到您的 composer.json 文件的 require 部分中。
用法
在 common/config/main_local.php 配置文件中设置邮件组件
return [ // ... 'components' => [ // ... 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', 'useFileTransport' => false, 'transport' => [ 'class' => 'Swift_SmtpTransport', 'username' => 'admin@example.com', 'password' => 'yourpassword', 'host' => 'smtp.example.com', 'port' => '465', 'encryption' => 'ssl', ], ], ], ];
在 frontend/config/main.php 中,向 controllerMap 部分添加以下行
return [ // ... 'controllerMap' => [ // ... 'callback' => [ 'class' => 'andrewdanilov\feedback\FeedbackController', // If you want you can use your own views for form and mail. // Just copy views files from `src/views` and `src/mail` folders // of extension to your location, for example, to `@frontend/views/feedback` // and `@frontend/mail/feedback` and set correspondent `formView`, // `mailView` and `mailLayout` paths here: 'formView' => '@frontend/views/feedback/default', // optional 'mailView' => '@frontend/mail/feedback/default', // optional 'mailLayout' => '@frontend/mail/feedback/layouts/html', // optional // label for extra field in mail template 'extraFieldLabel' => 'Extra data', // optional 'from' => ['admin@example.com' => 'My Site'], 'to' => ['admin@example.com', 'admin2@example.com'], 'subject' => 'Mail from site', // optional 'fields' => [ 'name' => [ 'required' => true, // optional 'label' => 'Name', // optional 'placeholder' => 'Enter your name', // optional 'type' => 'text', // optional, default 'text' 'maxlength' => 255, // optional 'class' => 'field-name', // optional 'style' => 'margin-bottom: 10px;', // optional 'errors' => [ // optional, default values is: 'required' => 'Field "{label}" is required.', // if requred field is empty 'maxlength' => 'Field "{label}" length of {maxlength} exeeded.', // if field length exeeded 'error' => 'Field "{label}" is incorrect.', // if validator returns false or empty error string ], ], 'address', // simple notation without config array 'email' => [ 'required' => true, 'label' => 'Email', 'placeholder' => 'Enter your e-mail', 'type' => 'email', 'class' => 'field-email', 'validator' => ['MyValidatorClass', 'myEmailValidator'], // optional, validator as an anonymous function, a function name as a string, or a valid PHP callable array ], 'country' => [ 'label' => 'Select country', 'type' => 'select', 'items' => [ 0 => 'Select your country', 1 => 'Great Britain', 2 => 'Germany', 3 => 'Norway', ], 'class' => 'field-country', ], 'phone' => [ 'label' => 'Phone', 'placeholder' => 'Enter your phone', 'type' => 'tel', 'class' => 'field-phone', ], 'comment' => [ 'label' => 'Comment', 'placeholder' => 'Enter your comment', 'type' => 'textarea', 'maxlength' => 1000, 'class' => 'field-comment', ], 'img' => [ 'label' => 'Upload Image', 'type' => 'file', 'multiple' => true, // optional, default is false 'maxFiles' => 10, // optional, default is 0, that equals no restriction 'extensions' => 'pdf, docx', // optional, default is empty string, that equals to any extension 'uploadDir' => '@webroot/upload/files', // optional, default is '@webroot/upload' 'class' => 'field-file', ], 'accept_agreement' => [ 'label' => 'Accept user agreement', 'type' => 'checkbox', 'default' => 1, 'class' => 'field-agreement', 'exclude' => true, // field will be excluded from mail ], ], ], ], ];
您可以添加任意数量的控制器映射。每个控制器映射代表一个反馈表单实例。
您可以使用自己的验证器来验证字段值。您只需定义字段定义中的 'validator' 属性(见上面的配置)。例如,您可以使用 PHP 可调用数组
// key is the field name
'my_email' => [
//...
'validator' => ['frontend\components\validators\MyValidatorClass', 'myEmailValidator'],
];
'my_phone' => [
//...
'validator' => ['frontend\components\validators\MyValidatorClass', 'myPhoneValidator'],
];
然后您需要在类 MyValidatorClass 中创建方法 myEmailValidator 和 myPhoneValidator
<?php namespace frontend\components\validators; class MyValidatorClass { // method accepts three parameters: first is validating field name, // second - its value, third - all form values in case if you need // to check some other fields to correctly validate current field public static function myEmailValidator($field_name, $field_value, $fields_values) { // check field only if it is filled if ($field_value && !filter_var($field_value, FILTER_VALIDATE_EMAIL)) { // if it is not ok, return an arror return [ 'error' => 'Email is incorrect', ]; // or you can just return boolean false: "return false;" } return true; // if all is ok - return boolean true } public static function myPhoneValidator($field_name, $field_value, $fields_values) { // check field only if it is filled if ($field_value && !preg_match('~^[\d\-\(\)\+ ]+$~', $field_value)) { // you can just return boolean false instead of an error array, // then default error message will be used return false; } return true; // if all is ok - return boolean true } }
如果您在 urlManager 中使用 "'enableStrictParsing' => true",则需要添加规则
return [ // ... 'urlManager' => [ // ... 'enableStrictParsing' => true, 'rules' => [ // ... '<controller>/send' => '<controller>/send', // this needs to be added to represent ajax handler '' => 'site/index', ], ], ];
您可以使用在 'controllerMap' 中定义的特定控制器 ID 代替 <controller>。
在视图中添加小部件调用
<?= \andrewdanilov\feedback\FeedbackWidget::widget([ // controller id configured in 'controllerMap' section of your config 'controller' => 'callback', // optional: widget ID 'id' => 'mywidgetID', // optional: instead of form displays button, which call floating form on click 'lightbox' => [ // optional: tag represents button triggering form appearance (div, span, i, a, etc.) // if not set or null, button will not be displayed, than you need to // create it manually, i.e.: // <a href="javascript:;" data-fancybox data-src="#feedback-mywidgetID" data-extra="extra message">Call me back!</a> // in that case you can pass extra data to your form, and each triggering button // can provide its own data to single form instance. 'button' => 'div', // optional: button name 'label' => 'Call me!', // optional: options for yii Html::tag() helper 'options' => ['class' => 'callback-btn'], // optional: delay before lightbox form will be closed 'delay' => 2500, // optional: close button template 'closeBtn' => '<a href="javascript:$("[data-fancybox-close]").click();$.fancybox.close(true);" class="close-btn">x</a>', // optional: lightbox window title 'title' => 'Call me back!', ], // optional: javascript code to execute after success submit happen 'jsCallback' => 'ga("send", "event", "my_form", "submit"); yaCounter100500.reachGoal("my_goal");', // optional: javascript code to execute after form send error happen 'jsErrorCallback' => 'alert("Error happened");', // optional: redirect visitor to page after submitting form 'redirect' => \yii\helpers\Url::to(['site/index']), // optional: success form submit message 'successMessage' => 'Message sent. Please, wait for an answer.', // optional: name and options for submit button 'submitButton' => [ 'name' => 'Send msg', // optional 'options' => ['class' => 'form-submit-button'], // optional ], // optional: class to be added to input element and its parent in case an error, default is 'has-errors' 'errorFieldClass' => 'error', // optional: scroll to first error field after form send if there is an error, default is true 'scrollToFirstError' => false, // optional: class of element containing error message, default is 'help-block' 'errorFieldAlertElementClass' => 'alert', // optional: form block options 'options' => [ 'class' => 'form-block-class', ], ]) ?>
对于错误处理和成功的提交,您可以在小部件调用中使用 jsErrorCallback 和 jsCallback 参数定义 JavaScript 回调函数。您还可以使用相应的定义的 JavaScript 事件。例如
$(function() { $(document).on('mywidgetID-form-submit', function() { alert('success'); }); $(document).on('mywidgetID-form-error', function() { alert('error'); }); });
简单示例
frontend/config/main.php 中的控制器映射
return [ // ... 'controllerMap' => [ // ... 'call_me' => [ 'class' => 'andrewdanilov\feedback\FeedbackController', 'formView' => '@frontend/views/feedback/default', 'from' => ['admin@example.com' => 'My Site'], 'to' => ['admin@example.com', 'admin2@example.com'], 'subject' => 'Mail from site', 'fields' => [ 'name', 'email', 'phone', 'message', 'img' => [ 'type' => 'file', 'multiple' => true, ], ], ], ], ];
小部件调用
<?= \andrewdanilov\feedback\FeedbackWidget::widget([ 'controller' => 'call_me', 'jsCallback' => '$(".call_me-success-message").show();', ]) ?>
表单视图 frontend/views/feedback/default.php
<?php /* @var $this yii\web\View */ /* @var $route string */ /* @var $options array */ /* @var $model \andrewdanilov\feedback\FeedbackForm */ /* @var $fields array */ /* @var $successMessage string */ /* @var $submitButton array */ ?> <form action="<?= $route ?>" id="<?= $options['id'] ?>"> <input type="hidden" name="<?= \Yii::$app->request->csrfParam ?>" value="<?= \Yii::$app->request->csrfToken ?>"> <!-- variables needs to be placed into an array "data" --> <input type="text" name="data[name]"> <p class="help-block"></p><!-- block for printing field error must be placed right after input element or right after its parent element --> <input type="text" name="data[email]"> <p class="help-block"></p> <input type="text" name="data[phone]"> <p class="help-block"></p> <textarea name="data[message]"></textarea> <!-- we can't place files variables into an array "data", so use direct variable name in attribute here --> <div class="my-file-uploader"> <!-- for multiple file selecting you need to add "multiple" attribute to input and [] to field name attribute --> <input type="file" name="img[]" multiple> </div> <p class="help-block"></p><!-- block for printing field error must be placed right after input element or right after its parent element --> <input type="submit" value="Send"> </form> <div class="call_me-success-message"> <div>Thank you!</div> </div>