Jump to content
wisconsinWildcat

Unexpected end of JSON input

Recommended Posts

Newbie here.

I have an ajax method in jquery calling a PHP class to search a database and return a single column in jSON, but I'm getting the "unexpected end" error message.

It doesn't have to be jSON if there's an easier or more sure way.

This is the meat of the jSON call. It was used for a ColdFusion component and was modified for PHP, so it's possible I left some chaff behind and don't recognize it.

    $.ajax({
        url: '../../../components/jobsDatabase.php',
        method: 'POST',
        dataType: 'json',
        data: {
            method: 'getAllRoles',
            returnFormat: 'json'
        },
        success: function(data) {
            var $optList = $('#rolesTitle');
            console.log('Success retrieving data.',data);
            $optList.empty();
            $optList.append('<option selected="true" disabled>Choose Job</option>');
            $optList.prop('selectedIndex',0);
            $.each(data, function(i,val){ 
                $optList.append('<option value="'+data[i]['role']+'">'+data[i]['role']+'</option>');
            });
            console.log('Done loading options.');
        },
        error: function(xhr, textStatus,errorThrown){
            console.log(xhr);
            alert(errorThrown);
        }
    });

Here's the class:

<?php
    class jobsDatabase {
        public $role;
        public $tag;
        public $location;
        public $job_id;
        
        function __construct( $role, $tag, $location, $job_id ) {
            $this->role     = $role;
            $this->tag      = $tag;
            $this->location = $location;
            $this->job_id   = $job_id;
        }
        
        function getAllRoles() {
            include( "connect_database.php" );
            $sql = "SELECT role FROM thedatabasenamehere.uniqueroles ORDER BY role";
            $json = array();
            $result = mysqli_query( $dbhandle, $sql );
            mysqli_close($dbhandle);
            while($row = mysqli_fetch_assoc($result)) {
                $temp = array( 
                    'role' => $row["role"]
                );
                array_push( $json, $temp );
            }

            $jsonstring = json_encode($json, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_FORCE_OBJECT);
            echo $jsonstring;

            die();
        }
    } // End of the class jobsDatabase
?>

I've run the connect-to-database and SQL/select separately and they work fine.  I wish you could easily use console.log() in PHP, it would sure help with debugging!   Yes, I use a real database name for "thedatabasenamehere".  I started the encode with no options, been trying some things out of desperation.

Also, shouldn't it "return $jsonstring" instead of echo it?  All the online references I found used echo so I'm confused.

Any help greatly appreciated.

Thank you!

WW

Share this post


Link to post
Share on other sites

Couple questions here, but the big one is this: you are calling the jobsDatabase::getAllRoles() method, right?

In your ajax target script (../../../components/jobsDatabase.php) you instantiate a jobsDatabase object, then call getAllRoles() on that object, right? If so, then yes, it might make more sense to return from the method instead of directly outputting (you'd have to dump the returned value from the instantiated object). At this point var_dump() $json after your while loop and check the network tab of your browser's developer's tools to see what the output is.

If you're not doing that, then that would be the problem - you're never going to get data from a method you don't call inside and object you don't instantiate.

Share this post


Link to post
Share on other sites

"you are calling the jobsDatabase::getAllRoles() method, right?"

Um...I definitely think so? 🙄

I thought the jQuery ajax code did that.  I also include it.  I posted everything pertinent. By virtue of you asking that question,  though,  you make me doubt that. 

How should I be making this event driven call?

Share this post


Link to post
Share on other sites

Instead of echoing the json string you should return it. 

return $jsonstring; 

Then you would need something like this. 

$job_db = new jobsDatabase; 

$data = $job_db->getAllRoles(); 

echo $data; 

 

Share this post


Link to post
Share on other sites

Nice, thank you! Didn't know exactly how to do that in PHP, you may have just given me the tools to finish this conversion!

wW

 

Share this post


Link to post
Share on other sites

What taquitosensei just posted is what I was talking about. Ajax is connecting to the file jobsDatabase.php and will parse that file. But if there's no action in the script (like instantiating the object and calling the getallRoles() method), nothing will happen.

Share this post


Link to post
Share on other sites

maxxd, isn't the method= portion of the ajax command doing just that, calling for the execution of the getAllRoles function?   Not sure how else I'd do an Ajax call without that. 

From what I ascertain about taquitosensei's post, I would replace the ajax command with the object call instead, right?

Share this post


Link to post
Share on other sites

From the jQuery documentation:

Quote
  • method (default: 'GET')
    Type: String
    The HTTP method to use for the request (e.g. "POST", "GET", "PUT"). (version added: 1.9.0)

The AJAX call will connect with the script assigned to the url parameter of settings object. In that script is where some action has to take place. For instance, in WordPress you pass a field named 'action' in your dataset to admin-ajax.php. admin-ajax.php then uses the value of that field to know what PHP functions to call in order to get you the data you need. What taquitosensei and I are suggesting is that you add the following to the end of he script - after the closing bracket of your class definition:

$job_data = new jobsDatabasee();
$data = $job_data->getAllRoles();
die($data);

and change `echo $json` to `return $json` inside the getAllRoles() method.

Before you do that however, what does the response header show in your devtool's network tab after the AJAX call has been made?

Share this post


Link to post
Share on other sites
Posted (edited)

I just took a look at the code again. I missed the 'method' in your data set - so, yes it's possible that is all being handled behind the scenes and not something you need to worry about. (Sorry - it's Monday in a big way here...)

