Nadir Miralimov
Nadir Miralimov

Reputation: 58

How to flush one entity without flushing another using Dcotrine?

How can I flush only one entity without flushing other entities?

For example: I have 2 objects BStatus and B. They are related by OneToOne relation. I want to do some work on B without saving it to DB but save the status of the work on BStatus so another process can read it.

class B {

    /**
     * @var int
     * @ORM\Column(type="integer")
     */
    public $i = 0;

    /**
     * @var BStatus
     * @ORM\OneToOne(targetEntity="BStatus", inversedBy="b")
     */
    public $status;

    /**
     * B constructor.
     */
    public function __construct() {
        $this->status = new BStatus($this);
    }

    public function count() {
        return $this->i++;
    }
}

class BStatus {
    /**
     * @var float
     * @ORM\Column(type="float")
     */
    public $progress = 0;

    // <UPDATED>
    /**
     * @var B
     * @ORM\OneToOne(targetEntity="B", mappedBy="status")
     */
    public $progress = 0;
    // </UPDATED>

    /**
     * BStatus constructor.
     * @param B $b
     */
    public function __construct(B $b)
    {
        $this->b = $b;
    }
}


$b = // Load from DB

$max = 100;

for ($i = 0; $i < $max; $i++) {
    $num = $b->count();
    $b->getStatus()->setProgress(($num + 1) / $max);
    // Here I want to save the status
}

// Here I want to save $b

Update BStatus have pointer to B.

Update 2

Tried to detach B, flush and merge B back.

for ($i = 0; $i < $max; $i++) {
    $num = $b->count();
    $status = $b->getStatus();
    $status->setProgress(($num + 1) / $max);

    $em->detach($b);
    $em->flush();
    $em->merge($b);
}

Got execption:

 'Doctrine\ORM\ORMInvalidArgumentException' with message 'A new entity was found through the relationship BStatus#b' that was not configured to cascade persist operations for entity: local. 
To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).'

Upvotes: 2

Views: 1129

Answers (2)

Cerad
Cerad

Reputation: 48865

$em->flush($b);

Will only flush the specified entity. Does not look like the online documents show this feature but a peak at actual code shows it has been these since at least Doctrine 2.4.

Upvotes: 2

Arthur
Arthur

Reputation: 2889

You can detach object from unit of work

$em->detach($instanceOfB)

Upvotes: 0

Related Questions