মতবাদ 2 সহ ক্যাসকেড মোছার সময়


227

পিতামাতার টেবিল থেকে কোনও সারিটি কীভাবে মুছতে হয় এবং ডক্ট্রাইন 2 ব্যবহার করে শিশু টেবিলে মিলে যাওয়া সারিটি স্বয়ংক্রিয়ভাবে মোছার উপায়টি জানতে আমি একটি সাধারণ উদাহরণ তৈরি করার চেষ্টা করছি।

আমি যে দুটি সত্তা ব্যবহার করছি তা এখানে:

Child.php:

<?php

namespace Acme\CascadeBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="child")
 */
class Child {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORM\ManyToOne(targetEntity="Father", cascade={"remove"})
     *
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="father_id", referencedColumnName="id")
     * })
     *
     * @var father
     */
    private $father;
}

Father.php

<?php
namespace Acme\CascadeBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="father")
 */
class Father
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
}

টেবিলগুলি সঠিকভাবে ডাটাবেসে তৈরি করা হয়েছে, তবে এটি মুছে ফেলা ক্যাসকেড বিকল্পটি তৈরি করা হয়নি। আমি কি ভুল করছি?


ক্যাসকেডগুলি যাইহোক সঠিকভাবে সম্পাদন করে কিনা আপনি পরীক্ষা করেছেন? সম্ভবত মতবাদ তাদের ডাটাবেসের পরিবর্তে কোডে পরিচালনা করে।
সমস্যাযুক্ত

উত্তর:


408

মতবাদে দুটি ধরণের ক্যাসকেড রয়েছে:

1) ওআরএম স্তর - cascade={"remove"}অ্যাসোসিয়েশনে ব্যবহার করে - এটি এমন একটি গণনা যা ইউনিটঅফ ওয়ার্কে করা হয় এবং এটি ডাটাবেস কাঠামোকে প্রভাবিত করে না। আপনি যখন কোনও বস্তু সরিয়ে ফেলবেন, ইউনিটঅফ ওয়ার্ক সংঘের সমস্ত বস্তুর উপরে পুনরাবৃত্তি করবে এবং সেগুলি সরিয়ে দেবে।

2) ডেটাবেস স্তর - onDelete="CASCADE"সংঘের যোগদানের কলামে ব্যবহার করে - এটি ডাটাবেসে বিদেশী কী কলামে অন ডিলিট ক্যাসকেড যুক্ত করবে:

@ORM\JoinColumn(name="father_id", referencedColumnName="id", onDelete="CASCADE")

আমি এটিও উল্লেখ করতে চাই যে আপনার ক্যাসকেডটি এখনই = remove "অপসারণ"} রয়েছে, আপনি যদি কোনও শিশু অবজেক্ট মুছে ফেলেন তবে এই ক্যাসকেডটি প্যারেন্ট অবজেক্টটিকে সরিয়ে ফেলবে। স্পষ্টতই আপনি যা চান তা নয়।


3
আমি সাধারণত onDelete = "CASCADE" ব্যবহার করি কারণ এর অর্থ হল ORM কম কাজ করতে হবে এবং এর কিছুটা ভাল পারফরম্যান্স করা উচিত।
মাইকেল রিডওয়ে

57
আমিও করি তবে এটি নির্ভর করে। উদাহরণস্বরূপ বলুন আপনার কাছে চিত্র সহ একটি চিত্র গ্যালারী রয়েছে। আপনি যখন গ্যালারী মুছবেন তখন আপনি চাইবেন চিত্রগুলিও ডিস্ক থেকে মুছে ফেলা হবে। আপনি যদি নিজের চিত্রটির মুছে ফেলা () পদ্ধতিতে ওআরএম ব্যবহার করে ক্যাসকেডিং মুছে ফেলেন তা নিশ্চিত করে তোলে যে অনাথ ইমেজ ফাইলগুলি পরীক্ষা করে এমন ক্রোনজবস প্রয়োগের কাজটি আপনাকে সংরক্ষণ করবে যে আপনার সমস্ত চিত্রের ডেল্ট () ফাংশন ডাকা হবে।
ফ্লু

