Data being saved to the database before save to table call made

The problem with the following code is that it saves the data to the users table before the condition if($usersTable->save($user) && $responseData->success ) is met and therefore prints out ‘Either the passwords don't match or the email address is already in use’ but when I put the condition in front of all the $this->request->getData() code, null values are saved to the database. I see that $user is saving status and verified fields to the database but when I comment them out, all of the data still gets saved to the database.

$usersTable = $this->fetchTable('Users');
$user = $usersTable->newEmptyEntity();
$fullname = $this->request->getData('contributor');
$email = $this->request->getData('email');
$password = $this->request->getData('password');
$password_confirm = $this->request->getData('password_confirm');
$token = Security::hash(Security::randomBytes(32));
$user->status = '0';
$user->verified = '0';
//responseData is for server side recaptcha verification
if($usersTable->save($user) && $responseData->success ) {
//here is some code that sends an email
$this->Flash->success(__('A verification link has been sent to your email account.'));
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
} else {
$this->Flash->error(__('Either the passwords don\'t match or the email address is already in use'));
}

your example is not complete because we have no idea where your $responseData is comming from.

My guess would be, that you need

if($responseData->success && $usersTable->save($user)) {

instead of

if($usersTable->save($user) && $responseData->success ) {

because $usersTable->save($user) actually does the saving, no matter if $responseData->success is true or not.

If statements are always executed from left to right, one by one.

I have a hidden input in my form that’s not getting a value.


<?= $this->Form->hidden('g-recaptcha-response', ['id'=>'g-recaptcha-response']);?>

When I debug my POST request:
if($this->request->is(‘post’)){
debug($this->request);
die();
It returns:

protected data => [
'email' => 'cp@example.com', 'contributor' => 'Kathleen', 'password' => 'red', 'password_confirm' => 'red', 'g-recaptcha-response' => '',
]

as you can see the ‘g-recaptcha-response’ at the end of the data call is empty.

data-callback callback Optional. The name of your callback function, executed when the user submits a successful response. The g-recaptcha-response token is passed to your callback.
My data-callback is enableBtn as you can see here:

<?php echo "<div class='g-recaptcha' data-sitekey='" . $recaptcha_user . "' data-callback='enableBtn'></div>"; ?>
<?php echo $this->Form->submit(__('Register'),['value' => 'submit',  'disabled'=> 'disabled', 'id'=>'button1']);  ?>
<script>
 function enableBtn(){
   document.getElementById("button1").disabled = false;
 }
 </script>

It should however work like the following:

Explanation: This code snippet indicates that when a user successfully completes the reCAPTCHA, the "myVerificationCallback" function will be executed, receiving the "g-recaptcha-response" token as input

No example myVerificationCallback script is shown and I don’t know how to receive the the “g-recaptcha-response” token as input

Try to check if get anything to your callback:

Your callback script is not taking in a variable which would have the input in it, or doing anything with it. Something like

function enableBtn(response) {
    document.getElementById("g-recaptcha-response").value(response);
}

When I add alert(response) to the enableBtn(response) function, the token appears in the pop-up but when I use debug($this->request) in my controller, the protected data still returns an empty variable 'g-recaptcha-response' => ''.

Did you fix your enableBtn function so that it actually puts the response value into the form field, per the code I suggested above?

Yes. I am using:

function enableBtn(response){
    alert(response);//this successfully shows the response token
    document.getElementById("button1").disabled = false;
    document.getElementById("g-recaptcha-response").value(response);
 }

Have you confirmed (e.g. with browser tools) that when this happens the value is correctly inserted into the form field in the browser?

I inspected the hidden input with id and name g-recaptcha-response and the value was empty.

Then there is still something wrong with your enableBtn function.

There is no such thing as a .value() method in native JS (unless you added it)

At least I get an error in the JS console which tells me that

Uncaught TypeError: document.getElementById(...).value is not a function

usually one should set attributes via

document.getElementById("somesuperid").setAttribute('value', 'test');

In my defence, I did say “something like…”

I got it to work using the following as the callback function:

function LoginButton() {
  var response = grecaptcha.getResponse();
  if(response.length === 0) { 
    //reCaptcha not verified
    alert("no pass"); 
  }
  else { 
    //reCaptch verified
    alert("pass", response); 
    
     var response = document.getElementById("g-recaptcha-response").value;
	//alert('response= ' + response);
  }
}

I used
var response = document.getElementById("g-recaptcha-response").value;
with value at the end. You said this wasn’t javascript but it worked.

Google showed:

// Correct usage:
const inputElement = document.getElementById('myInput');
const inputValue = inputElement.value;

// Incorrect usage:
const divElement = document.getElementById('myDiv');
const divValue = divElement.value; // This will cause the error

But I declared response two times. That needs to be changed.

If I change the name of the g-recaptcha-response hidden input to something other than response, it doesn’t work. But maybe I will have browser incompatibility issues if I don’t fix it.

var response = document.getElementById("g-recaptcha-response").value; gets the value from the input. What you want to do is set the value into the input, with the setAttribute('value' call that Kevin shared, i.e.

document.getElementById("g-recaptcha-response").setAttribute('value', response);