Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I’m really hoping some one here will be able to help me with this!

I’m making a Facebook Canvas game and I’m having difficulty inputting the player’s details (Facebook ID, first name, last name, email etc) into my database.

Here’s the process I’m trying to make happen:

When a player arrives at the game’s homepage, I want the game to check the user’s Facebook ID against the database to see if the player’s id, and other details are there, this will tell me if they’ve played the game before. If their id/details are not contained in the database then I want them to be inserted, and I want a Javascript message box to appear which will contain a short tutorial on the game. If the check shows that the player’s details are already in the database, then I want no message box to appear and the page should be unchanged.

I’m trying to get this to work by calling a Javascript function using “onload” in the html. The Javascript function contains code to get the user’s details from Facebook, and contains some AJAX which calls a PHP script which inserts the details into the database. This works perfectly if I use “onclick” or “onmouseover” inside the tag (when I try these two methods the user’s details get entered correctly and the message box appears). However, when I try using the “onload” method, while it does create a row in the database, every cell is empty, it seems like it’s executing the code correctly but the AJAX call doesn’t have time to get the user’s details from Facebook, and so the row gets created with no values.

This is the correctly working Javascript/AJAX funtion, and the PHP it calls:

function getUserDetails() {


  FB.api('/me', function(response) {
      var userid = response.id;
      var userfirst_name = response.first_name;
      var userlast_name = response.last_name;
      var useremail = response.email;
      var userbirthday = response.birthday;
      var usergender = response.gender;


    $.ajax({
     url: 'insertuserdetails.php',
    data: {'userid' : userid, 'userfirst_name' : userfirst_name, 'userlast_name' : userlast_name, 'useremail' : useremail, 'userbirthday' : userbirthday, 'usergender' : usergender},
    type: "POST",

}).done(function( msg ) {
  alert("php file called, A TUTORIAL COULD GO HERE"+msg);
});

});


}

The PHP:

<?php 

session_start();

require_once '/facebook-php-sdk-v4-4.0-dev/autoload.php';

use Facebook\HttpClients\FacebookHttpable;
use Facebook\HttpClients\FacebookCurl;
use Facebook\HttpClients\FacebookCurlHttpClient;
use Facebook\Entities\AccessToken;
use Facebook\Entities\SignedRequest;
use Facebook\FacebookSession;
use Facebook\FacebookSignedRequestFromInputHelper;
use Facebook\FacebookCanvasLoginHelper;
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookRequest;
use Facebook\FacebookResponse;
use Facebook\FacebookSDKException;
use Facebook\FacebookRequestException;
use Facebook\FacebookOtherException;
use Facebook\FacebookAuthorizationException;
use Facebook\GraphObject;
use Facebook\GraphUser;
use Facebook\GraphSessionInfo;

FacebookSession::setDefaultApplication('MYAPPID', 'MYAPPSECRET');

$servername = "XXX";
$username = "XXX";
$password = "XXX";
$dbname = "XXX";


// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}

$userid = $_POST['userid'];
$userfirst_name = $_POST['userfirst_name'];
$userlast_name = $_POST['userlast_name'];
$useremail = $_POST['useremail'];
$userbirthday = $_POST['userbirthday'];
$usergender = $_POST['usergender'];

$sql="INSERT INTO player (facebook_id, first_name, last_name, email, birthday, gender) VALUES 
('$userid', '$userfirst_name', '$userlast_name', '$useremail', '$userbirthday', '$usergender')";


if (mysqli_query($conn, $sql)) {
    echo "New record created successfully";
} else {
    echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}

mysqli_close($conn);
?> 

I could just use “onclick” and “onmouseover” but this means that every time these actions are performed by the user, multiple calls will be made to the database, that’s really messy and would probably slow the game down a lot. Ideally I’d like for the Javascript function to be called only once per session (when the page loads).

The "onload" in the html that results in an empty row being created:

<body onload="getUserDetails()">

I’m not sure why "onload" returns empty values while the other two methods don’t. I was wondering if delaying a function by a few seconds would solve the problem? But I’m really not sure, so I thought I’d ask for help here. :) Thanks in advance!

