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

BUG: Changes to persistent objects are not stored in session #3346

Open
1 task done
cornerfarmer opened this issue May 1, 2024 · 1 comment
Open
1 task done

BUG: Changes to persistent objects are not stored in session #3346

cornerfarmer opened this issue May 1, 2024 · 1 comment
Labels

Comments

@cornerfarmer
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

If you store an object, that is persisted, in the session, only the reference to the object is actually stored and all modifications are lost between requests.

Expected Behavior

In the docu it says Persistent objects which are modified are fully stored in the session. (https://flowframework.readthedocs.io/en/stable/TheDefinitiveGuide/PartIII/SessionHandling.html).
This would also be the expected behavior, which is necessary for example if you want to edit an object across multiple requests in the session and only in the end write it into the database.

Steps To Reproduce

The entity class:

<?php
declare(strict_types=1);

namespace MyCompany\MyPackage\Domain\Model;

use Doctrine\ORM\Mapping as ORM;
use Neos\Flow\Annotations as Flow;
/**
 *
 * @Flow\Entity
 */
 class Number {

    /**
     * @ORM\Column(length=50, nullable=true)
     * @var int
     */
    public $value;

 }

The session class:

<?php
declare(strict_types=1);

namespace MyCompany\MyPackage\Domain\Session;

use Neos\Flow\Annotations as Flow;
use MyCompany\MyPackage\Domain\Model\Number;

/**
 * @Flow\Scope("session")
 */
class SessionTest
{
    /**
     * The user which corresponds to this settings container
     *
     * @var Number
     */
    protected $number;


    /**
     * @Flow\Session(autoStart = true)
     * @param Number $number
     */
    public function setSessionNumber(Number $number)
    {
        $this->number = $number;
    }
    
    /**
     * @return Number
     */
    public function getSessionNumber()
    {
        return $this->number;
    }

}

Now in the first request:

// Create new number object
$number = new Number();
$number->value = 5;

// Persist it
$this->numberRepository->add($number);
$this->persistenceManager->persistAll();

// Set it in the session
$this->sessionTest->setSessionNumber($number);

In the second request:

// Change the number only in the session
$number = $this->sessionTest->getSessionNumber();
$number->value = 6;

In the third request:

// Read the number 
$number = $this->sessionTest->getSessionNumber();
echo $number->value;

This outputs 5, not as expected 6!

If you dont persist the object in the first request, the output is 6, as expected.

Environment

- Flow: 8.3
- PHP: 8.2

Anything else?

In the serialization, the object only is fully serialized if it is not persited:

if ($this->$propertyName instanceof DoctrineProxy || ($this->$propertyName instanceof PersistenceMagicInterface && !Bootstrap::$staticObjectManager->get(PersistenceManagerInterface::class)->isNewObject($this->$propertyName))) {

Before #2700, there was a workaround, that if one creates a copy of the PHP object (same PID), then this copied object would be fully serialized.

Is there now any possibility to store a modified persted object in session, except creating a temporary copy with new PID?

@kitsunet
Copy link
Member

kitsunet commented May 2, 2024

Thanks for opening this report, you are correct that this is the current behavior. I wasn't aware of the discrepancy in the documentation and I am actually not aware when the described behavior was ever the one actually implemented (apart from new objects).

The problem is that the behavior you would like is inherently dangerous in that there could be write operations to this entity in the meantime which would be fully overwritten by the entity from the session. I think it would be much safer to only store the "changes" in session then load the current state of the entity at the end and apply the (session stored) changes to it.

Implementationwise that would mean a change object which is not an entity that has a relation to the respective entity. and storing this change object in the session.

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

No branches or pull requests

2 participants