Closed sparcbr closed 3 years ago
Hi @sparcbr ,
Did you face any specific issue? Do you have an example code?
The method _exec_query()
is a private method and it is working as it should. It does return an array. An array of objects actually. Check out this example:
<?php
$igdb = new IGDB($client_id, $access_token);
// Example query with zero results
var_dump(
$igdb->game(
array(
"search" => "abcdefghijklm",
"fields" => array("id", "name")
)
)
);
// Example query with 1 result
var_dump(
$igdb->game(
array(
"search" => "uncharted 4",
"fields" => array("id", "name"),
"limit" => 1
)
)
);
// Example query with 2 results
var_dump(
$igdb->game(
array(
"search" => "uncharted 4",
"fields" => array("id", "name"),
"limit" => 2
)
)
);
?>
This script executes 3 different queries with 0, 1 and 2 items in their results. The output of the script is:
C:\wamp64\www\igdb\index.php:16:
array (size=0)
empty
C:\wamp64\www\igdb\index.php:25:
array (size=1)
0 =>
object(stdClass)[2]
public 'id' => int 7331
public 'name' => string 'Uncharted 4: A Thief's End' (length=26)
C:\wamp64\www\igdb\index.php:35:
array (size=2)
0 =>
object(stdClass)[2]
public 'id' => int 7331
public 'name' => string 'Uncharted 4: A Thief's End' (length=26)
1 =>
object(stdClass)[3]
public 'id' => int 136686
public 'name' => string 'Uncharted 4: A Thief's End - Deluxe Edition' (length=43)
You can see in case of any number of results, the return value of the endpoint method is always an array. No matter how many matches are in the results.
Hello, unfortunately I have the same problem.
$igdb = new IGDB("key", "secret"); $result = $igdb->game( array( "search" => "abcdefghijklm", "fields" => array("id", "name") ) );
var_dump($result);
PHP then reports:
Fatal error: Uncaught Error: Cannot use object of type stdClass as array in igdb.php:314 Stack trace: #0 igdb.php(688): IGDB->_exec_query('https://api.igd...', Array) #1 {main} thrown in igdb.php on line 314
If I change line 305 as sparcbr wrote, the error is eliminated afterwards.
I did some investigation on this issue and I found that it seems the guys at IGDB has changed the the way the endpoint responds in case of errors. Changing the code a bit, printing the contents of the$result
variable in the _exec_query
method like this:
// Executing the request
$result = json_decode(curl_exec($this->curl_handler));
// Getting request information
$this->request_info = curl_getinfo($this->curl_handler);
// If there were errors
if($this->request_info['http_code'] != 200) {
var_dump($result); // a var_dump here to see what response we got from IGDB, removed the rest of the response processing
throw new Exception('Error ' . $this->request_info['http_code'] . ': ' . $result->message . ": " . $result->Docs);
}
Using this example code:
<?php
require_once "src/class.igdb.php";
// invalid key and access token
$igdb = new IGDB("key", "secret");
try {
$result = $igdb->game(
array(
"search" => "abcdefghijklm",
"fields" => array("id", "name")
)
);
var_dump($result);
} catch (Exception $e) {
echo $e->getMessage();
}
?>
Will result this output:
C:\wamp64\www\igdb-original\src\class.igdb.php:312:
object(stdClass)[2]
public 'message' => string 'Authorization Failure. Have you tried:' (length=38)
public 'Tip 1' => string 'Ensure you are sending Authorization and Client-ID as headers.' (length=62)
public 'Tip 2' => string 'Ensure Authorization value starts with 'Bearer ', including the space' (length=69)
public 'Tip 3' => string 'Ensure Authorization value ends with the App Access Token you generated, NOT your Client Secret.' (length=96)
public 'Docs' => string 'https://api-docs.igdb.com/#authentication' (length=41)
public 'Discord' => string 'https://discord.gg/FrvfwQg' (length=26)
Error 401: Authorization Failure. Have you tried:: https://api-docs.igdb.com/#authentication
This is an object indeed, and this is why the parsing throws error. Executing the request from postman I will get this result:
{
"message": "Authorization Failure. Have you tried:",
"Tip 1": "Ensure you are sending Authorization and Client-ID as headers.",
"Tip 2": "Ensure Authorization value starts with 'Bearer ', including the space",
"Tip 3": "Ensure Authorization value ends with the App Access Token you generated, NOT your Client Secret.",
"Docs": "https://api-docs.igdb.com/#authentication",
"Discord": "https://discord.gg/FrvfwQg"
}
So it seems the problem is, that the failed request is recognised without an issue (catching the error code 401) but parsing the response should be updated for this new format.
@h4eDashboard , your example must have been executed without proper client id and access token. When I executed the same code I got the error message you mentioned, but when I replaced the "key" and "secret" strings with my valid credentials, the game
method returned with a simple empty array.
C:\wamp64\www\igdb-original\index.php:20:
array (size=0)
empty
Can you confirm this?
With the changed code, the error message "Authorization Failure" now appears.
However, I get a PHP error again with full login data that was up before the change you described:
I read a list of games, write the result to $result and then want to check directly if isset($result[0]["name"]). At this point PHP reports again Fatal error: Uncaught Error: Cannot use object of type stdClass as array. So according to PHP the return of $igdb->game($query) is still not an array. The error disappears only as soon as the command in the class json_decode(curl_exec($this->curl_handler), true); means, without comes perma the message that it is not an array.
// Executing the request $result = json_decode(curl_exec($this->curl_handler), true);
This way the error will no longer appear.
Okay, I think I can see the problem now. You are trying to access the data using $result[0]["name"]
. This is incorrect. This way you are trying to access an element in an associative array. The response from the endpoint methods are - if count is not present - always array of objects. Let's check this code for example:
<?php
require_once "src/class.igdb.php";
$client_id = "xxx";
$access_token = "xxx";
try {
$result = (new IGDB($client_id, $access_token))->game(
array(
"search" => "uncharted",
"fields" => array("id", "name"),
"limit" => 3
)
);
var_dump($result);
echo $result[0]->name; // this is the proper way of accessing properties
} catch (Exception $e) {
echo $e->getMessage();
}
?>
The output of this command code is:
C:\wamp64\www\igdb-original\index.php:18:
array (size=3)
0 =>
object(stdClass)[2]
public 'id' => int 126126
public 'name' => string 'Uncharted Ocean' (length=15)
1 =>
object(stdClass)[3]
public 'id' => int 82008
public 'name' => string 'Uncharted Waters' (length=16)
2 =>
object(stdClass)[4]
public 'id' => int 4459
public 'name' => string 'Uncharted Waters' (length=16)
Uncharted Ocean
The var_dump here shows that the the $result
is an array with objects in it, and you can access the first elements' name property with the object operator: $result[0]->name
.
The php documentation on object properties: https://www.php.net/manual/en/language.oop5.properties.php
If you try to access it like $result[0]["name"]
it will throw an exception saying: Fatal error: Cannot use object of type stdClass as array.
Oh, I must have been dreaming, thanks for pointing that out.
The changes are merged to the master branch, version 4.0.2 contains the fix for this issue.
_exec_query() is returning an object, not an array..
to fix, add true as second argument to json_decode: $result = json_decode(curl_exec($this->curl_handler), true);