parse-community / parse-php-sdk

The PHP SDK for Parse Platform
https://parseplatform.org/
Other
811 stars 346 forks source link

Issue removing ParseObject from ParseRelation #439

Closed jschwartzmtn closed 5 years ago

jschwartzmtn commented 5 years ago

In the code below, I have an array of objectId's from my _User class ($_POST["crew"]). After getting the relation I query the relation to check for these users, and if those users are in the PFRelation, I remove them.

For some reason when I do this I'm getting an uncaught internal server error on Parse Server. If I comment out the lines where remove() is called, I don't get the exception. If I run this with all of the code live, no errors are thrown by ParseException, but the users are not removed. Is this something I am doing wrong? It seems pretty straight forward, but I can't get it working.

if (isset($_POST["submit"]) && isset($_POST["jobId"]) && isset($_POST["crew"])) {                
            try {
                $query = new ParseQuery("Job");
                $query->includeKey("unsignedCrew");
                $query->includeKey("signedCrew");
                $job = $query->get($_POST['jobId']);

                $unsignedCrewRelation = $job->getRelation("unsignedCrew", "_User");
                $unsignedQuery = $unsignedCrewRelation->getQuery();
                $unsignedQuery->containedIn("objectId", $_POST["crew"]);
                $unsignedCrewToRemove = $unsignedQuery->find();
                if (count($unsignedCrewToRemove) > 0) {
                    $unsignedCrewRelation->remove($unsignedCrewToRemove);
                }

                $signedCrewRelation = $job->getRelation("signedCrew");
                $signedQuery = $signedCrewRelation->getQuery();
                $signedQuery->containedIn("objectId", $_POST["crew"]);
                $signedCrewToRemove = $signedQuery->find();
                if (count($signedCrewToRemove) > 0) {
                    $signedCrewRelation->remove($signedCrewToRemove);
                }

                $job->save();
                $errors = array();
                $successString = "Crew members removed successfully!";
                header('location:view.php?success=' . $successString);
            } 
            catch (ParseException $error) {
                header('location:view.php?exception=' . $error->getMessage());
            }

 }

It's also worth mentioning, that in the course of troubleshooting this, I've done a var_dump on every variable I created and all come back as expected.

dplewis commented 5 years ago

Can you write a failing test? I believe this could all be done simpler without the unnecessary querying. Also your doing includeKey on a relation. IncludeKey is for pointers.

jschwartzmtn commented 5 years ago

Right you are, I added the includeKey after running out of good ideas and hoping there was something missing from the documentation.

How would I go about removing objects without querying? It is my understanding that with relations, you have to add and remove ParseObjects, it is not enough to just have their objectIds. Am I wrong in that?

dplewis commented 5 years ago

Fork the project, create a branch and write a test here then we both can look into it.

If you need help running test refer to the CONTRIBUTING.md

jschwartzmtn commented 5 years ago

Unfortunately I don't have the time to get into that at the moment - this is setup on a hosted Parse Server that I don't have access to alter configuration for, so migrating it would be a process. I refactored my code a little and using this function, I have the same issue (as expected, since I really didn't change the process at all, just made it cleaner):

    function removeRelation(ParseObject $parent, string $field, array $objectIds) {
        $relation = $parent->getRelation($field, '_User');
        $query = $relation->getQuery();
        $query->containedIn('objectId', $objectIds);
        $objectsToRemove = $query->find();
        if (!empty($objectsToRemove)) {
            $relation->remove($objectsToRemove);
        }
    }
dplewis commented 5 years ago

Are objects getting returned when you do your query?

    function removeRelation(ParseObject $parent, string $field, array $objectIds) {
        $relation = $parent->getRelation($field, '_User'); <------ Second parameter is optional.
        $query = $relation->getQuery();
        $query->containedIn('objectId', $objectIds);
        $objectsToRemove = $query->find(); <-------------- HERE
        if (!empty($objectsToRemove)) {
            $relation->remove($objectsToRemove);
        }
    }
jschwartzmtn commented 5 years ago

Yes, if I do

echo var_dump($objectsToRemove);

I get an array of ParseObjects. The results are as expected, an array of the objects in the relation that are also in $objectIds. I have also tried it with and without specifying the class in getRelation(), same result both ways.

dplewis commented 5 years ago

@jschwartzmtn I added a test https://github.com/parse-community/parse-php-sdk/pull/440 It passes locally for me. Compare it to what you have been doing, or change the test

jschwartzmtn commented 5 years ago

Thanks, that does look to test exactly what I am doing. Perhaps there is an issue with my hosted server, I will address this with the hosting company. Thank you for all your help!

dplewis commented 5 years ago

I'm getting an uncaught internal server error on Parse Server.

Can you post logs? VERBOSE=1

jschwartzmtn commented 5 years ago

2019-04-10T15:00:26.908Z - Uncaught internal server error. 2019-04-10T15:00:26.907Z - Error generating response. TypeError: Cannot read property 'className' of undefined at getObjectType (/usr/src/app/node_modules/parse-server/lib/Controllers/SchemaController.js:1056:38) at getObjectType (/usr/src/app/node_modules/parse-server/lib/Controllers/SchemaController.js:1059:16) at getType (/usr/src/app/node_modules/parse-server/lib/Controllers/SchemaController.js:977:14) at SchemaController.validateObject (/usr/src/app/node_modules/parse-server/lib/Controllers/SchemaController.js:783:24) at loadSchema.then.then (/usr/src/app/node_modules/parse-server/lib/Controllers/DatabaseController.js:384:21) at process._tickDomainCallback (internal/process/next_tick.js:135:7)

jschwartzmtn commented 5 years ago

Nevermind, I think I finally tracked it down to a mismatch in the version of Parse Server and the SDK I was using. I updated both to the latest version and it is working now. Thanks again for your help, I knew it was something silly!

dplewis commented 5 years ago

Glad you got it working!