EC-CUBE4に新規テーブルを加えて既存テーブルとリレーションさせ、Joinして出力させたいと思っています。開発環境はwindows10、xamppのバージョンは7.4.23、PHPは7です。
しかし、リポジトリからJoin文を発行してもうまく認識してくれません。
連携の手順が間違っているのかと思い、文法や前準備の手順の確認をお願いしようと思います。
連携の手順
CustomerエンティティとCustomerRankエンティティを用意。
CustomerとCustomerRankは1:1関係。CustomerのidとCustomerRankのcustomer_id
両方のentityの中に以下を書き込む
####Customer
エンティティの設定
- indexesで外部キーを設定。INDEX(name="〇〇"はDBに登録されたキー名。columns={"カラム名"}),
※上の理解は正しいか?
- @ORM\Entity(repositoryClass="Customerエンティティ用のリポジトリのパス"
※一つだけしか指定できないか?
/** * Customer * * @ORM\Table(name="dtb_customer", uniqueConstraints={@ORM\UniqueConstraint(name="secret_key", columns={"secret_key"})}, indexes={@ORM\Index(name="dtb_customer_buy_times_idx", columns={"buy_times"}),(中略)) * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255) * @ORM\HasLifecycleCallbacks() * @ORM\Entity(repositoryClass="Customize\Repository\CustomerRepository") */
プロパティの設定
- joinする予定のカラムの真下にリレーションの設定を書く。
- targetEntityはCustomize\もしくはEccube\から始まる連携先エンティティへのパスを書く、で正しいか。パスを書く際にはUSEで何らかのクラスを呼んでおく必要はあるか。
- mappedByで指定されている名前(自分を指す)は何か。これは自分の「クラス名」なのか、それとも何らかの変数名やエイリアスなのか(ここが多くの記事やサンプルコードで触れられていない)。
- 最後の変数は
private $ProductClasses;
のように複数形(クラス名と異なる名前)になっているものもあるが、名前は任意か。 - ここで宣言された変数にはどこで何を代入するのか。既存のクラスではconstructで
$this->ProductClasses = new \Doctrine\Common\Collections\ArrayCollection();
のように空のコレクションクラスを代入して、そこにfunction copyで値を入れているようだが…
/** * @var integer * * @ORM\Column(name="id", type="integer", options={"unsigned":true}) * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \Doctrine\Common\Collections\Collection * @ORM\OneToOne(targetEntity="Customize\Entity\CustomerRank", mappedBy="Customer", cascade={"remove"}) */ private $CustomerRank;
コンストラクタの設定
- ここでArrayCollectionを代入するだけでよいのか。ほかにしておくことはないか。
public function __construct(){ $this->CustomerFavoriteProducts = new \Doctrine\Common\Collections\ArrayCollection(); $this->CustomerAddresses = new \Doctrine\Common\Collections\ArrayCollection(); $this->customerRank = new \Doctrine\Common\Collections\ArrayCollection(); //↑の行追加 $this->setBuyTimes(0); $this->setBuyTotal(0); }
####CustomerRank
Joinのリレーションの設定。
- InversedByで指定されているのはmappedByと同じようにクラス名か、それとも何らかの変数名やエイリアスか。
- JoinColumn内のnameは何を指定するのか。下では
@ORM\Column(name="customer_id"
で指定した名前を書いているが正しいか。 - 同様に、referencedColumnNameはCusotmerの
@ORM\Column(name="id",
に合わせてあるがこれでよいか。
/** * @var integer * @ORM\Column(name="customer_id",type="integer",options={"unsigned":true}) * @ORM\Id */ private $customer_id; /** * @ORM\OneToOne(targetEntity="Customize\Entity\Customer",inversedBy="CustomerRank") * @ORM\JoinColumn(name="customer_id",referencedColumnName="id") */ private $customer_rank
CustomerRepository
リポジトリでentityとRepositoryを呼び出す
クラス呼び出し
- 念のために並べたが不要のものもあるかもしれない。絶対必要なものはどれか。
use Customize\Entity\Customer use Customize\Entity\CustomerRank use Customize\Entity\CustomerRankRepository
コンストラクタ
- 親クラスのコンストラクタにはクラスは一つしか渡せない、でよいか。
- ここで渡したクラスが下のSQLでcreateQueryBuilderの対象となる、でよいか。
public function __construct(RegistryInterface $registry){ parent::__construct($registry, Customer::class); }
SQL
- leftJoin('c.CustomerRank','cr')の、c.CustomerRankはCustomerエンティティのCustomerRankプロパティにエイリアスをつけているのか。
- このメソッドが正しく動くためには、CustomerRankにはそれまでに何を代入しておく必要があるか。
$qp=$this->createQueryBuilder('c') ->select('c','cr')//取得するデータ ->leftJoin('c.CustomerRank','cr')//ここの指定が正しいか不安 ->where('c.id=:id')->setParameter('id',$id) ->setParameter('id', $id); $result = $qb->getQuery()->getSingleResult(); return $result;
その他
- Joinを呼び出す前に、どこかにこれらの関係性を認識させるなどの手順は必要か。
- また、リレーションを利用するために必要な(useすべき)クラスはあるか。
質問ばかり多くて済みませんが、多くの解説も公式ドキュメントすらわりと説明を端折っている部分が多く、わからない部分・不安な部分を書きだしたところこれだけになりました。
お手数ですが、よろしくお願いいたします。
あなたの回答
tips
プレビュー