4
@ মিশেল রিডওয়ে মাঝে মাঝে উভয় বক্তব্য প্রয়োগ করা উচিত - onDeleteপাশাপাশি cascade = {"remove"}উদাহরণস্বরূপ যখন আপনার ফস ইউজারের সাথে কোনও বিষয় সম্পর্কিত থাকে। উভয় বস্তুর একা অস্তিত্ব থাকা উচিত নয়
লুক অ্যাডামসিজেস্কি

17
মনে রাখবেন আপনি কেবল লিখতে পারেন @ORM\JoinColumn(onDelete="CASCADE")এবং তবুও মতামতটি কলামের নামগুলি স্বয়ংক্রিয়ভাবে পরিচালনা করতে দেয়।
mcfedr

5
@dVaffection এটি একটি ভাল প্রশ্ন। আমি মনে করি যে onDelete="CASCADE"ডক্ট্রাইন cascade={"remove"}মূল সত্তাটি সরিয়ে দেওয়ার আগে সম্পর্কিত সত্তাগুলি সরান (যেহেতু) এটি কোনও প্রভাব ফেলবে না। সুতরাং যখন মূল সত্তাটি মুছে ফেলা হবে তখন onDelete="CASCADE"মুছার জন্য কোনও বিদেশী সম্পর্ক নেই । তবে নিশ্চিত হওয়ার জন্য আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি কেবল একটি ছোট পরীক্ষার কেস তৈরি করুন এবং কার্যকর করা প্রশ্নগুলি এবং তাদের মৃত্যুদণ্ডের আদেশটি দেখুন।
ফ্লু

50

এখানে সহজ উদাহরণ। একটি পরিচিতিতে একের সাথে অনেকগুলি যুক্ত ফোন নম্বর রয়েছে। যখন কোনও পরিচিতি মুছে ফেলা হয়, আমি চাই এর সাথে সম্পর্কিত সমস্ত ফোন নম্বরও মুছে ফেলা হোক, তাই আমি মুছে ফেলুন ক্যাসকেড ব্যবহার করি। একের সাথে একাধিক / বহু-এক-এক সম্পর্ক বিদেশী কী দ্বারা ফোন_নম্বারে প্রয়োগ করা হয়।

CREATE TABLE contacts
 (contact_id BIGINT AUTO_INCREMENT NOT NULL,
 name VARCHAR(75) NOT NULL,
 PRIMARY KEY(contact_id)) ENGINE = InnoDB;

CREATE TABLE phone_numbers
 (phone_id BIGINT AUTO_INCREMENT NOT NULL,
  phone_number CHAR(10) NOT NULL,
 contact_id BIGINT NOT NULL,
 PRIMARY KEY(phone_id),
 UNIQUE(phone_number)) ENGINE = InnoDB;

ALTER TABLE phone_numbers ADD FOREIGN KEY (contact_id) REFERENCES \
contacts(contact_id) ) ON DELETE CASCADE;

বিদেশী কী সীমাবদ্ধতার সাথে "অন ডিলেট ক্যাসকেড" যুক্ত করে, ফোন সম্পর্কিত নম্বরগুলি তাদের সম্পর্কিত পরিচিতি মুছে ফেলা হলে স্বয়ংক্রিয়ভাবে মুছে ফেলা হবে।

INSERT INTO table contacts(name) VALUES('Robert Smith');
INSERT INTO table phone_numbers(phone_number, contact_id) VALUES('8963333333', 1);
INSERT INTO table phone_numbers(phone_number, contact_id) VALUES('8964444444', 1);

এখন যখন পরিচিতি সারণীতে একটি সারি মুছে ফেলা হবে, তখন সম্পর্কিত সমস্ত ফোন_নম্বার সারি স্বয়ংক্রিয়ভাবে মোছা হবে।

DELETE TABLE contacts as c WHERE c.id=1; /* delete cascades to phone_numbers */

ডক্ট্রাইনে একই জিনিস অর্জন করতে, একই ডিবি-স্তরের "অন ডিলিট ক্যাসকেড" আচরণটি পেতে, আপনি @ জয়নকলামকে অনডিলিট = "ক্যাসকেড" বিকল্পের সাহায্যে কনফিগার করেন ।

<?php
namespace Entities;

use Doctrine\Common\Collections\ArrayCollection;

/**
 * @Entity
 * @Table(name="contacts")
 */
class Contact 
{

