1

ドクトリン エンティティを ZF2 フォームに抽出する際に問題が発生しています。私はZF2とDoctrineの両方にかなり慣れていません(クラステーブルの継承も同様です)。ZF2 と Doctrine のほぼすべてのドキュメントを読みましたが、これを機能させる方法がまだわかりません。

システムを簡単に説明すると、ポリシーと呼ばれる主要なエンティティがあります。Policy エンティティには、Proposer エンティティと PolicyProduct エンティティ、およびその他のいくつかの列が含まれます。

私は PolicyProduct エンティティで Class Table Inheritance を使用しています。これは、3 つの異なる製品タイプがあり、それぞれに異なるデータが必要であるためです。3 つの製品エンティティは、TouringCaravan、StaticCaravan、および Parkhome です。

Policy エンティティは、1 つの Proposer と 1 つの PolicyProduct のみを持つことができます。

すべてのエンティティには、列ごとに getter メソッドと setter メソッドがあります。

表示されているフォームには、Policy エンティティと PolicyProduct エンティティの両方のフィールドが含まれています。

フォームを表示するには、まずポリシー エンティティとポリシー フィールドセットを取得します。次に、ポリシー フィールドセットをベースとして設定します。

$policyEntity = $entityManager->getRepository('Policy\Entity\Policy')->find($policyId);
$policyFieldset = $formElementManager->get('policy_form_policy_fieldset');
$policyFieldset->setUseAsBaseFieldset(true);

次に、PolicyProduct 固有のフィールドセットを取得し、それを policyFieldset に追加します。

eg
$productFieldset = $formElementManager->get('tourers_form_touring_fieldset');
$policyFieldset->add($productFieldset);

次に、policyFieldset をフォームに追加し、それを Policy エンティティにバインドして、完成したフォームを返します。

$productForm->add($policyFieldset);
$productForm->bind($policyEntity);
return $productForm;

注目すべきは、DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator各フィールドセットのハイドレーターとして を使用していることです。init()次に、各フィールドセットのメソッド内で次を呼び出します 。

// Example from PolicyFieldset
$hydrator = new DoctrineHydrator($this->objectManager,true);

$this->setHydrator($hydrator)
     ->setObject(new Policy());

フォームに入力してデータベースに保存すると、データがテーブルに正しく保存されていることがわかります。その後、エンティティで同じフォームをハイドレートしようとすると、PolicyProduct エンティティの値がマップされません。ただし、ポリシー エンティティの値は正しくハイドレートされます。

ダンプする$policyEntity->getPolicyProduct()と、すべてのデータが表示されます。つまり、エンティティが情報を正しく保存および取得していることを意味します。問題は、エンティティ データをフォーム フィールドセットに抽出しようとしたときに発生するようです。

これが理にかなっていることを願っていますが、そうでない場合はお知らせください。明確にしようと思います。

ありがとう


ここに主なエンティティがあります

ポリシー

namespace Policy\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="policy")
*/
class Policy {

   /**
    * @ORM\Id
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    /**
    * @ORM\ManyToOne(targetEntity="Proposer\Entity\Proposer", inversedBy="policy")
    * @ORM\JoinColumn(name="proposer_id", referencedColumnName="id")
    *
    protected $proposer;

    /**
    * @ORM\ManyToOne(targetEntity="Product")
    * @ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="RESTRICT")
    */
    protected $product;

    /**
    * @ORM\OneToOne(targetEntity="Policy\Entity\PolicyProduct")
    * @ORM\JoinColumn(name="policy_product_id", referencedColumnName="id")
    */
    protected $policyProduct;

    /**
    * @ORM\ManyToOne(targetEntity="PolicyStatus")
    * @ORM\JoinColumn(name="policy_status_id", referencedColumnName="id", onDelete="RESTRICT")
    */
    protected $policyStatus;

    /**
    * @ORM\Column(name="policyInception", type="date", nullable=true)
    */
    protected $policyInception;

    // Omitted getters and setters

}

ポリシー製品

namespace Policy\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name="policy_product")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="productDiscriminator", type="integer")
* @ORM\DiscriminatorMap({1 = "Tourers\Entity\TouringCaravan", 2 = "Statics\Entity\StaticCaravan", 3 = "Parkhomes\Entity\Parkhome"})
*/

