PHP/JavaScript: How do I access the properties of my JSON object from my PHP script?

I used .ajax() to call a PHP script which returns a Customer object. This is what's in the PHP script:

$cust = getCustomer($custID); // I HAVE CONFIRMED, $cust IS CORRECTLY POPULATED WITH THE EXPECTED DATA
$arrResponse = array('result'=>'ok', 'cust'=>$cust); // I AM PASSING IT BACK TO MY .ajax() CALL ON THE WEB PAGE
echo json_encode($arrResponse);

Open in new window


Then on my web page, I have this:

.done(function(data, textStatus, jqXHR) {
    // console.log(data.cust) PRINTS [object Object], SO I KNOW IT HAS SOMETHING.
    // I WAS HOPING I'D BE ABLE TO SEE THE FIRST NAME PROPERTY HERE, BUT I GET 'undefined'.
    console.log(data.cust.firstname);
    }
})

Open in new window


So what am I doing wrong? How can I extract the customer properties from the JSON object that PHP sent back to me? Thanks.
elepilAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dave BaldwinFixer of ProblemsCommented:
I would access your PHP page directly in your browser to see what it actually returns.  It can be hard to troubleshoot when you are mixing all those functions together.
elepilAuthor Commented:
Dave,

Hmm.. I tried that and I got this:

{"result":"ok","cust":{}}

Open in new window


It's returning nothing in the cust object. Is PHP not able to pass a json representation of a class data object back? I am able to view the contents of my Customer object through it's __toString() prior to sending it back to the page, and it is properly populated with data.

Do you, as a common practice, ever pass a data object from PHP back to the page via Ajax?
Dave BaldwinFixer of ProblemsCommented:
I don't use JSON for anything.   I do use AJAX a lot but all my return data is text of one sort or another.  What's the original data look like?  Your code looks like $cust is either empty or it is another array.
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

Dave BaldwinFixer of ProblemsCommented:
This little demo seems to work ok.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>JSONTest</title>
</head>
<body>
<h1>JSONTest</h1>
<?php 
//$cust = getCustomer($custID); // I HAVE CONFIRMED, $cust IS CORRECTLY POPULATED WITH THE EXPECTED DATA
$cust = 'thecustomer'; // I HAVE CONFIRMED, $cust IS CORRECTLY POPULATED WITH THE EXPECTED DATA
$arrResponse = array('result'=>'ok', 'cust'=>$cust); // I AM PASSING IT BACK TO MY .ajax() CALL ON THE WEB PAGE
foreach($arrResponse as $key => $val) {
	echo $key.'=>'.$val.'<br>';
	}
echo json_encode($arrResponse);
 ?>
</body>
</html>

Open in new window

elepilAuthor Commented:
Dave, $cust is supposed to be an instance of my Customer class, not a string. You put a string value in it, and yes, it will be okay because I know strings work fine with json.
Dave BaldwinFixer of ProblemsCommented:
In this statement array('result'=>'ok', 'cust'=>$cust) , $cust is a 'value' and should be a string or a number.  This page about the 'array' type http://php.net/manual/en/language.types.array.php , only mentions classes as being converted to arrays.  Try echoing $cust and see what you get.
Julian HansenCommented:
I suspect you probably left out the JSON parameter in your ajax call to tell JQuery to parse the returned result from JSON.
More here http://api.jquery.com/jQuery.post/ [dataType]

Here is some sample code that demonstrates several approaches (including yours) to retrieving data via AJAX.

The PHP file
<?php
function getCustomer($custId)
{
  $cust = new stdClass;
  $cust->custID = $custId;
  $cust->firstname= 'John';
  $cust->surname='Smith';
  $cust->accno='12345';
  return $cust;
}
$custID = isset($_REQUEST['custID']) ? $_REQUEST['custID'] : 0;
$arrResponse = array('result'=>'ok'); // I AM PASSING IT BACK TO MY .ajax() CALL ON THE WEB PAGE
if ($custID > 0) {
  $cust = getCustomer($custID); // I HAVE CONFIRMED, $cust IS CORRECTLY POPULATED WITH THE EXPECTED DATA
  $arrResponse['cust'] = $cust;
}
else {
  $arrResponse['result'] = 'fail';
  $arrResponse['error'] = 'Customer ID not found';
}

