Zend\Form\Fieldset
s ve Zend\Form\Collections
s yuvalanmış olabilir ve daha fazla veya daha az otomatik olarak form girişinden bir comlete nesnesi (kaydedilmeye hazır) almak için karmaşık nesne yapıları onları eşleştirmek için çok rahat bir yol sağlar. Form Collections tutorial çok iyi bir örnek sağlar.Veritabanı ve ZF2 uygulamasında farklı referans yönleri nasıl ele alınır?
Şu anda sahip olduğum vaka, bir referans inversiyon içerdiğinden, biraz daha karmaşıktır. Bunun anlamı şudur:
İki varlık vardır - MyA
ve MyB
ve veritabanında aralarındaki ilişki mya.id
için myb.mya_id
den FOREIGN KEY
olarak uygulanır ise, uygulama ters referanslamaya kullanıyor:
MyA has MyB
Ya bazı kodla:
namespace My\DataObject;
class MyA {
/**
* @var integer
*/
private $id;
/*
* @var text
*/
private $foo;
/**
* @var MyB
*/
private $myB;
}
namespace My\DataObject;
class MyB {
/**
* @var integer
*/
private $id;
/*
* @var text
*/
private $bar;
/*
Actually it's even bidirectional, but it's not crucial for this issue.
For this problem it's not important,
wheter the class MyB has a property of type MyA.
We get the issue already,
when we define a property of type MyB in the class MyA.
Since the direction of the reference MyA.myB->MyB differes
from the direction of the reference my_b.my_a.id->my_a.id.
*/
/**
* @var MyA
*/
// private $myA;
}
Benim Mapper
nesneler DataObject
s argüman olarak geçmiş olsun: MyAMapper#save(MyA $object)
ve MyBMapper#save(MyB $object)
. demektir
namespace My\Mapper;
use ...
class MyAMapper
{
...
public fuction save(MyA $object)
{
// save the plain MyA propertis a new entry in the my_a table
...
$myMapperB->save($myA->getMyB());
}
}
namespace My\Mapper;
use ...
class MyBMapper
{
...
public fuction save(MyB $object)
{
// save the plain MyB propertis a new entry in the my_b table
...
}
}
,
MyAMapper#save(...)
evrything
my_a
masaya
MyA
nesneyi kurtarmak için gerekli vardır. Ancak
MyBMapper
'da
my_b.my_a_id
verileri eksik olacaktır.
Ve ayrıca (MyBMapper#save(...)
için my_b.my_a_id
için veri aktarmak için sırayla) MyA#MyB#MyA
doldurmak için MyAFieldset
içine daha sonra iç içe bir fieldset MyBFieldset
ve yuva fieldset MyBFieldset
ile bir alan kümesi MyAFieldset
oluşturamazsınız:
class MyAFieldset {
$this->add([
'name' => 'my_b',
'type' => 'My\Form\Fieldset\MyBFieldset',
'options' => []
]);
}
class MyBFieldset {
$this->add([
'name' => 'my_a',
'type' => 'My\Form\Fieldset\MyAFieldset',
'options' => []
]);
}
Bu, tekrarlayıcı bir bağımlılığa neden olur ve işe yaramaz.
Uygulama düzeyindeki başvuru yönü, veritabanındaki yönünden farklı olduğunda, nasıl kullanılır? Tam bir ("kurtarılmaya hazır") nesne sağlayan bir alan yapıları nasıl oluşturulur? Belki de,
class MyConrtoller {
...
public function myAction() {
$this->myForm->bind($this->myA);
$request = $this->getRequest();
$this->myForm->setData($request->getPost());
// here the hack #start#
$this->myB->setMyA($this->myA);
// here the hack #stop#
$this->myAService->saveMyA($this->myA);
}
}
Well:
Çözüm 1 bir şekilde işlenir
, bir başka MyA
nesne oluşturulur ve MyB
nesneye eklenebilir formda var denetleyicide değil, mapper bunun için daha iyi bir yer olabilir:
class MyAMapper
{
...
public function save(MyA $myA)
{
$data = [];
$data['foo'] = [$myA->getFoo()];
// common saving stuff #start#
$action = new Insert('my_a');
$action->values($data);
$sql = new Sql($this->dbAdapter);
$statement = $sql->prepareStatementForSqlObject($action);
$result = $statement->execute();
$newId = $result->getGeneratedValue()
// common saving stuff #stop#
...
// hack #start#
if(! $myA->getB->getA()) {
$myA->getB->setA(new MyA());
$myA->getB->getA()->setId($newId);
}
// hack #stop#
// and only after all that we can save the MyB
$myB = $this->myBMapper->save($myB);
$myA->setMyB($myB);
...
}
}
Ama yine de sadece bir kesmek.
Geçici çözüm 2
MyB
sınıf bir özellik $myAId
alır. Ama aynı zamanda temiz bir yol değil.
MyBFieldset
Çözüm 3 alt fieldset olarak MyAFieldsetFake
alır.
class MyAFieldset {
...
public function init()
{
$this->add([
'type' => 'text',
'name' => 'id',
'options' => [...],
]);
$this->add([
'type' => 'text',
'name' => 'foo',
'options' => [...],
]);
}
}
class MyAFieldset {
...
public function init()
{
$this->add([
'type' => 'text',
'name' => 'id',
'options' => [...],
]);
$this->add([
'type' => 'text',
'name' => 'bar',
'options' => [...],
]);
$this->add([
'type' => 'text',
'name' => 'foo',
'type' => 'My\Form\Fieldset\MyAFakeFieldset',
'options' => [...],
]);
}
}
class MyAFieldset {
...
public function init()
{
$this->add([
'type' => 'text',
'name' => 'id',
'options' => [...],
]);
}
}
Ama sahte nesneler de biraz kirli: Bu fieldset sınıfı sadece MyA
veri nesnesi için ID
içeren, ardından MyAFieldset
sadece "sığ" kopyasıdır.
Ben emin değilim. Eğer her ilişkinin bir sahip ve ters taraf olduğu doktrini okuyabiliyorsanız, gerçek veritabanı ilişkisini belirtin. Benim düşünceme göre temiz bir uygulama, nesne ilişkilerini nasıl görüyorsunuz. MyA myB'ye sahip olduğundan, myA hem myA hem de myB nesnelerini kaydetmek için seçilebilir. – Pradeep
Yorumunuz için teşekkürler! Aslında önemli bir zihinsel adımı açıklamadım. Sadece soruyu güncelledi. Sorunu şimdi anladın mı? – automatix
B'yi A içine referans olarak ayarladığınızda, aynı ayarlayıcı B'nin A için referansını da ayarlayabilir. – Pradeep