Hi!
I’m currently exploring your SDK for PHP and now I’m stuck on a problem that I seem to not figure out.
When i use a code like the following (from your documentation):
$query = new BackendlessDataQuery();
$query->setWhereClause('age = 147');
$result_collection = Backendless::$Persistence->find('Contact', $query);
I get an error message saying:
Fatal error: Uncaught exception ‘backendless\exception\BackendlessException’ with message ‘It is impossible get entity name, use the method “…->of(“entity_name”)->…” to set a specific entity.’ in …/vendor/backendless/src/services/Persistence.php:255 Stack trace: #0 …/vendor/backendless/src/services/Persistence.php(206): backendless\services\Persistence->getTableName() #1 …(62): backendless\services\Persistence->find(‘Contact’, Object(backendless\services\persistence\BackendlessDataQuery)) #2 …(40): …->getOldToken(NULL) #3 …(94): …->getToken() #4 …/main.php(11): …->updateAll() #5 {main} thrown in …/vendor/backendless/src/services/Persistence.php on line 255
What am I doing wrong? (I used … to remove some parts of “urls” that contains information about my system (name and so on))
Thanks in advance!
Hi Tobias,
Could you please try the following syntax instead? Please let me know if it works for you.
Backendless::$Data->of( ‘Contact’ )->find( $query );
Regards,
Mark
Thanks Mark!
Works perfectly
Just tried the same thing with findFirst and findLast. Didn’t work. I rewrote them to look like this:
public function findFirst( $data_query_or_relation_depth = null ) {
if( is_a( $data_query_or_relation_depth, '\backendless\services\persistence\BackendlessDataQuery') ) {
return new BackendlessCollection( RequestBuilder::doRequest( 'data', $this->getTableName() . '/first' ."?".$data_query_or_relation_depth->buildUrlVars(), null, 'GET') );
} else {
$relations_depth = $data_query_or_relation_depth;
$relations_depth = ( $relations_depth === null )? "" : "?relationsDepth={$relations_depth}";
return new BackendlessCollection( RequestBuilder::doRequest( 'data', $this->getTableName() . '/first' . $relations_depth, null, 'GET') );
}
}
public function findLast( $data_query_or_relation_depth = null ) {
if( is_a( $data_query_or_relation_depth, '\backendless\services\persistence\BackendlessDataQuery') ) {
return new BackendlessCollection( RequestBuilder::doRequest( 'data', $this->getTableName() . '/last' ."?".$data_query_or_relation_depth->buildUrlVars(), null, 'GET') );
} else {
$relations_depth = $data_query_or_relation_depth;
$relations_depth = ( $relations_depth === null )? "" : "?relationsDepth={$relations_depth}";
return new BackendlessCollection( RequestBuilder::doRequest( 'data', $this->getTableName() . '/last' . $relations_depth, null, 'GET') );
}
}
And now it works but I’m not sure if my code is correct now or if i screwed something over in the SDK?
Hi Tobias,
I had our PHP expert look into this and this is what I got back:
You should grab the latest code for the SDK. Then use any of the following approaches:
$last = Backendless::$Data->of("Contact")->findLast()->getAsArray();
// returns the data object as an array
$last = Backendless::$Data->of(“Contact”)->findLast()->getAsObject();
// returns the data object as stdClass
BackendlessAutoloader::addNamespace( ‘app’, DIR );
Backendless::mapTableToClass( “Contact”, “app\models\Contact” );
$last = Backendless::$Data->of(“Contact”)->findLast()->getAsClass();
// returns the data objects as an instance of your class (app\models\Contact)
Additionally, both findLast() and findFirst() can accept an integer value which identifies the depth of relations you want to retrieve.
$last = Backendless::$Data->of("Contact")->findLast( 3 )->getAsObject();
Hope this helps.
Regards,
Mark
Thanks Mark!
It works, it was me that didn’t understand the usage of findFirst and findLast. Thought you could use it as find with a query but to only return one result My bad!
I still ran in to new problems (that I can’t seem to solve through the documentation…). Now when I’ve fetched a result using the third method you described above. I try to use the setter for “value” (of my object) to update the object. This works but when I now run save($thisObject) I get the following error:
Fatal error: Uncaught exception ‘backendless\exception\BackendlessException’ with message ‘Backendless API return error: Saved related data contains inconsistent properties definitions. Please, make sure all related objects contain the same properties set or define all needed properties from console first . Error code:8021’
But my object looks like this:MyApp\Setting Object ( [data:protected] => Array ( [created] => 1454254140000 [___class] => Setting [ownerId] => [value] => token:3c9a594f6fb65ae8f0da8fa39cfddfa5178199da|expires:1453926063 [updated] => 1454254258000 [key] => bearer_token [objectId] => 04627D99-661C-0189-FF62-B05B74146500 [__meta] => {“relationRemovalIds”:{},“selectedProperties”:[“created”,"___class",“ownerId”,“value”,“updated”,“key”,“objectId”],“relatedObjects”:{}} ) )
The releatedObjects is empty so why does it tell me something is wrong with them?!
Thanks in advance!
Hi Tobias,
Would it be possible for you to share some sample code demonstrating the problem?
Regards,
Mark
Of course! Sorry for not doing it right away! Here:
Backendless::mapTableToClass("Setting", "MyApp\Setting");
$query = new BackendlessDataQuery();
$query->setWhereClause("key = 'bearer_token'");
$settings = Backendless::$Data->of("Setting")->find($query)->getAsClasses();
if (!(count($settings) > 0)) {
return "No bearer_token found";
}
$token = $settings[0];
$token->value = "new value";
Backendless::$Data->save($token);
This is the code I run, as I said I manage to get the object, update the value to the new and it’s on the last ->save() that fails with this error
Thanks!
Hi again Mark!
I’ve done some more investigation on my part.
This problem only occurs when my objects extends Data (to avoid needing my own setters etc)…
Tobias,
This is exactly the feedback the dev team came back to me with - do not extend the Data class. I am glad you figured it out. I’ll mark this ticket as “Resolved”.
Cheers,
Mark
Mark,
Thanks for the this code. It fixed my issue too. I do however have a question about what “Backendless::$Data->of( ‘Contact’ )->find( $query );” is returning…
I’m doing a little form validation. I have a user table where “username” is set as the “identity” column. If a user tries to register with the same username, I’m trying to build a custom error message. Here is what I’m doing…
// create a new backendless query for checking if the username already exists
$usernameQuery = new BackendlessDataQuery();
// assign the form value for username to variable
$usernameCheck = $input['username'];
// set the where clause for the database query
$usernameQuery->setWhereClause("username = '$usernameCheck'");
// check the database to see if the username already exists
$usernameCheckResult = Backendless::$Data->of( 'Users' )->find( $usernameQuery );
if (isset($usernameCheckResult)) {
return error message...
}
The problem I’m having is even if the username does not already exist, my error message is being sent to the user. So it looks like even if the username doesn’t exist in the database, “$usernameCheckResult” is still getting set to something. So does Backendless::$Data->of( ‘Users’ )->find( $usernameQuery ); return a value even if the query doesn’t find a result? If so, how do I work around this?
Thanks,
Chris
Hi Chris,
The following call:
Backendless::$Data->of( ‘Users’ )->find
will always return a valid collection. The difference is when there are no results in the response, the collection will be empty. Therefore you need to call getAsArray() on $usernameCheckResult and then check its size:
Hope this helps.
Regards,
Mark
Thank you very much for the quick reply. Let me try and get this to work.
Have a great day.
Chris