class PolicyProduct {

    /**
    * @ORM\Id
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    // Omitted getters and setters
}

TouringCaravan - PolicyProduct 継承テーブルの例

namespace Tourers\Entity;

use Doctrine\ORM\Mapping as ORM;
use Policy\Entity\PolicyProduct;

/**
* @ORM\Entity
* @ORM\Table(name="touring_caravan")
*/

class TouringCaravan extends PolicyProduct {

    /**
    * @ORM\Id
    * @ORM\Column(type="integer")
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    /**
    * @ORM\OneToOne(targetEntity="Policy\Entity\Policy")
    * @ORM\JoinColumn(name="policy_id", referencedColumnName="id")
    */
    protected $policy;

    /**
    * @ORM\ManyToOne(targetEntity="TouringCaravanMake")
    * @ORM\JoinColumn(name="touring_caravan_make", referencedColumnName="id", onDelete="RESTRICT")
    */
    protected $caravanMake;

    /**
    * @ORM\Column(name="caravanModel", type="string", length=128, unique=false, nullable=false)
    */
    protected $caravanModel;

    ....
    Lots more columns specific to the TouringCaravan Entity

    // Omitted getters and setters
}
4

1 に答える 1

0

ここにあるエンティティが多すぎるようです。あなたが何をしようとしているのか理解できれば、各ポリシーは、TouringCaravan、StaticCaravan、または Parkhome のいずれかになる製品の単一の「クラス」に関連付けられています。その場合、discriminator 列は Policy エンティティに属し、PolicyProduct enitiy は削除できます。やりたいことは次のとおりです。

1) でこの変更を行いPolicy\Entity\Policyます:

// ... //

/**
* @ORM\Entity
* @ORM\Table(name="policy")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="policyProduct", type="integer")
* @ORM\DiscriminatorMap({1 = "Tourers\Entity\TouringCaravan", 2 = "Statics\Entity\StaticCaravan", 3 = "Parkhomes\Entity\Parkhome"})
*/
class Policy {

// ... //

これを削除します:

/**
* @ORM\OneToOne(targetEntity="Policy\Entity\PolicyProduct")
* @ORM\JoinColumn(name="policy_product_id", referencedColumnName="id")
*/
protected $policyProduct;

1a) ここにいる間に、DocBlock for $proposerwithをエスケープする必要があります*/

2) 削除しPolicy\Entity\PolicyProductます。

Tourers\Entity\TouringCaravan3)および他のすべての子エンティティでこの変更を行います。

// ... //

class TouringCaravan extends Policy {

// ... //

4) ID の名前を変更することを検討してください。各エンティティには独自の ID があり、それらがすべて $id と呼ばれていると、どれがどれであるかを簡単に見失います。Product エンティティの ID が$product_idで、TouringCaravan エンティティの ID が$touring_caravan_idなどの場合、識別が容易になります。テーブルとエンティティの両方の ID に一意のわかりやすい名前を割り当てます。マッピング ステートメントをいくつか作成するのを忘れた場合、Doctrine が接続を作成してくれることがあります。

5)。Tourers\Entity\TouringCaravanおよび他の子エンティティから生成された子 ID を削除し、データベースにテーブル内の値を生成させることを検討してください。あるエンティティが別のエンティティを拡張し、JOIN に 2 つの autonumber 列がある場合、Doctrine はそれを好まないことがわかりました。

ここでは、共有したことよりも多くのことが行われているため (Proposer エンティティと PolicyStatus エンティティ)、これらの提案がすべての問題を解決するかどうかはわかりませんが、それは始まりです.

あなたの質問とは関係のない別の提案:

識別子の列を整数ではなく文字列に変更し、そこに製品の説明文を記録することを検討してください。それ以外の場合は、さらに別のエンティティを作成するか、配列をハード コードして、1 = TouringCaravan、2 = StaticCaravan、3 = Parkhome であることを示す必要があります。また、ポリシー テーブルにテキストを記録すると、必要に応じてデータ テーブルを読みやすくなり、単一のエンティティからインデックス ビューを作成しやすくなります。

于 2014-04-25T21:55:09.110 に答える