1

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.

+0

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

+0

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

+0

B'yi A içine referans olarak ayarladığınızda, aynı ayarlayıcı B'nin A için referansını da ayarlayabilir. – Pradeep

cevap

0

Nasıl kendi başlarına eşleştirmeleri işlemek için yeni bir tablo oluşturma hakkında. O zaman bu karmaşıklığı, bunlardan yararlanan nesnelerden uzaklaştırabilirsiniz.

Yani, yeni bir nesne AtoBMappings Sonra

namespace My\DataObject; 

class MyA { 
    /** 
    * @var integer 
    */ 
    private $id; 
    /* 
    * @var text 
    */ 
    private $foo; 
    /** 
    * @var MyAtoB 
    */ 
    private $myAtoB; 
} 

namespace My\DataObject; 

class MyB { 
    /** 
    * @var integer 
    */ 
    private $id; 

    /** 
    * @var AtoBMapperID 
    */ 
    private $myAtoB; 
} 

class MyAtoBMapper { 
    /** 
    * @var myB 
    */ 
    private $myB 

    /** 
    * @var myA 
    ** 
    private $myA 
} 

olabilir yerine Mapper yöntemini hacking, sadece Myb yaratılmasına Mya bir atama yapabilir.

class MyAMapper 
{ 
    ... 
    public function save(MyA $myA) 
    { 

     $myAtoB = new MyAtoBMapper(); 
     //.... instert new myAtoB into DB 

     $data = []; 
     $data['foo'] = [$myA->getFoo()]; 
     $data['myAtoB'] = $myAtoB->getId(); 
     // 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(); 
     $myA->setMyAtoB($newAtoB); 
     $myAtoBMapper->myA = $newId; 
     // common saving stuff #stop# 
     // and only after all that we can save the MyB 
     $myB = $this->myBMapper->save($myB); 
     $myB->setMyAtoB($newAtoB); 
     $myAtoBMapper->myB = $myB; 
     ... 
    } 
} 

Bunun işe yarayacağını düşünüyor musunuz, yoksa bunun çok fazla bir kesmek olduğunu mu düşünüyorsunuz? Ben doğru karmaşıklığı anlamış Bence veritabanında ters inversiyon, nesne ilişkisi etkilemez çünkü

İlgili konular