Code used to initialize the Facebook Javascript API:

$( document ).ready(function() {

FB.init({
  appId: MYAPPID,
frictionlessRequests: true,
status: true,
version: 'v2.1'
});

FB.Event.subscribe('auth.authResponseChange', onAuthResponseChange);
FB.Event.subscribe('auth.statusChange', onStatusChange);

UPDATE: I’ve marked @floor’s answer as working because it has solved my problem. There’s just one issue I’m having now but it doesn’t directly involve the AJAX issue.

I thought I’d be able to do something simple like check if the AJAX+PHP insertion was successful and if so, then a tutorial pop-up would appear, if not, then it would mean that user’s id is already in the database and so no tutorial would appear.

My problem is that this check was always coming back as successful (because the AJAX call is always successful, regardless of whether the SQL insert completes successfully or not), so I was asking the wrong question, instead I needed to add an echo at the end of my SQL/PHP script, whose value is determined by the success or failure of the insert statement. I then need to add a success check in the AJAX call which will initiate the popup, or not, depending on the echo it receives back from the PHP script.

The code I’m using to do this is: AJAX:

   $.ajax({
     url: 'insertuserdetails.php',
     data: {'userid' : userid,
           'userfirst_name' : userfirst_name,
           'userlast_name' : userlast_name,
           'useremail' : useremail,
           'userbirthday' : userbirthday,
           'usergender' : usergender},
    type: "POST",
    success: function(response){
                if(response==1){
                        alert( "Success!");
                        }else{
                        alert( "Failed!" );
                             }
                }
   });

And the PHP to send the success/fail echo:

//If the SQL insert statement completed correctly...
if($sql){
$verify=1;
}else{
$verify=0;
}
echo $verify;

I must have an error in this code, because the popup always displays "Failed!", it does this both when the Insert is successful (when I run the script with an empty database), and when it's unsuccessful (when the database isn't empty/when the row already exists before running the script).

The PHP should be echoing "1", so the AJAX should output "Success!", but it isn't. Can anyone see an error in the check I'm trying to perform?

share|improve this question
    
Hi @floor thanks for your reply, I've tried that but it's still not working. Am I right in thinking that if "onload" is inserting an empty row, then the problem isn't with the page not being loaded in time, but is instead with the Javascript call to Facebook and the AJAX not having time to operate before the PHP runs the insert command? Also, the Javascript function and the AJAX are contained in a .js file/script which is included/called at the top of the html page, I've tried writing the Javascript+AJAX function directly on to the html page too, but it's resulting in the same empty rows. –  Emily Mar 25 at 16:51
    
Hi @floor yes that's correct, insertuserdetails.php contains the SQL to take the data the AJAX gives it and insert it into the database. The values of var userid = response.id etc are not empty when I set the function to run "onclick" or "onmouseover" (they get entered into the database correctly when I try these two methods), but when I try the "onload" method, while it successfully creates a row in the table, the values are always empty. So it seems like the AJAX call is sending empty data, would that suggest the problem is some delay in getting the data from Facebook? –  Emily Mar 25 at 18:18
    
Hi @floor, if I understand correctly you mean I should replace the variable named in the PHP script with some text? I did that and then reloaded the page, it called the Javascript & AJAX and a new row was created in the database, all values were empty except for the variable I changed into text, that text got inserted into the row. In my reply to Mike's comment below I tried an alert before the AJAX call and it gave me an access token error. –  Emily Mar 25 at 18:50
    
Hi again @floor, other than the javascript contained in the game mechanics, and some javascript for an "Invite Friends" button, that's all the javascript I'm working with at the minute. –  Emily Mar 25 at 21:44
    
Can you post the code where you are initializing the facebook javascript api –  floor Mar 25 at 22:17

2 Answers 2

up vote 0 down vote accepted

Giving the comments, I think this code will work.

 FB.login(function(response) {
  if (response.authResponse) {
    console.log('Welcome!  Fetching your information.... ');

     FB.api('/me', function(response) {

     if (response.error) {
       console.log('Error - ' + response.error.message);
     }
     else {
       var userid = response.id;
       var userfirst_name = response.first_name;
       var userlast_name = response.last_name;
       var useremail = response.email;
       var userbirthday = response.birthday;
       var usergender = response.gender;

       $.ajax({
         url: 'insertuserdetails.php',
         data: {'userid' : userid,
               'userfirst_name' : userfirst_name,
               'userlast_name' : userlast_name,
               'useremail' : useremail,
               'userbirthday' : userbirthday,
               'usergender' : usergender},
        type: "POST",

       }).done(function( msg ) {
         alert("php file called, A TUTORIAL COULD GO HERE"+msg);
       });
     }
    });
  } else {
    console.log('User cancelled login or did not fully authorize.');
  }
 }, {scope: 'email user_birthday'});

So what this does is after the user authenticates (logs in / gives permission) then the api requests the information and calls your ajax request. I think by doing this the data will be available. Plus now you don't need to call this function, it just happens on user authentication.

So now onto the last part of your question.

You want to know if the insert occurred or if it failed you can do this by setting your sql query to a variable:

$result = mysqli_query($conn, $sql);
if (!$result) {
   $verify=0;
}
else{
  $verify=1;
}
echo $verify;
share|improve this answer
    
Try this and let me know what the outcome is –  floor Mar 25 at 19:02
    
Hi @floor thanks for your reply, I tried your code but nothing happens, no insertion into the database and not even an error message, despite that I still think maybe it's an error in not getting the data from Facebook in time before the php is run? I'm now considering creating a landing page with an "Enter" button to force the player to have an onclick event that will load up the database before they reach the game, I don't want to do that but I can't see why the onload isn't working, I don't understand how to prevent the php from running before the user's data is received from Facebook. –  Emily Mar 25 at 21:40
    
the problem is that facebook loads data in async, so the data isn't there are the time of the function call. Which you already figured, but there are options to leverage this. I requested for javascript code mainly I need to see the facebook api initialization because in that block of code you can tell it once its done load, gets the data call this function. –  floor Mar 25 at 22:16
    
Hi @floor, I'm trying the code you gave to put after the sql query but for some strange reason the AJAX is always alerting with the second (failed) option, even when the record is added successfully. I'm using your SQL on the database side, and this is what I have in the AJAX file: –  Emily Mar 26 at 22:09
1  
Ah yep :) you were right, just had to add it as a permission, thanks again! –  Emily Mar 27 at 1:07