echo json_encode($arrResponse);

Open in new window


The calling file
<!doctype html>
<html>
<head>
<title>Test</title>
</head>
<body>

<form>
    Customer ID <input id="custID" type="text" /> <br/>
    <input type="submit" />
</form>

<ul id="result"></ul>

<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(function() {
  $('form').submit(function() {

    var postdata = {custID: $('#custID').val()};

    $.post('t792.php', postdata, function(){},'JSON').done(function(data, textStatus, jqXHR) {
      if (data.result == 'ok') {
        $('#result').append($('<li/>').html('POST .done() SUCCESS: ' + data.cust.firstname));
      }
      else {
        $('#result').append($('<li/>').html('POST .done() FAILED: ' + data.error));
      }
    });
    
    $.post('t792.php',postdata, function(data) {
      if (data.result == 'ok') {
        $('#result').append($('<li/>').html('POST success SUCCESS:  ' + data.cust.firstname));
      }
      else {
        $('#result').append($('<li/>').html('POST success FAILED: ' + data.error));
      }
    }, 'JSON');
    
    $.get('t792.php',postdata, function(){},'JSON').done(function(data, textStatus, jqXHR) {
      if (data.result == 'ok') {
        $('#result').append($('<li/>').html('GET .done SUCCESS:  ' + data.cust.firstname));
      }
      else {
        $('#result').append($('<li/>').html('GET .done FAILED: ' + data.error));
      }
    });
    
    $.get('t792.php', postdata, function(data) {
      if (data.result == 'ok') {
        $('#result').append($('<li/>').html('GET success SUCCESS:  ' + data.cust.firstname));
      }
      else {
        $('#result').append($('<li/>').html('GET success FAILED: ' + data.error));
      }
    }, 'JSON');
    
    $.ajax({
      url: 't792.php',
      type: 'POST',
      data: postdata,
      dataType: 'JSON',
      success: function(data) {
        if (data.result == 'ok') {
          $('#result').append($('<li/>').html('AJAX success SUCCESS:  ' + data.cust.firstname));
        }
        else {
          $('#result').append($('<li/>').html('AJAX success FAILED: ' + data.error));
        }
      }
    });
    
    return false;
  });
});
</script>
</body>
</html>

Open in new window


Working sample here http://www.marcorpsa.com/ee/t792.html

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ray PaseurCommented:
These AJAX things are so much easier to debug if you take one side at a time.  In my experience, the server side of the application can be handled by making GET requests - whether or not GET is the appropriate protocol.  Just start there anyway.  If you use GET requests you can debug the script from the browser address bar -- a great advantage.  In the event that your requests are not nullipotent and must use POST or PUT, you can make these protocol changes after the debugging process; just change your script and unit test case to reflect the new protocol.  By doing it this way you will be able to see the JSON string in the browser display, and you can visually check for accuracy.
Slick812Commented:
greetings elepil, ,  Debugging in the three process of the AJAX sequence, can be very misunderstood when anyone starts out with the Ajax server exchange code, as there can be an error in any of the three processes, , , and even errors in all three processes, and because Jquery Ajax, hides most of the javascript functioning and operations (to make it easy, LOL) , you have to guess sometimes, at where, or what the problem may be.
since your observed response string is -
    {"result":"ok","cust":{}}

then your PHP code definitely is bonked. Your object return from -
     $cust = getCustomer($custID);
 as $cust, does not seem to have ANY properties (public), that the json_encode( ) can do it's thing with, so you get nothing in the -
   "cust":{}
