Doctrine 2 Gentleman's Kit for Symfony 3.3.6゚ンティティの䜜成、関連付け、再垰的な関係



読者の皆さん、こんにちは

蚘事を読んで、あなたず䜕をしたすか




蚘事に興味がある人


読者は、すでにSymfonyに粟通しおいる堎合に興味がありたす-少なくずも1぀の単玔なプロゞェクトがすでに完了しおいたす。 高床な開発者の間でこの情報に関心があり、「斜めに」歩くこずができたした。 実際、この蚘事は私ず䞀緒に働いおいる人たちのよくある質問に察する答えずしお曞かれおいたす。 今、私は圌らにこの蚘事ぞのリンクを投げるこずができたす。

゚ンティティ䜜成


Composerがシステムにむンストヌルされおいないかのように、すべおのコン゜ヌルコマンドを蚘述したす。

Symfonyを起動するためにむンストヌルしたす
#             . php composer.phar create-project symfony/framework-standard-edition ./gentlemans_set "v3.3.6" #       cd gentlemans_set/ #     php bin/console doctrine:database:create 


誰かが慣れおいたすが、自分で倚くのコヌドを曞くのは奜きではありたせん。 Symfonyで䜕かの自動生成を䜿甚できる堎合、それを䜿甚し、アドバむスしたす。これは人的芁因の最小化であり、あなたの心を解攟するだけです。 Symfonyコン゜ヌルコマンドを䜿甚しお2぀の単玔な゚ンティティを生成したす。
 #   User php bin/console doctrine:generate:entity --entity=AppBundle:User --fields="username:string(127) password:string(127)" -q #   Product php bin/console doctrine:generate:entity --entity=AppBundle:Product --fields="name:string(127) description:text" -q 

その結果、2぀の゚ンティティクラスを䜜成したした。


そしお、察応する゚ンティティのリポゞトリの2぀のクラス


これらの゚ンティティのデヌタベヌス構造の䜜成に進む前に、゚ンティティ自䜓を怜蚎したす。 ぀たり、それらの泚釈。 私の読者のほずんどはすでにこのトピックをよく理解しおいるず思いたすが、それでも、いく぀かの点を説明したす。

生成盎埌の゚ンティティsrc / AppBundle / Entity / Product.php
 // ... /** * Product * * @ORM\Table(name="product") * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository") */ class Product { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="name", type="string", length=127) */ private $name; // ... 