So that begs the question, what does the response show in your browser's devtool's network tab?

Edited by maxxd

Share this post


Link to post
Share on other sites

I'm not used to using the Network tab - didn't need it with ColdFusion. What am I looking for there?

I do get the error "SyntaxError: Unexpected end of JSON input" popping up from the ajax error output though.

Share this post


Link to post
Share on other sites

Would I be able to replace the ajax call with 

$job_data = new jobsDatabasee();
$data = $job_data->getAllRoles();
die($data);

Admittedly, this is an area of jQuery/Javascript and PHP that is uncharted territory for me.

Share this post


Link to post
Share on other sites
15 minutes ago, wisconsinWildcat said:

I do get the error "SyntaxError: Unexpected end of JSON input" popping up from the ajax error output though.

Right, and we need to see what the actual JSON string is. If you're using Chrome, select 'More Tools > Developer Tools' from the menu (option - command - uppercase 'i' on a mac, Ctrl + Shift + uppercase 'i' on Windows). You'll see the 'Network' tab along the top - select that, then trigger your ajax call. You'll see 'jobsDatabase.php' under the 'Name' column. Click it, then select the 'Response' tab from the details screen that appears. This will show you the raw JSON output, which may have a slightly more helpful error message.

Share this post


Link to post
Share on other sites

You should be able to browse to jobsDatabase.php?method=getAllRoles and see your json. If you don't then the php to echo the json isn't being called. You do need to echo the $data. Just doing die($data); will end the script without sending the json data.   The ajax call is on the client side and it posts to the php page which then runs  and outputs the json data which the ajax call receives in the success and processes. 

Share this post


Link to post
Share on other sites

Ah, I had the dev tools up and the Network tab opened, but didn't know what you wanted to see from there.  Great to know and I can there to see the response, but....

"This request has no response data available."

 

Share this post


Link to post
Share on other sites

Sadly, "/jobsDatabase.php?method=getAllRoles" shows nothing. I changed it to "echo $jsonstring;" and still nothing.

 

Here's what Headers show when I call it with url/script?method  (I think I changed just enough to protect my client and my workstation) which makes it look like I'm making the trip there successfully, but it results in no data output:

    1.  
      Request URL:
      http://domain-name-here/components/jobsDatabase.php?method=getAllRoles
      Request Method:
      GET
      Status Code:
      200 OK
      Remote Address:
      xxx.xxx.200.71:80
      Referrer Policy:
      no-referrer-when-downgrade
      Response Headersview source
      Content-Length:
      0
      Content-Type:
      text/html
      Date:
      Mon, 18 Mar 2019 19:27:19 GMT
      Server:
      Microsoft-IIS/7.5
      X-Powered-By:
      ASP.NET
      X-Powered-By-Plesk:
      PleskWin
      Request Headersview source
      Accept:
      text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
      Accept-Encoding:
      gzip, deflate
      Accept-Language:
      en-US,en;q=0.9
      Cache-Control:
      max-age=0
      Connection:
      keep-alive
      Cookie:
      PHPSESSID=7hg9abcdefg8ii5rjtne1chph3g1
      Host:
      domain-name-here
      Upgrade-Insecure-Requests:
      1
      User-Agent:
      Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
      Query String Parametersview sourceview URL encoded
      method:
      getAllRoles

       

    1.  

Share this post


Link to post
Share on other sites

Did you write jobsDatabase.php yourself? Are you using a framework or library?

Share this post


Link to post
Share on other sites

yes, I wrote it myself.  Right now, what I shared here is the entire thing, to start. It will grow much larger with functions that accept inputs as I do the conversion, but I wanted this first one to work without pollution from other functions getting in the way.

 

Share this post


Link to post
Share on other sites

If that's all the code there is and you're not using a framework, then yes, you need to call the method on the object.

Add this to the bottom of your file:

$job_data = new jobsDatabase(0,0,0,0);
$data = $job_data->getAllRoles();
die($data);

Note that anything happening here is dependent on the contents of connect_database.php.

While you're learning it may be a little easier to create a static array inside getAllRoles() and output that. That way you know everything is self-contained and you know what you're expecting. This should make it easier to track down any issues and errors in the process.

Share this post


Link to post
Share on other sites

