1

I am trying to build a function that allow me insert|update new entities but I have a problem trying to apply DRY principle of software development, aimed at reducing repetition of information of all kinds. This is what I have:

foreach ($data as $row) {
        $entity = $this->_em->getRepository('PDOneBundle:Target')->findOneBy(
            array('veeva_account_id' => $row['Id'])
        );

        $lastModifiedAt = new \DateTime($row['LastModifiedDate']);

        // Constraints
        if ($row['Id'] != null && $row['FirstName'] != null && $row['LastName']) {
            // CREATE
            if (!is_object($entity)) {
                $entity = new Entity\Target();
                $entity->setVeevaAccountId($row['Id']);

                $entity->setVeevaAccountId($row['Id']);
                $entity->setNpi($row['NPI_vod__c']);
                $entity->setFirst(ucfirst(strtolower($row['FirstName'])));
                $entity->setLast(ucfirst(strtolower($row['LastName'])));
                $entity->setTitle($row['Title__c']);
                $entity->setDisplayName(
                    ucfirst(strtolower($row['FirstName'])).' '.ucfirst(
                        strtolower($row['LastName'])
                    )
                );
                $entity->setLastSyncAt(new \DateTime());

                // Persisting the current user
                $this->_em->persist($entity);

                // Each 1000 items persisted we flush everything
                if (($i % $this->_batchSize) === 0) {
                    echo 'Flushing batch...'."\n";
                    echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";

                    $this->_em->flush();
                    $this->_em->clear();

                    echo 'After batch...'."\n";
                    echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";
                }
                ++$i;
            }

            $lastSyncAt = $entity->getLastSyncAt();

            // UPDATE
            if ($lastModifiedAt > $lastSyncAt) {
                // Updating info
                $entity->setVeevaAccountId($row['Id']);
                $entity->setNpi($row['NPI_vod__c']);
                $entity->setFirst(ucfirst(strtolower($row['FirstName'])));
                $entity->setLast(ucfirst(strtolower($row['LastName'])));
                $entity->setTitle($row['Title__c']);
                $entity->setDisplayName(
                    ucfirst(strtolower($row['FirstName'])).' '.ucfirst(
                        strtolower($row['LastName'])
                    )
                );
                $entity->setLastSyncAt(new \DateTime());

                // Persisting the current user
                $this->_em->persist($entity);

                // Each 1000 items persisted we flush everything
                if (($i % $this->_batchSize) === 0) {
                    echo 'Flushing batch...'."\n";
                    echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";

                    $this->_em->flush();
                    $this->_em->clear();

                    echo 'After batch...'."\n";
                    echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";
                }
                ++$i;
            }
        }
    }

As you may notice this piece of code:

$this->_em->persist($entity);

// Each 1000 items persisted we flush everything
if (($i % $this->_batchSize) === 0) {
    echo 'Flushing batch...'."\n";
    echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";

    $this->_em->flush();
    $this->_em->clear();

    echo 'After batch...'."\n";
    echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";
}
++$i;

Is present twice, then what comes to my mind is check if Doctrine has something to persist|flush and then get out the code and put below the conditionals but I don't know if that is possible either how, so any advices?

PS: Code logic changes are welcome, feel free to make me suggestions in order to achieve the same and improve my code

ReynierPM
  • 17,594
  • 53
  • 193
  • 363
  • 2
    Have a look at this answer, it might point you in the right direction: http://stackoverflow.com/questions/9057558/is-there-a-built-in-way-to-get-all-of-the-changed-updated-fields-in-a-doctrine-2 – Darragh Enright Jun 24 '15 at 13:28
  • 1
    Try prePersist or preUpdate events – Pi Wi Jun 24 '15 at 13:54

1 Answers1

2

Like mentioned in the comments you could make use of doctrines prePersist/preUpdate events (documentation: http://doctrine-orm.readthedocs.org/en/latest/reference/events.html).

If you just want to keep it DRY, I can also recommend you a function like this:

protected function flushBatch($em, $counter, $batchSize) {
    if (($counter % $batchSize) === 0) {
        echo 'Flushing batch...'."\n";
        echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";

        $em->flush();
        $em->clear();

        echo 'After batch...'."\n";
        echo 'Memory: '.$this->getReadableSize(memory_get_usage())."\n";
    }
}

Obviously this is only a recommendation if you dont need the logic anywhere else in your project.

NiMeDia
  • 995
  • 1
  • 15
  • 27