1
\$\begingroup\$

I wrote this PHP method to update database record sort order after moving a specific record with jQuery UI Sortable in a website. That sort order is stored in a column named order.

I'd like to know if this is SOLID approved or should I split it in more methods, maybe separating the logic that searches for previous, current and next record? I don't know, I'm open for suggestions, thanks!

This code is meant for PHP 5.* and Zend Framework 2.

/**
 * Update records sort order inside a specific Job, after a specific row is moved with jQuery Sortable
 *
 * @param  integer $idJob  
 * @param  integer $idPrevious id of previous record after moving $current
 * @param  integer $idCurrent  id of moved record
 * @param  integer $idNext     id of next record after moving $current
 *
 * @return void
 */
public function sort($idJob, $idPrevious, $idCurrent, $idNext)
{
    if (!$idPrevious && !$idNext) {
        throw new BadMethodCallException('Didn\'t send previous neither next record');
    }

    if (!$idCurrent) {
        throw new BadMethodCallException('Didn\'t send moved record');
    }

    $currentEntity = $this->findById($idCurrent);

    if (!$currentEntity) {
        throw new DomainException('Moved record not found');
    }

    $currentOrder    = $currentEntity->getOrder();
    $currentWentDown = false;
    $currentWentUp   = false;

    // Searches for previous record after moving and identifies if the moved record went down
    if ($idPrevious) {
        $previousEntity = $this->findById($idPrevious);

        if (!$previousEntity) {
            throw new DomainException('Previous record not found');
        }

        $currentWentDown = $previousEntity->getOrder() > $currentOrder;
    }

    // Searches for next record after moving and identifies if the moved record went up
    if ($idNext) {
        $nextEntity = $this->findById($idNext);

        if (!$nextEntity) {
            throw new DomainException('Next record not found');
        }

        $currentWentUp = $nextEntity->getOrder() < $currentOrder;
    }

    // logic to update only the affected records instead of the entire list
    if ($currentWentDown) {
        $currentNewOrder = $previousEntity->getOrder();

        // update all affected records except the moved one
        $this->updateWith(
            ['order' => new Predicate\Expression('order - 1')],
            [
                'id_campanha' => $idJob,
                new Predicate\Between('order', $currentOrder + 1, $previousEntity->getOrder())
            ]
        );

        // update moved record
        $currentEntity->setOrder($currentNewOrder);
        $this->update($currentEntity);

    } elseif ($currentWentUp) {
        $currentNewOrder = $nextEntity->getOrder();

        // update all affected records except the moved one
        $this->updateWith(
            ['order' => new Predicate\Expression('order + 1')],
            [
                'id_campanha' => $idJob,
                new Predicate\Between('order', $nextEntity->getOrder(), $currentOrder - 1)
            ]
        );

        // update moved record
        $currentEntity->setOrder($currentNewOrder);
        $this->update($currentEntity);
    }
}

Briefly explaining about things

  • The class in the example above is a Model, all Models extends AbstractModel
  • findById method is inside AbstractModel, and if not found returns false or if found returns a Entity that is a class used to map a table, so each database column is a property
  • *Entity->getOrder() returns integer
\$\endgroup\$
  • \$\begingroup\$ It might be slightly difficult to answer without seeing more code - e.g. are you able to include the findById() method? And how about the classes used like the class for the currentEntity items? maybe it would be intuitive for ZF users? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Dec 2 '17 at 1:32
  • \$\begingroup\$ @SamOnela I added a few more notes to help understand the code. If you have any more questions let me know. \$\endgroup\$ – Edson Horacio Junior Dec 4 '17 at 18:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.