Skip to content

Loading…

DDC-2302: entity not updating with existing \Datetime object #3005

Closed
doctrinebot opened this Issue · 6 comments

2 participants

@doctrinebot

Jira issue originally created by user stijink:

Within an entity i have an method to add days to a subscription. For that an datetime object is modified.

But the database is not going to be updated if an already existing datetime-object is modified an set. It's only working when an freshly created datetime object is used.

NOT WORKING EXAMPLE:

    public function addDaysToSubscription($days) {

        if ($this->hasValidSubscription()) {

            $startFromDate = $this->getSubscriptionValidUntil();
        }
        else {

            $startFromDate = new \DateTime('now');
        }

        $this->setSubscriptionValidUntil($startFromDate->modify('<ins>' . $days .' days'));
    }

WORKAROUND:

    public function addDaysToSubscription($days) {

        if ($this->hasValidSubscription()) {

            $validDate = $this->getSubscriptionValidUntil()->format('Y-m-d H:i:s');
            $startFromDate = new \DateTime($validDate);
        }
        else {

            $startFromDate = new \DateTime('now');
        }

        $this->setSubscriptionValidUntil($startFromDate->modify('</ins>' . $days .' days'));
    }
@doctrinebot

Comment created by @beberlei:

From the documentation (Mapping Objects):

DateTime and Object types are compared by reference, not by value. Doctrine updates this values if the reference changes and therefore behaves as if these objects are immutable value objects.

You have to replace them with a new instance.

@doctrinebot

Comment created by stijink:

Whats the reason for this behaviour ? For me it seem not very intuitive and cost me a couple of hours of project time :)

@doctrinebot

Comment created by @ocramius:

[~stijink] there is no real "global" way of comparing objects in PHP. The only way would be to use a non-strict comparison (aka == vs ===), and that leads to many unexpected problems.

Since DateTime instances are objects like any other, the comparison is applied with ===.

This the safest way to handle this is to work with it as if it was an immutable:

public function setCreationTime(\DateTime $dateTime)
{
    $this->creationTime = clone $dateTime;
}

public function getCreationTime(\DateTime $dateTime)
{
    return clone $this->creationTime;
}

This basically disallows a lot of unexpected behaviors, even when not working with the ORM.

@doctrinebot

Comment created by @beberlei:

Also DateTime objects being mutable was a mistake in PHP, this is why 5.5 will have DateTimeImmutable, which we will switch to if possible in the future :)

@doctrinebot

Comment created by @beberlei:

Change to 'Invalid'

@doctrinebot

Issue was closed with resolution "Invalid"

@beberlei beberlei was assigned by doctrinebot
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.