Try putting your call in the document ready function.

$(document).ready(function() {
    getUserDetails();
});

This will fire after the body has loaded fully (or more accurately, when the DOM is ready).

http://learn.jquery.com/using-jquery-core/document-ready/

share|improve this answer
    
Hi @mike-b thanks for your quick reply! I just tried: <script> $( document ).ready(function() { getUserDetails(); }); </script> Inside the <head> tag of the html page, and I got rid of the “onload” inside the <body> tag, but it’s still creating a blank row inside the database. It’s seems like the function isn’t waiting for the user data from Facebook and is instead just creating an empty row. :( –  Emily Mar 25 at 16:24
    
Hm... Try setting a break point in your JS code and check the value of "response". In Chrome, you can hit F12 to bring up the tools screen, then I believe it's the "Sources" tab. –  Mike B. Mar 25 at 17:00
    
Or, for testing, you could just add alert(JSON.stringify(response)); right before your AJAX call, if that's easier! –  Mike B. Mar 25 at 17:06
    
Also... not related to your question (and maybe you just have it that way for testing), but you need to escape your database inputs in your PHP script... browsers can (either accidentally or maliciously) send whatever data they want, so they can read (and/or destroy) your database if you don't escape them! :) –  Mike B. Mar 25 at 17:15
    
Hi @Mike-b I've just tried your suggestion of alert(JSON.stringify(response)); and when I called the function using onload it gave me the following error: {"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500}} I’m really confused now, does this mean that an active access token isn’t in place in time when using “onload” but is in place when using “onclick” or “onmousemove”? –  Emily Mar 25 at 18:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.