更新时间:2023-12-03 22:36:04
Form
实施Controller
实现(实际上,这里不需要进行任何更改,但是为了完整性……)View
实施Form
implementationController
implementation (actually no changes needed here, but for completeness...)View
implementation验证器是其中最关键的部分,所有其他内容都很直观...
The validator is the most crucial part of this, all other things are rather intuitive ...
use \Phalcon\Validation\Validator;
use \Phalcon\Validation\ValidatorInterface;
use \Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
if (!$this->isValid($validation)) {
$message = $this->getOption('message');
if ($message) { // Add the custom message defined in the "Form" class
$validation->appendMessage(new Message($message, $attribute, 'Recaptcha'));
}
return false;
}
return true;
}
/********************************************
* isValid - Return Values
* =======================
* true .... Ok
* false ... Not Ok
* null .... Error
*/
public function isValid($validation)
{
try {
$config = $validation->config->recaptcha; // not needed if you don't use a config
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
$url = $config->verifyUrl; // or 'https://www.google.com/recaptcha/api/siteverify'; without config
$data = ['secret' => $config->secretKey, // or your secret key directly without using the config
'response' => $value,
'remoteip' => $ip,
];
// Prepare POST request
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
],
];
// Make POST request and evaluate the response
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result)->success;
}
catch (Exception $e) {
return null;
}
}
}
class SignupForm extends Form
{
public function initialize($entity = null, $options = null)
{
// Name (just as an example of other form fields)
$name = new Text('name');
$name->setLabel('Username');
$name->addValidators(array(
new PresenceOf(array(
'message' => 'Please enter your name'
))
));
$this->add($name);
// Google Recaptcha v2
$recaptcha = new Check('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'Please confirm that you are human'
]));
$this->add($recaptcha);
// Other form fields...
}
尽管控制器与其他所有表单都相同,但出于完整性考虑,这里还是一个示例...
Even though the controller is the same as with every other form, for completeness sake here an example...
class SessionController extends \Phalcon\Mvc\Controller
{
public function signupAction()
{
$form = new SignupForm();
if ($this->request->isPost()) {
if ($form->isValid($this->request->getPost()) != false)
{
// Add user to database, do other checks, etc.
// ...
}
}
$this->view->form = $form;
}
}
对于视图,您可以将html放在其中,也可以让引擎呈现它.如果要渲染它(例如,使用{{ form.render('recaptcha') }}
),则还必须创建一个Recaptcha
元素,而不是使用默认值之一(有关此信息,请参见本答案的最后一点).
For the view you can either just put the html there or let it be rendered by the engine. If you want it rendered instead (with e.g. {{ form.render('recaptcha') }}
), you will have to also create an Recaptcha
Element instead of using one of the defaults (see last point in this answer for that).
...
{{ form('class':'signupForm') }}
<fieldset>
<div>{{ form.label('name') }}</div>
{{ form.render('name') }}
{{ form.messages('name') }}
<!-- other elements here -->
<!-- ... -->
<div class="g-recaptcha" data-sitekey="{{ this.config.recaptcha.publicKey }}"></div>
{{ form.messages('recaptcha') }}
如果您不想为公共密钥使用配置(下一部分),只需将data-sitekey的值设置为您的个人(Google reCaptcha)公共密钥.
If you don't wanna use a config for your public key (next section), just set the value of the data-sitekey to your personal (Google reCaptcha) public key.
也不要忘记将脚本(<script src='https://www.google.com/recaptcha/api.js'></script>
)包含在某个位置(例如,在html头部分中).
Also don't forget to include the script (<script src='https://www.google.com/recaptcha/api.js'></script>
) somewhere (e.g. in your html head section).
如果您想使用配置来存储您的Recaptcha密钥,请将以下内容添加到您的config/config.php
...
If you wanna use the config to store your recaptcha keys, also add the following to your config/config.php
...
// config/config.php
return new \Phalcon\Config([
'application' => [
'controllersDir' => __DIR__ . '/../../app/controllers/',
'modelsDir' => __DIR__ . '/../../app/models/',
'formsDir' => __DIR__ . '/../../app/forms/',
'viewsDir' => __DIR__ . '/../../app/views/',
'pluginsDir' => __DIR__ . '/../../app/plugins/',
'libraryDir' => __DIR__ . '/../../app/library/',
'cacheDir' => __DIR__ . '/../../app/cache/',
'baseUri' => '/',
],
// other configs here
// ...
'recaptcha' => [
'publicKey' => 'your public key',
'secretKey' => 'your private key',
'verifyUrl' => 'https://www.google.com/recaptcha/api/siteverify',
],
]);
要能够在您的视图中访问配置,您可能还需要将$di->set('config', $config);
添加到依赖项注入器中(通常在config/services.php
中).
To be able to access the config in your view, you might also need to add $di->set('config', $config);
to your dependency injector (typically within config/services.php
).
如果您希望为您呈现自己的Recaptcha(而不是直接将div
放在视图中),则需要单独的\Phalcon\Forms\Element\
...
If you want your recaptcha to be rendered for you (instead of you putting the div
directly in the view), you will need a separate \Phalcon\Forms\Element\
...
class Recaptcha extends \Phalcon\Forms\Element
{
public function render($attributes = null) {
return '<div class="g-recaptcha" data-sitekey="'
.$this->config->recaptcha->publicKey
.'"></div>';
}
}
您还必须相应地更改Form
:
// ...
$recaptcha = new Recaptcha('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
'message' => '...'
]));
// ...
最后还有您的View
:
{{ form.render('recaptcha') }}