but an empty object {}
although you say that the  object gives you correct data with the  __toString()   , that is NOT what  json_encode( )  uses.
You will likely need to build your response using the  $cust  object methods, or  the access procedures, maybe something like -
   $arrResponse = array('result'=>'ok', 'cust'=> array('firstName' => $cust->getFirst(), 'lastName' => $cust->getLast()) );

or it may do a database pull for the user data,

$userData = $cust->DBselect();
$arrResponse = array('result'=>'ok', 'cust'=> array('firstName' => $userData->first, 'lastName' => $userData->last ) );

I am just guessing at the factors that your object from -
     getCustomer($custID)
has or can do, but whatever the $cust has to offer, the json_encode( )  can not deal with it.
elepilAuthor Commented:
Thanks to all responders. I found the problem, and I think I owe you all the solution.

JulianH, I greatly appreciate your thorough and concise examples that demonstrate how the server side and client side might look like.

Slick812, you are right that my problem is on the server side, and I appreciate your suggestion of breaking down my class object by assigning its individual properties to the array I'm returning to the page.

Both JulianH and Slick812's responses led me to the problem. JulianH gave examples of both how he thinks my Customer class would look like and how it would be inserted into the array I'm returning to the page. Slick812's did the latter.

To Ray Paseur and Dave Baldwin, as always, I'm grateful when you respond, and I appreciate your debugging suggestions which I will keep in mind.

To all of you, here is how my Customer class looks like (which I really should've included in my original post):

class Customer {
    protected $data = array();
    
    public function &__get($name) {
        if (isset($this->data[$name])) {
            return $this->data[$name];
        } else {
            $result = false;
            return $result;
        }
    }
    
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
    
    public function __toString() {
        $output = '[custid=' . $this->custid . ']' .
                  '[firstname=' . $this->firstname . ']' .
                  '[middlename=' . $this->middlename . ']' .
                  '[lastname=' . $this->lastname . ']' .
                  '[spouseFirstName=' . $this->spouseFirstName . ']' .
                  '[spouseMiddleName=' . $this->spouseMiddleName . ']' .
                  '[spouseLastName=' . $this->spouseLastName . ']' .
                  '[address1=' . $this->address1 . ']' .
                  '[address2=' . $this->address2 . ']' .
                  '[city=' . $this->city . ']' .
                  '[state=' . $this->state . ']' .
                  '[zipcode=' . $this->zipcode . ']' .
                  '[locale=' . $this->locale . ']' .
                  '[homephone=' . $this->homephone . ']' .
                  '[workphone=' . $this->workphone . ']' .
                  '[workextension=' . $this->workextension . ']' .
                  '[cellphone=' . $this->cellphone . ']' .
                  '[otherphone=' . $this->otherphone . ']' .
                  '[email=' . $this->email . ']' .
                  '[notes=' . $this->notes . ']' .
                  '[clientsince=' . $this->clientsince . ']' .
                  '[banned=' . $this->banned . ']' .
                  '[editdate=' . $this->editdate . ']' .
                  '[editedbyid=' . $this->editedbyid . ']' .
                  '[deleted=' . $this->deleted . ']' . '<br/>';
        
        return $output;
    }
}

Open in new window


I am using the PHP magic functions __get() and __set in my class. Without the __toString() method, one can't really tell what properties this class is supposed to have. I do it this way because in getCustomer(), you will see these lines:

$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Customer', array($custID));
            $customer = $stmt->fetch();

Open in new window


The above leverages PHP's feature of automatically populating a class with property/value pairs using column names and values read in from the database. It's a great convenience because I don't have to declare getters/setters for any property. PHP stores all properties of my Customer class in an internal array called $data.

What I had to do was make $data public. In doing so, the array was passed to the page so I could access it as data.cust.data.firstname, data.cust.data.lastname, etc.

Thanks again to all responders.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.