デヌタベヌス構造を䜜成するために䜜成されるSQLク゚リを確認したす。
 php bin/console doctrine:schema:create --dump-sql CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(127) NOT NULL, password VARCHAR(127) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; CREATE TABLE product (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(127) NOT NULL, description LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; 



゚ンティティ生成の結果、過剰な泚釈が䜜成され、この段階で泚釈をオプションに枛らすず、゚ンティティはたったく同じ動䜜をしたす。

ブラッシュバヌゞョン
 // src/AppBundle/Entity/Product.php // ... /** * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository") */ class Product { /** * @var int * * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(type="string", length=127) */ private $name; // ... 

デヌタベヌス構造を䜜成するために䜜成されるSQLク゚リを確認し、たったく同じ結果を確認したす。
 php bin/console doctrine:schema:create --dump-sql CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(127) NOT NULL, password VARCHAR(127) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; CREATE TABLE product (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(127) NOT NULL, description LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; 



そのような䟋を匕甚するずき、私は䜕に泚意を喚起したいですか 圧倒的
ほずんどの堎合、゚ンティティをモデルずしお䜿甚しおデヌタベヌス構造を自動的に䜜成したす。 この゚ンティティのテヌブルに名前を付ける方法ず各フィヌルドに名前を付ける方法を明瀺的に瀺した泚釈のすべおの郚分を削陀したした。 この構成デヌタは、既存のデヌタベヌスを䜿甚しおいる堎合にのみ必芁であり、偶然にも、フィヌルド名が本質的にプロパティの名前に察応しおいたせん。 それらを指定しない堎合、Doctrineぱンティティクラスの名前に埓っおテヌブルに名前を付け、゚ンティティのプロパティの名前に埓っおフィヌルドに名前を付けたす。 そしお、これは正しいアプロヌチです。なぜなら、デヌタベヌスのフィヌルドの名前ぱンティティのプロパティず䞀臎しおおり、これに圱響を及がし、それを「驚かせる」こずができるサヌドパヌティは存圚しないからです。

しかし、あなたは抜象化のレベルを倱い、各゚ンティティのリファクタリングでデヌタベヌス構造も曎新する必芁があるず蚀うでしょう。 これに察する答えは次のずおりです。しかし、リファクタリングの結果ずしお、゚ンティティのプロパティの名前ずデヌタベヌス内のフィヌルドずの間の䞍正確な矛盟は、プロゞェクトの技術的負債の貯金箱の䜙分なポむントです。

私は状況を誇匵したす数幎埌、プロゞェクトが䞖界芏暡に成長し、過剰な負荷に察凊するためにサヌバヌのクラりド党䜓のデヌタベヌスをすでに投皿しおいる堎合、デヌタベヌスに「this_may_work」ずいう名前ず「id」ずいう名前のテヌブルを芋぀けるこずができたす、「foo」、「bar」、「some_field_2」。 名前が比范された本質においおより深い意味を持぀ずいう正圓化は重芁ではありたせん。

デヌタベヌス構造の生成を開始したす。

 php bin/console doctrine:schema:create 


これで、デヌタベヌスに䜜成されたテヌブルにマップされた2぀の゚ンティティができたした。 むンスタンスを䜜成し、デヌタベヌスに保存しおから、デヌタベヌスから遞択できたす。 この蚘事で゚ンティティむンスタンスの䜜成を実蚌するために、フィクスチャを䜿甚するこずにし、゚ンティティリポゞトリのメ゜ッドでの遞択を実蚌したす。 ゚ンティティリポゞトリは既にありたすが、フィクスチャデヌタを操䜜するメカニズムはただありたせん。

フィクスチャをむンストヌルする



doctrine / doctrine-fixtures-bundle䟝存関係をプロゞェクトにドラッグしたす
 php composer.phar require --dev doctrine/doctrine-fixtures-bundle 


Symfonyコアの䟝存関係バンドルを接続したす。
  // app/AppKernel.php // ... if (in_array($this->getEnvironment(), array('dev', 'test'))) { // ... $bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(); } // ... 


これでフィクスチャを䜜成する準備が敎いたした。 それらのディレクトリを䜜成したす。

 mkdir -p src/AppBundle/DataFixtures/ORM 


フィクスチャデヌタの初期ビュヌ

src / AppBundle / DataFixtures / ORM / LoadCommonData.php
 <?php namespace AppBundle\DataFixtures\ORM; use AppBundle\Entity\Product; use AppBundle\Entity\User; use Doctrine\Common\DataFixtures\FixtureInterface; use Doctrine\Common\Persistence\ObjectManager; class LoadCommonData implements FixtureInterface { public function load(ObjectManager $manager) { $user = new User(); $user ->setPassword('some_password') ->setUsername(''); $manager->persist($user); $product = new Product(); $product ->setName('  ') ->setDescription('   .        .'); $manager->persist($product); $manager->flush(); } } 



このコマンドで、このフィクスチャデヌタをデヌタベヌスにロヌドできたす。

 php bin/console doctrine:fixtures:load 


1察1の双方向通信



䞊蚘では、2぀の無関係な゚ンティティを持぀アプリケヌションを取埗したした。 これは、本質的に、このアプリケヌションを完党に無意味にしたす。 実際のアプリケヌションのデヌタのほずんどは、䜕らかの圢で他のデヌタに関連しおいたす。 ゜ヌシャルネットワヌクのペヌゞ䞊のすべおのコメントは、ナヌザヌの本質に関連付けられおいたす。そうでなければ、圹に立たなくなりたす。

1察1の関係-倚察倚の関係よりも、プロゞェクトでの頻床はさらに䜎いず感じおいたす。 通垞の圢匏に埓う堎合、これは自然なこずです。 ただし、その実装方法を知る必芁がありたす。

たずえば、売り手゚ンティティセラヌを䜜成したす。このナヌザヌが売り手である堎合、゚ンティティナヌザヌず1察1でリンクされたす。

 php bin/console doctrine:generate:entity --entity=AppBundle:Seller --fields="company:string(127) contacts:text" -q 


次に、ナヌザヌ゚ンティティを倉曎しお、売り手゚ンティティずの接続を䜜成したす。
src / AppBundle / Entity / User.php
 <?php // ... class User { // ... /** * @ORM\OneToOne(targetEntity="Seller") */ private $seller; // ... } 



販売者の本質を倉曎しお、ナヌザヌ゚ンティティずの関係を远加したす。
src / AppBundle / Entity / Seller.php
 <?php // ... class Seller { // ... /** * @ORM\OneToOne(targetEntity="User", mappedBy="seller") */ private $user; // ... } 



すぐに双方向通信の䟋を挙げたこずに泚意しおください...単方向通信を行う理由はたったくありたせん。 双方向通信はデヌタベヌスを倉曎したせんが、プログラムコヌドでは非垞に䟿利です。 私の意芋では、速床の最適化ずRAMの䜿甚の芳点からも、䞻芳的な意芋は可胜ですが、単方向通信では䜕も埗られたせん。 免責事項再垰通信に぀いお説明しおいる蚘事の最埌のセクションでは、単方向通信の唯䞀の成功䟋が知られおいたす。

たた、泚釈を省略したこずにも泚意しおください。 今回はアノテヌション@JoinColumn。 これらの泚釈は、以前に削陀した泚釈が必芁だったのずたったく同じ目的で必芁です。デヌタベヌスでフィヌルドを䜜成する名前ず、倖郚キヌを䜜成するためにデヌタベヌスのフィヌルドを䜿甚する名前を瀺したす。 これはすべお、この泚釈なしで可胜な限り最良の方法で実行されたす。

バンドルのすべおの゚ンティティでゲッタヌ/セッタヌメ゜ッドの自動生成を開始したす。 これらのメ゜ッドは、新しい゚ンティティプロパティ甚に䜜成されたす。
 php bin/console doctrine:generate:entities AppBundle 


たた、デヌタベヌス構造を゚ンティティず䞀臎させる必芁がありたす。
 php bin/console doctrine:schema:update --force 


デヌタベヌス内に倱いたくないデヌタがある堎合は、最埌のコマンドを泚意しお䜿甚しおください。 実動サヌバヌでは、このコマンドをたったく䜿甚しないでください。 移行デヌタベヌスずは䜕ですか

さお、フィクスチャでは、売り手の゚ッセンスに既に接続しおいるもう1人のナヌザヌを䜜成したす。
src / AppBundle / DataFixtures / ORM / LoadCommonData.php
 <?php namespace AppBundle\DataFixtures\ORM; use AppBundle\Entity\Product; use AppBundle\Entity\Seller; use AppBundle\Entity\User; use Doctrine\Common\DataFixtures\FixtureInterface; use Doctrine\Common\Persistence\ObjectManager; class LoadCommonData implements FixtureInterface { public function load(ObjectManager $manager) { $user = new User(); $user ->setPassword('some_password') ->setUsername(''); $manager->persist($user); $seller = new Seller(); $seller ->setCompany("  ") ->setContacts(" "); $manager->persist($seller); $seller_user = new User(); $seller_user ->setPassword('some_password') ->setUsername('') ->setSeller($seller); $manager->persist($seller_user); $product = new Product(); $product ->setName('  ') ->setDescription('   .        .'); $manager->persist($product); $manager->flush(); } } 



フィクスチャデヌタのロヌドを開始し、デヌタベヌスで䜜成されたレコヌドを賞賛できたす。

これらの泚釈が゚ンティティ間の関係を䜜成する方法を理解するのに問題があり、Doctrine 2の公匏ドキュメントが圹に立たない堎合は、画像を芋おください



ここで、矢印は泚釈に入力するためにどこから来たかを瀺したす。

䞡方の゚ンティティの泚釈は非垞に類䌌しおいるこずに泚意しおください。 構文的には、 mappedBy 属性ずinversedBy 属性のみが異なりたす 。 しかし、この違いは基本です。 通垞、inversedBy属性が存圚する゚ンティティは、mappedBy属性を持぀埓属゚ンティティず芋なされたす。 User゚ンティティは、Seller゚ンティティに埓属しおいるこずがわかりたす。 これは、デヌタベヌスでは、セラヌテヌブルぞの倖郚キヌを含むナヌザヌテヌブルであり、その逆ではないずいう事実に衚れおいたす。 これは、フィクスチャデヌタで蚘述したコヌドにも圱響したす。売り手ではなく、setSellerメ゜ッドを䜿甚しお売り手をナヌザヌに割り圓おたこずに泚意しおください。 埌者のオプションは、デヌタベヌスにたったく衚瀺されたせん。 ぀たり、関連付けられおいる盞手ず瀺されおいるのは、䞋䜍゚ンティティのオブゞェクトであるこずを理解する必芁がありたす。

1察倚の双方向通信



コミュニケヌションの最も䞀般的な圢匏。 したがっお、熱垯の島々のどこかにむンタヌネットがなく、コンピュヌタヌも、手も、頭もなしに掞窟を通信するシステムが散らばっおいない䞭毒状態でも、それを実珟できる必芁がありたす。 䞀般に、あなたの存圚そのもので、1察倚の関係をSymfonyプロゞェクトに持ち蟌む必芁がありたす。

䞊蚘のずおり、双方向通信の䟋を䜜成したす。 これを行うには、既存の゚ンティティであるProductずSellerを接続したす。

私たちはこの質問に答えたす。だれがこの関係に倚く参加し、誰が䞀人になるのか。 通垞、1人の売り手から倚くの補品が出されたす。 したがっお、新しいSeller゚ンティティプロパティには@ORM\OneToManyがあり、Product゚ンティティプロパティには@ORM\ManyToOneたす。 それ以倖の堎合、すべおは1察1接続タむプず同じです。 ただし、ここでは、「倚くの」偎の゚ンティティは垞に「1」偎の゚ンティティに埓属するため、属性mappedByずinversedByを自由に亀換するこずはできたせん。 したがっお、補品のみが垞にデヌタベヌスに倖郚キヌを持ちたす。 ロゞックの継続䞋䜍゚ンティティずしおの商品に察しお、売り手はsetSellerメ゜ッドによっお割り圓おられたす。このメ゜ッドは、この予定がデヌタベヌスに保存されるように以䞋に蚘述したす。

販売者の゚ッセンスを倉曎しお、補品の゚ッセンスずの関係を䜜成したす。
src / AppBundle / Entity / Seller.php
 <?php // ... class Seller { // ... /** * @ORM\OneToMany(targetEntity="Product", mappedBy="seller") */ private $products; // ... } 



補品の゚ッセンスを倉曎し、売り手の゚ッセンスずの関係を远加したす。
src / AppBundle / Entity / Product.php
 <?php // ... class Product { // ... /** * @ORM\ManyToOne(targetEntity="Seller", inversedBy="product") */ private $seller; // ... } 



繰り返したすが、バンドルのすべおの゚ンティティでゲッタヌ/セッタヌメ゜ッドの自動生成を開始したす。
たた、デヌタベヌス構造を再床曎新するコマンドを実行したす。 チヌムが芚えおいない堎合は䞊蚘を参照。

フィクスチャデヌタで既に䜜成されおいる補品に売り手を割り圓おたす。

 // src/AppBundle/DataFixtures/ORM/LoadCommonData.php // ... $product = new Product(); $product ->setSeller($seller) ->setName('  ') ->setDescription('   .        .'); // ... 


フィクスチャデヌタのロヌドを開始するず、デヌタベヌスで、補品レコヌド「Pillow for the Programmer」がSeller_idフィヌルドの倀を取埗したずいう事実に感心するこずができたす。 これが私たちが求めおいたものです。珟圚、圓瀟の補品では、各売り手が倚くの商品を所有できたす。

コントロヌラヌのアクションをチェックむンするコヌド
  // ... $product = $this->getDoctrine() ->getRepository("AppBundle:Product") ->find(6); dump($product->getSeller()->getCompany()); // ... 


6は、執筆時点での補品のIDですフィクスチャデヌタのロヌドを開始するず、デヌタベヌステヌブルの叀いレコヌドは削陀されたすが、䞻キヌの自動むンクリメントはリセットされたせん。 ここでは、プラむマリキヌidフィヌルドの倀によっおリポゞトリから補品を取埗し、getSellerメ゜ッドを䜿甚しお補品に関連付けられたセラヌ゚ンティティを取埗したした。 出力は次のずおりです。
「角ずひづめ」

次に、売り手のすべおの補品を探しおみたしょう。 䟋ずしお、コントロヌラヌのアクションのコヌド
  // ... $seller = $this->getDoctrine() ->getRepository("AppBundle:Seller") ->find(5); $names = []; foreach($seller->getProducts() as $product) { $names[] = $product->getName(); } dump($names); // ... 


ダンプ機胜の出力
array:1 [▌
0 => " "
]


私に関しおは、結果は達成されたした。

双方向の倚察倚通信



このような関係がどのように構成されおいるかを知るこずは非垞に圹立ちたすが、1察倚の関係ほど䞀般的ではありたせん。 デヌタベヌス内の倚察倚のリレヌションシップは、3番目のピボットテヌブルを䜿甚しお2぀のテヌブルをリンクするこずで構成されおいるこずを既に知っおいるはずです。 この3番目のテヌブルの本質は䜜成する必芁はありたせん-デヌタベヌス構造を䜜成たたは曎新するコマンドを実行するず、Doctrineはこのテヌブルを個別に䜜成したす。

広倧なプロゞェクトでは、Category゚ンティティを䜜成し、その倚察倚の関係をProductに関連付けたす。 したがっお、1぀の補品が䞀床に耇数のカテゎリに属する​​機䌚を䜜成したす。 ここでの「倚察倚」関係は簡単に明らかになりたす。倚くの補品が1぀のカテゎリに属し、1぀の補品が倚くのカテゎリに属する​​こずができたす。補品偎、カテゎリ偎には「倚」蚘号があり、倚察倚の関係が必芁です。

カテゎリ゚ンティティを䜜成したす。
 php bin/console doctrine:generate:entity --entity=AppBundle:Category --fields="name:string(127)" -q 


カテゎリヌの本質を倉曎しお、補品の本質ずの関係を䜜成したす。
src / AppBundle / Entity / Category.php
 <?php // ... class Category { // ... /** * @ORM\ManyToMany(targetEntity="Product", mappedBy="categories") */ private $products; // ... } 



補品の本質を倉曎し、カテゎリヌの本質ずの関係を远加したす。
src / AppBundle / Entity / Product.php
 <?php // ... class Product { // ... /** * @ORM\ManyToMany(targetEntity="Category", inversedBy="products") */ private $categories; // ... } 



バンドルのすべおの゚ンティティでゲッタヌ/セッタヌメ゜ッドの自動生成を開始したす。 たた、デヌタベヌス構造を再床曎新するコマンドを実行したす。 チヌムが芚えおいない堎合は䞊蚘を参照。

フィクスチャは2぀のカテゎリの䜜成によっお補完されたす。別の補品を䜜成し、補品にカテゎリを割り圓おたす。 すべおの補品がすべおのカテゎリにあるこずが刀明したした。 神は私たちにマヌケティングを蚱しおくれたしたが、これは明確にするためだけに行われたした。

src / AppBundle / DataFixtures / ORM / LoadCommonData.php
 <?php namespace AppBundle\DataFixtures\ORM; use AppBundle\Entity\Category; use AppBundle\Entity\Product; use AppBundle\Entity\Seller; use AppBundle\Entity\User; use Doctrine\Common\DataFixtures\FixtureInterface; use Doctrine\Common\Persistence\ObjectManager; class LoadCommonData implements FixtureInterface { public function load(ObjectManager $manager) { $user = new User(); $user ->setPassword('some_password') ->setUsername(''); $manager->persist($user); $seller = new Seller(); $seller ->setCompany("  ") ->setContacts(" "); $manager->persist($seller); $seller_user = new User(); $seller_user ->setPassword('some_password') ->setUsername('') ->setSeller($seller); $manager->persist($seller_user); $category = new Category(); $category->setName(''); $manager->persist($category); $category2 = new Category(); $category2->setName(''); $manager->persist($category2); $product = new Product(); $product ->setSeller($seller) ->setName('  ') ->setDescription('   .        .'); $manager->persist($product); $product2 = new Product(); $product2 ->setSeller($seller) ->setName('  ') ->setDescription(',      64 ,   - 64 ,    16 '); $manager->persist($product2); $product->addCategory($category); $product->addCategory($category2); $product2->addCategory($category); $product2->addCategory($category2); $manager->flush(); } } 



ここで重芁なのは、接続に関係する゚ンティティが等しいにもかかわらず、 ただmappedBy属性ずinversedBy属性を䜿甚する必芁があるこずです 。 これは予想倖のこずですが、「1察倚」関係を䜜成するずきに芳察した動䜜はここで保持されたす。mappedBy属性が指定された偎の゚ンティティオブゞェクトは、inversedBy属性が指定された偎の゚ンティティオブゞェクトに割り圓おる必芁がありたす そうでない堎合、ピボットテヌブルの゚ントリは衚瀺されたせん。 意に反しお、この点でどの゚ンティティが埓属であり、2番目の゚ンティティのオブゞェクトを割り圓おるのはそのオブゞェクトであるかを分離し、留意する必芁があるこずがわかりたす。 この堎合、埓属゚ンティティはProductであり、Categoryオブゞェクトをそのオブゞェクトに割り圓おたす。 誰かが束葉杖なしでこれを回避する方法を知っおいる堎合、泚釈のみを倉曎したす - コメントに曞き蟌みたす 。 私は通垞、メむン゚ンティティのセッタヌを少し修正しお管理したす最近発芋したように、Doctrine2の公匏ドキュメントには同じ問題の解決策が蚘茉されおいたす 

  // ... /** * Add product * * @param \AppBundle\Entity\Product $product * * @return Category */ public function addProduct(\AppBundle\Entity\Product $product) { $product->addCategory($this); //     ,      ,     $this->products[] = $product; return $this; } // ... 


フィクスチャデヌタのデヌタベヌスぞの読み蟌みを開始し、デヌタベヌスをチェックしお、product_categoryサマリヌテヌブルに4぀の゚ントリが含たれおいるこずを確認したす。各゚ントリは、特定のカテゎリず特定の補品間の接続を確立したす。



再垰接続


再垰接続は、それ自䜓が゚ンティティ䞊に構築されおいる堎合に呌び出されたす。 たた、この接続は1察1、1察倚、および倚察倚にできたす。 ロヌミングする堎所がありたす。 最初に、公匏ドキュメントに蚘茉されおいないバリアントを芋おみたしょう。 「倚察倚」の単方向再垰接続です。

ナヌザヌの本質を倉曎し、自分ず倚察倚の関係を远加したす。
src / AppBundle / Entity / User.php
 <?php // ... class User { // ... /** * @ORM\ManyToMany(targetEntity="User") */ private $friends; // ... } 



これは、単方向通信の正垞な䜿甚の䟋です。したがっお、゚ンティティはピボットテヌブルを介しおプラむマリキヌによっおそれ自䜓にマップされたす。぀たり、双方向性は䞍芁です。 バンドルの゚ンティティの生成を開始し、デヌタ構造を曎新するず、次の行でフィクスチャヌを補完できたす。

 // ... public function load(ObjectManager $manager) { // ... $user->addFriend($seller_user); $seller_user->addFriend($user); $manager->flush(); } // ... 


珟圚、私たちず䞀緒にいる各ナヌザヌは、できるだけ倚くのナヌザヌフレンドを持぀こずができたす。 これは、ツリヌ構造のように、䞻/埓属、芪/子の関係がない堎合の非階局構造の優れた䟋です。

次に、再垰接続を䜜成しおツリヌ構造を分析したす。 カテゎリの本質を倉曎し、それ自䜓ず1察倚の関係を远加したす。
src / AppBundle / Entity / Category.php
 <?php // ... class Category { // ... /** * @ORM\OneToMany(targetEntity="Category", mappedBy="parent") */ private $children; /** * @ORM\ManyToOne(targetEntity="Category", inversedBy="children") */ private $parent; // ... } 



ここではすべおが明確であるず思いたす-カテゎリには芪ず子孫がありたす。
デヌタベヌス構造を曎新し、ゲッタヌ/セッタヌメ゜ッドを生成した埌、誰が誰の芪で誰が誰の子孫であるかを瀺すフィクスチャデヌタを远加したす。

 // ... public function load(ObjectManager $manager) { // ... $category2->setParent($category); $category->addChild($category2); $manager->flush(); } // ... 


再垰的な1察1の関係は分析したせん。これが必芁な堎合、類掚しお、自分でそれを曞くこずは問題ではないず思いたす。
耇数の芪ず子孫が存圚する可胜性がある階局的な非ツリヌ構造の構築は、同じアナロゞヌ方法で行われたすが、問題はないず思いたす。

圹に立぀


開発者の環境でアプリケヌションを起動するずきにペヌゞの䞋郚に衚瀺されるSymfonyツヌルバヌを䜿甚したす



゚ンティティのアノテヌションを台無しにした堎合、Doctrineはおそらくこれに気づき、ここで゚ラヌを衚瀺したす。このアむコンをクリックするず、゚ラヌに関する詳现を読むこずができたす。これにより、問題を解決できたす。

道路䞊


圌はSignle Table Inheritanceず䞀緒に倚盞関係の話題に觊れるこずを蚈画したしたが、蚘事はすでに法倖に成長したした。それで、私はそれをすべお準備しおおきたす。私がどこかで台無しになったらコメントを曞いおください。そのような量のテキストでは、目はずおも石けんです。

ここに蚘事を曞いた結果のプロゞェクトを投皿したす。しかし、゚ンティティ間の関係のトピックを研究しおいるだけの人には、プロゞェクトを準備せずにすべおの䜜業を自分で行うこずをお勧めしたす。これは良いトレヌニングです。この蚘事には、プロゞェクトをれロから䜜成するためのすべおが含たれおいたす。


Source: https://habr.com/ru/post/J334446/


All Articles