Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReferenceOne with discriminator map #625

Closed
Parad0X opened this issue Jun 29, 2013 · 1 comment
Closed

ReferenceOne with discriminator map #625

Parad0X opened this issue Jun 29, 2013 · 1 comment

Comments

@Parad0X
Copy link
Contributor

Parad0X commented Jun 29, 2013

So ReferenceOne with discriminator map/type doesn't seem to be working. It's not saving the type. This is what my mapping file looks like:

referenceOne:
    model:
        discriminatorField: model_type
        discriminatorMap:
            user: Blah\Bundle\UserBundle\Model\User
            reservation: Blah\Bundle\WebBundle\Model\Reservation

And all I have in the DB is:

{ ... "model" : DBRef("reservations", ObjectId("51cf0b65d0c3f5661000001a")) ... }

model_type is not set.

This is a relevant code from PersistenceBuilder::prepareInsertData

} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
    if ($mapping['isInverseSide']) {
        continue;
    }

    $oid = spl_object_hash($new);

    if ($this->isScheduledForInsert($new)) {
        // The associated document $new is not yet persisted, so we must
        // set $new = null, in order to insert a null value and schedule an
        // extra update on the UnitOfWork.
        $this->uow->scheduleExtraUpdate($document, array(
            $mapping['fieldName'] => array(null, $new)
        ));
    } else {
        $value = $this->prepareReferencedDocumentValue($mapping, $new);
    }
// @EmbedOne
}

If I change it to:

} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
    if ($mapping['isInverseSide']) {
        continue;
    }

    $oid = spl_object_hash($new);

    if ($this->isScheduledForInsert($new)) {
        // The associated document $new is not yet persisted, so we must
        // set $new = null, in order to insert a null value and schedule an
        // extra update on the UnitOfWork.
        $this->uow->scheduleExtraUpdate($document, array(
            $mapping['fieldName'] => array(null, $new)
        ));
    } else {
        $value = $this->prepareReferencedDocumentValue($mapping, $new);
    }

    // Store a discriminator value if the embedded document is not mapped explicitly to a targetDocument
    if (isset($mapping['discriminatorField'])) {
        $insertData[$mapping['discriminatorField']] = $this->getDiscriminatorValue($mapping, $new);
    }

// @EmbedOne
}

and add getDiscriminatorValue private function:

/**
 * Returns discriminator value for a document.
 *
 * @param  array  $mapping
 * @param  object $document
 * @return string
 *
 * @throws RuntimeException If discriminator map doesn't contain an entry for document
 */
private function getDiscriminatorValue(array $mapping, $document)
{
    $refClassName = get_class($document);

    if (isset($mapping['discriminatorMap'])) {
        $key = array_search($refClassName, $mapping['discriminatorMap']);

        if (! $key) {
            throw new \RuntimeException(sprintf(
                'Discriminator map does not contain an entry for %s',
                $refClassName
            ));
        }

        return $key;
    }

    return $refClassName;
}

What do you guys think? Is there a better way to solve this problem? Or am I just missing something?

@Parad0X
Copy link
Contributor Author

Parad0X commented Jul 2, 2013

Submitted a pull request #626 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant