Bu yazıda doctrine'nin cascade={"persist"} özelliğinin nerede ve ne zaman kullanılacağını veya kullanılmayacağını öğreneceğiz.


Ön bilgi


İlişkilerin her iki tarafında ("inverse" ve "owning") cascade={"persist"} özelliğinin kullanılması tavsiye edilmez ama kullanırsanız da problem olmaz. Genel olarak "inverse" tarafta kullanılır, yani mappedBy özelliğinin tanımlandığı taraf. Buna "parent/independent" tarafta diyebilirsiniz. Elimizde League 1-n Team (OneToMany) şeklinde bir ilişki olduğunu varsayarsak, "inverse" taraf League olacaktır.


Yapı


class League
{
/**
* @ORM\OneToMany(targetEntity="Team", mappedBy="league")
*/
private $teams;

public function __construct()
{
$this->teams = new ArrayCollection();
}
}

class Team
{
/**
* @ORM\ManyToOne(targetEntity="League", inversedBy="teams")
* @ORM\JoinColumn(name="league_id", referencedColumnName="id", nullable=false)
*/
private $league;
}

Örnek


Cascade 1) Cascade yok


Bu gibi durumlarda, persist işlemi her iki entity üzerinde manuel olarak yapıIır.


League: @ORM\OneToMany(targetEntity="Team", mappedBy="league")
Team: @ORM\ManyToOne(targetEntity="League", inversedBy="teams")

$league = new League();
$team = new Team();

// add or set Team in League
// add or set League in Team

$entityManager->persist($league);
$entityManager->persist($team);
$entityManager->flush();

Cascade 2) Cascade League


Bu gibi durumlarda, persist işlemi sadece League üzerinde manuel olarak yapıIır. Team üzerinde manuel olarak işlem yapmaya gerek yok ama yaparsanızda herhangi bir problem çıkmaz.


League: @ORM\OneToMany(targetEntity="Team", mappedBy="league", cascade={"persist"})
Team: @ORM\ManyToOne(targetEntity="League", inversedBy="teams")

$league = new League();
$team = new Team();

// add or set Team in League
// add or set League in Team

$entityManager->persist($league);
$entityManager->persist($team); // Unnecessary
$entityManager->flush();

Cascade 3) Cascade Team


Bu gibi durumlarda, persist işlemi sadece Team üzerinde manuel olarak yapıIır. League üzerinde manuel olarak işlem yapmaya gerek yok ama yaparsanızda herhangi bir problem çıkmaz.


League: @ORM\OneToMany(targetEntity="Team", mappedBy="league")
Team: @ORM\ManyToOne(targetEntity="League", inversedBy="teams", cascade={"persist"})

$league = new League();
$team = new Team();

// add or set Team in League
// add or set League in Team

$entityManager->persist($league); // Unnecessary
$entityManager->persist($team);
$entityManager->flush();

Cascade 4) Cascade League ve Team


Bu gibi durumlarda, persist işlemi ya League ya da Team üzerinde manuel olarak yapıIır. Her ikisi üzerinde manuel olarak işlem yapmaya gerek yok ama yaparsanızda herhangi bir problem çıkmaz.


League: @ORM\OneToMany(targetEntity="Team", mappedBy="league", cascade={"persist"})
Team: @ORM\ManyToOne(targetEntity="League", inversedBy="teams", cascade={"persist"})

$league = new League();
$team = new Team();

// add or set Team in League
// add or set League in Team

$entityManager->persist($league); // Either this
$entityManager->persist($team); // or this
$entityManager->flush();

Sonuç


Persist işlemini cascade={"persist"} özelliğini kullanan entity üzerinde yapmak yeterli olacaktır, o nedenle diğer entity es geçilebilir ama, aynı ilişkide her iki entity için cascade={"persist"} özelliği ayarlanırsa, her iki entity üzerinde persist işlemi yapabilirsiniz.


Genel hata


Persist işlemi yaparken, şu şekilde bir hata mesajı alabilirsiniz (genelde ilişkilerde cascade={"persist"} özelliğinin kullanmayı unuttuğunuzda olur): A new entity was found through the relationship 'League#teams' that was not configured to cascade persist operations for entity: Team@000000006fefb0fd00007fa33b3653bf. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ORM\...(..,cascade={"persist"}).. Mesajdaki bilinmeyen (unknown) diye geçen entity Team olanıdır. Sizden istenen, ya $entityManager->persist($team); komutunun çalıştırılması, ya da o andaki persist işleminin yapıldığı League üzerinde cascade={"persist"} özelliğinin ektinleştirilmesidir.


# As you can see below, our mapping is missing cascade property

League: @ORM\OneToMany(targetEntity="Team", mappedBy="league")
Team: @ORM\ManyToOne(targetEntity="League", inversedBy="teams")

$league = new League();
$team = new Team();

// add or set Team in League
// add or set League in Team

$entityManager->persist($league);
// $entityManager->persist($team); // -> You forgot to use this so either enable it or just add cascade={"persist"} to League entity
$entityManager->flush();