Search code examples
phpmysqlormpropelpropel2

PHP/Propel delete record 1:n


I've got two tables: step and links joined 1:n. I'm aiming to maintain the links through the step objects. I retrieve all steps from the database and populate the relation with the links table. I persist the step object containing a collection of links to JSON and return it to the front end using REST.

That means that if a step is linked or unlinked to another step in the front end I send the entire step back to the backend including a collection of links. In the back end I use the following code:

public function put($processStep) {
        if (isset($processStep['Processesid']) && isset($processStep['Coordx']) && isset($processStep['Coordy'])) {
            $p = $this->query->findPK($processStep['Id']);

            $p->setId($processStep['Id']);
            $p->setProcessesid($processStep['Processesid']);
            if (isset($processStep['Flowid'])) $p->setFlowid($processStep['Flowid']);
            if (isset($processStep['Applicationid'])) $p->setApplicationid($processStep['Applicationid']);
            $p->setCoordx($processStep['Coordx']);
            $p->setCoordy($processStep['Coordy']);

            $links = $p->getLinksRelatedByFromstep();
            $links->clear();

            foreach ($processStep['Links'] as $link) {
                if (!isset($link['Linkid'])) {
                    $newLink = new \Link();

                    $newLink->setFromstep($link['Fromstep']);
                    $newLink->setTostep($link['Tostep']);

                    $links->prepend($newLink);
                }
            }

            $p->save();

            return $p;
        } else {
            throw new Exceptions\ProcessStepException("Missing mandatory fields.", 1);
        }
    }

I'm basically deleting every link from a step and based upon the request object I recreate the links. This saves me the effort to compare what links are deleted and added. The insert work like a charm Propel automatically creates the new links. Thing is it doesn't delete like it inserts. I've checked the object that is being persisted ($p) and I see the link being deleted but in the MySQL log there is absolutely no action being performed by Propel. It looks like a missing member from the link collection doesn't trigger a dirty flag or something like that.

Maybe I'm going about this the wrong way, I hope someone can offer some advice.

Thanks


Solution

  • Thanks to Ben I got on the right track, an explicit call for a delete is not needed. I came across a function called: setRelatedBy(ObjectCollection o) I use this function to provide a list of related objects, new objects are interpreted as inserts and omissions are interpreted as deletes.

    I didn't find any relevant documentation regarding the problem so here's my code:

    $p = $this->query->findPK($processStep['Id']);
    
                $p->setId($processStep['Id']);
                $p->setProcessesid($processStep['Processesid']);
                $p->setCoordx($processStep['Coordx']);
                $p->setCoordy($processStep['Coordy']);
                if (isset($processStep['Flowid'])) $p->setFlowid($processStep['Flowid']);
                if (isset($processStep['Applicationid'])) $p->setApplicationid($processStep['Applicationid']);
    
                //Get related records, same as populaterelation
                $currentLinks = $p->getLinksRelatedByFromstep();
                $links =  new \Propel\Runtime\Collection\ObjectCollection();
    
                //Check for still existing links add to new collection if so.
                //This is because creating a new Link instance and setting columns marks the object as dirty creating an exception due to duplicate keys
                foreach ($currentLinks as $currentLink) {
                    foreach ($processStep['Links'] as $link) {
                        if (isset($link['Linkid']) && $currentLink->getLinkid() == $link['Linkid']) {
                            $links->prepend($currentLink);
    
                            break;
                        }
                    }
                }
    
                //Add new link objects
                foreach ($processStep['Links'] as $link) {
                    if (!isset($link['Linkid'])) {
                        $newLink = new \Link();
    
                        $newLink->setFromstep($link['Fromstep']);
                        $newLink->setTostep($link['Tostep']);
    
                        $links->prepend($newLink);
                    }
    
                }
    
                //Replace the collection and save the processstep.
                $p->setLinksRelatedByFromstep($links);
                $p->save();