    /**
     *  @Id
     *  @Column(type="integer", name="contact_id") 
     *  @GeneratedValue
     */
    protected $id;  

    /** 
     * @Column(type="string", length="75", unique="true") 
     */ 
    protected $name; 

    /** 
     * @OneToMany(targetEntity="Phonenumber", mappedBy="contact")
     */ 
    protected $phonenumbers; 

    public function __construct($name=null)
    {
        $this->phonenumbers = new ArrayCollection();

        if (!is_null($name)) {

            $this->name = $name;
        }
    }

    public function getId()
    {
        return $this->id;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function addPhonenumber(Phonenumber $p)
    {
        if (!$this->phonenumbers->contains($p)) {

            $this->phonenumbers[] = $p;
            $p->setContact($this);
        }
    }

    public function removePhonenumber(Phonenumber $p)
    {
        $this->phonenumbers->remove($p);
    }
}

<?php
namespace Entities;

/**
 * @Entity
 * @Table(name="phonenumbers")
 */
class Phonenumber 
{

    /**
    * @Id
    * @Column(type="integer", name="phone_id") 
    * @GeneratedValue
    */
    protected $id; 

    /**
     * @Column(type="string", length="10", unique="true") 
     */  
    protected $number;

    /** 
     * @ManyToOne(targetEntity="Contact", inversedBy="phonenumbers")
     * @JoinColumn(name="contact_id", referencedColumnName="contact_id", onDelete="CASCADE")
     */ 
    protected $contact; 

    public function __construct($number=null)
    {
        if (!is_null($number)) {

            $this->number = $number;
        }
    }

    public function setPhonenumber($number)
    {
        $this->number = $number;
    }

    public function setContact(Contact $c)
    {
        $this->contact = $c;
    }
} 
?>

<?php

$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

$contact = new Contact("John Doe"); 

$phone1 = new Phonenumber("8173333333");
$phone2 = new Phonenumber("8174444444");
$em->persist($phone1);
$em->persist($phone2);
$contact->addPhonenumber($phone1); 
$contact->addPhonenumber($phone2); 

$em->persist($contact);
try {

    $em->flush();
} catch(Exception $e) {

    $m = $e->getMessage();
    echo $m . "<br />\n";
}

আপনি এখন যদি

# doctrine orm:schema-tool:create --dump-sql

আপনি দেখতে পাবেন যে একই এসকিউএল প্রথম, কাঁচা-এসকিউএল উদাহরণ হিসাবে তৈরি করা হবে


4
এটি কি সঠিক প্লেসমেন্ট? ফোন নম্বর মোছার সাথে যোগাযোগ মুছে ফেলা উচিত নয়। যার সাথে মুছে ফেলা ক্যাসকেডকে ট্রিগার করা উচিত এটির যোগাযোগ। তাহলে কেন শিশু / ফোনে ক্যাসকেড রাখবেন?
przemo_li

1
@ প্রজেমো_লি এটি সঠিক স্থাপনা। পরিচিতিটি ফোন নম্বর বিদ্যমান তা জানে না, কারণ ফোন নম্বরগুলির যোগাযোগের একটি রেফারেন্স রয়েছে, এবং কোনও পরিচিতির ফোন নম্বরগুলির একটি উল্লেখ নেই। সুতরাং যদি কোনও পরিচিতি মুছে ফেলা হয়, একটি ফোন নম্বরটিতে একটি অস্তিত্বযুক্ত যোগাযোগের উল্লেখ রয়েছে। এই ক্ষেত্রে, আমরা কিছু ঘটতে চাই: অনটি মোছার ক্রিয়াটি ট্রিগার করে। আমরা মুছে ফেলা ক্যাসকেড করার সিদ্ধান্ত নিয়েছি, যাতে ফোন নম্বরগুলিও মুছে ফেলা যায়।
marijnz0r

3
@ প্রজেমি_লিটি সত্তায় onDelete="cascade"সঠিকভাবে স্থাপন করা হয়েছে (সন্তানের উপরে) কারণ এটি এসকিউএল ক্যাসকেডিং , যা সন্তানের উপর স্থাপন করা হয়। কেবলমাত্র ডক্ট্রাইন ক্যাসকেডিং ( cascade=["remove"]যা এখানে ব্যবহৃত হয় না ) পিতামাতার উপর স্থাপন করা হয়।
মরিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.