I'm sorry, but add it to the end of which file?  I can't add it after the Ajax command because that's where the <option> statement is assembled.

Share this post


Link to post
Share on other sites

...and are you recommending

jobsDatabase(0,0,0,0);

because there are four PUBLIC statements at the beginning, and this provides placeholders for them?

Share this post


Link to post
Share on other sites
Posted (edited)

I followed answer 2 on https://stackoverflow.com/questions/17356469/how-to-call-a-class-function-from-jquery-php and now do not get any errors, but it doesn't stuff the result back to the form. 

That's a different problem. I'll keep grinding.

Thanks for the help!

P.S. What I don't understand in that method is why I can't have it all in one file. My main page calls a js file that calls a single-use php file that instantiates an object from yet another file.  Seems like over-complication.

Edited by wisconsinWildcat

Share this post


Link to post
Share on other sites

Yeah, Jason Larke's answer is pretty much exactly what taquitosensei and I have been saying.

1 hour ago, wisconsinWildcat said:

...and are you recommending


jobsDatabase(0,0,0,0);

because there are four PUBLIC statements at the beginning, and this provides placeholders for them?

No. The 'public statements' before the __construct() method are called object properties or object variables. The reason I'm passing in 4 random values is because the constructor signature calls for 4 parameters to be passed in; you've got

22 hours ago, wisconsinWildcat said:

__construct( $role, $tag, $location, $job_id )

The first 0 is now assigned to $role, the second is $tag, third is $location, and fourth is $job_id. They're not used in the class you've written, so I passed in nonsense values.

59 minutes ago, wisconsinWildcat said:

What I don't understand in that method is why I can't have it all in one file. My main page calls a js file that calls a single-use php file that instantiates an object from yet another file.  Seems like over-complication.

There's a bunch of different reasons for having multiple files. The biggest is that AJAX is a client-side technology, but database interaction is a server-side technology. So you need to have the JavaScript file and a PHP file. The JavaScript is separate from the HTML file because if it was all in the same file you'd run a decent chance of breaking the functionality every time you change a DOM element.

The PHP is the server-side file that actually gathers the data and prints it back to the AJAX call. Adding the lines above to the jobsDatabase.php file will automatically create an instance of the jobsDatabase class and run the getAllRoles() method of that object, which in turn prints the gathered data.

Basically, you're dealing with a whole lot of moving parts with what you're trying to do. Given what we've talked about, I'll recommend again just stubbing in the data - instead of trying to use an additional PHP file to connect to the database and gather the actual data, just make up an array and print it to the AJAX call. In the AJAX success() callback, print that data to screen or console. Once you see the data you're expecting, move on to the next stage - in this case, populating the returned data in the form. From there, worry about actual database interaction.

Hopefully at least some of that makes sense - again, it's  been a bit of a Monday here.

Share this post


Link to post
Share on other sites

Where do you create your database connection in jobsDatabase.php?

Share this post


Link to post
Share on other sites
12 hours ago, wisconsinWildcat said:

I followed answer 2 on https://stackoverflow.com/questions/17356469/how-to-call-a-class-function-from-jquery-php and now do not get any errors, but it doesn't stuff the result back to the form. 

That's a different problem. I'll keep grinding.

Thanks for the help!

P.S. What I don't understand in that method is why I can't have it all in one file. My main page calls a js file that calls a single-use php file that instantiates an object from yet another file.  Seems like over-complication.

Because it doesn't work that way. Ajax is client side javascript that runs in the browser. It is not aware of the php page at all until you say,  send this data to jobsDatabase.php on the server and get me the results.

Share this post


Link to post
Share on other sites
Posted (edited)

I apologize for the delay in responding. Life threw me a couple curveballs I had to contend with.

Maxxd, I appreciate your explanation more than you know. I've been in the computer field and programming since 1978 and I've forgotten more languages (most self-taught, many in the mainframe realm, then PC's when they came out: MAPPER, SSG, Basic, Pascal, Fortran, COBOL, Assembler, PowerBuilder, dBASE, Foxpro, and on and on) than most programmers ever learn, but I never did quite get the ajax stuff, and I'm brand new to PHP.  Your explanation helps me a great deal, and I feel it's going to help more folks who stumble upon this thread.

Barand, I have an include file for my connection, and I include that file before every database action.  Perhaps it's not correct for PHP, but in past programs I've learned to re-use programs and minimize the amount of code I ever have to re-write for new systems. I'd bet you do as well.  I'm sorry I didn't include the entire file, but I am trying to protect my client.

taquitosensei, Thanks for chiming in.  One day, this will all click, like it's done for so many programs before, and I'll be off and running.

I certainly appreciate all the help from all of you! Thank you!   I'm not "there" yet, but I hope to be soon.

May you all enjoy 41+ years of programming!  And I'm nowhere near done yet.  PHP / Ajax / MySQL is just the next thing for me.

Edited by wisconsinWildcat

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.