2013-07-31 4 views
12

बिना किसी किस्मत के डिस्काउंट कैस्केड और सॉफ्टडिलेट के साथ विदेशी कुंजी का उपयोग करने का प्रयास किया।Laravel4 में softdeletes पर कैसे cascade?

मेरे पास 2 टेबल हैं: उपयोगकर्ता, घटनाक्रम। दोनों टेबलों में मुलायम डीलीट हैं।

उपयोगकर्ता 0..n घटनाक्रम हो सकते हैं।
घटनाक्रम एक user_id, उन पर विदेशी कुंजी के रूप में इस्तेमाल किया है इस तरह:

$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE'); 

समस्या है, जब मैं एक उपयोगकर्ता को हटाते हैं, यह नरम हटाए गए, लेकिन इसकी घटनाक्रम नहीं हो जाता है - या तो मुलायम को हटाने या उसे शारीरिक विलोपन।

क्या मैं कुछ गलत कर रहा हूं, या यह सही वाद्य व्यवहार है?

दूसरा, यदि यह सही व्यवहार है, तो हटाने के कैस्केड को सर्वोत्तम तरीके से कैसे कार्यान्वित किया जाए? शायद इस तरह के मेरे मॉडल में हटाएं() विधि को ओवरराइड कर रहा है ...

public function delete() 
{ 
    //delete all events... 
    __parent::delete() 
} 

?

उत्तर

11

डीबी की विदेशी कुंजी कुछ भी नहीं करेगी क्योंकि आपने प्राथमिक कुंजी को प्रश्न में नहीं बदला है। केवल अगर आप प्राथमिक कुंजी को अपडेट या हटाते हैं तो संबंधित पंक्तियां संशोधित की जाएंगी।

सब कुछ से मैं इस विषय के बारे में पा सकता हूं, समाधान हटाने के लिए Eloquent's Model Events का उपयोग करना है, और संबंधित तालिकाओं को अपडेट करना है।

Here's one StackOverflow question about it.

वैकल्पिक रूप से, आप "विस्तार" कर सकते हैं delete() विधि और कार्यक्षमता सीधे रूप में अच्छी तरह शामिल हैं। Here's an example.

+0

Cryode, मैं मॉडल घटनाक्रम की कोशिश की और यह काम करता है - लेकिन आंशिक रूप से। मुझे समझाने दो। असली स्थिति 3 टेबल है: उपयोगकर्ता, घटनाक्रम, टिप्पणियाँ। घटनाओं में 0 .. कोई टिप्पणी नहीं है। निम्नलिखित [लिंक] (http://stackoverflow.com/questions/17243637/laravel-4-cascading-soft-deletes), मैंने बूट() विधि में उपयोगकर्ता और घटनाओं दोनों में तर्क जोड़ा। अब: softDelete ईवेंट, अपेक्षित: softDelete टिप्पणियां, परिणाम: ठीक है; softDelete उपयोगकर्ता, अपेक्षित: softDelete घटनाक्रम, परिणाम: ठीक है, उन घटनाओं के लिए softDelete टिप्पणियां, परिणाम: केओ। ऐसा लगता है कि हटाना पहले "स्तर" से आगे नहीं फैलता है .. – RedSash

+1

यह वह समाधान है जिसे मैंने स्वयं लागू किया है। मैं सबसे पहले उन रिश्तों का नक्शा निकालता हूं जो मेरे सभी मॉडल एक-दूसरे के साथ होते हैं और फिर मेरे मॉडल के भीतर वाक्प्रचार बढ़ाने के लिए हटाए गए तरीकों को लिखते हैं जिन्हें हटाना चाहिए। आखिरकार यह एक आसानी से मुर्गा हुआ कार्य है क्योंकि मैं यह दिखाने के लिए यूनिट-टेस्ट लिखता हूं कि कैस्केड प्रभाव केवल उस पर प्रभाव डालता है जो इसके लिए होता है। इस प्रकार उपयोगकर्ता उपयोगकर्ता रिकॉर्ड्स को हटाते हैं जिन्हें हटाएं, फिर UserRecordsMeta को हटाएं और इसी तरह से कॉल करें। – carbontwelve

0

यदि मैं सही ढंग से समझता हूं, तो आप दोनों टेबलों में सॉफ्टडेलेट को कैस्केड करने की कोशिश कर रहे हैं?

मुझे लगता है कि ऑन अपडेट कैस्केड के साथ ऐसा करने का सही दृष्टिकोण नहीं है। मैं यह बताने की कोशिश करूंगा कि क्यों ...

ऐसा करने का प्रयास करने के लिए आपको समग्र कुंजी के लिए विदेशी कुंजी का रिश्ता बनाना होगा।

यानी आपको (events.user_id और delete_at) को (user.id और delete_at) से लिंक करने की आवश्यकता है। आप एक बदलते हैं, यह दूसरे को अपडेट करेगा।

सबसे पहले आपको अपने हटाए गए कॉलम कॉलम में एक डिफ़ॉल्ट नियम जोड़ना होगा, क्योंकि आप शून्य मानों पर लिंक नहीं कर सकते हैं।

तो दोनों तालिकाओं के लिए आपके माइग्रेशन के लिए जोड़ ... $table->softDeletes()->default('0000-00-00 00:00:00');

घटनाओं में फिर 'आईडी' और 'deleted_at'

Schema::table('users; function($table) { $table->unique(array('id','deleted_at')) });

का उपयोग कर अपने उपयोगकर्ता तालिका में जोड़े एक अद्वितीय कुंजी तालिका इस तरह एक विदेशी कुंजी बनाते हैं (अद्वितीय कुंजी के लिंक)

Schema::table('events; function($table) { $table->foreign(array('user_id','deleted_at'),'events_deleted_at_foreign_key')-> }->references(array('id','deleted_at'))->on('users')->onUpdate('CASCADE'));

इसे चलाएं, अब आपको यह पता लगाना चाहिए कि क्या आप अपने उपयोगकर्ता को नरम हटाते हैं, यह अपने 'ईवेंट को नरम हटा देगा।

हालांकि यदि आप अब किसी घटना को नरम करने का प्रयास करते हैं, तो यह विदेशी कुंजी संयम पर असफल हो जाएगा। आप क्यों पूछ सकते हैं !?

वैसे आप जो कर रहे हैं वह आईडी का उपयोग करके एक अभिभावक बाल संबंध बना रहा है, दोनों तालिकाओं में हटाए गए_एट। माता-पिता को अपडेट करना, बच्चे को अपडेट करेगा। और रिश्ता अखंड है। हालांकि अगर आप बच्चे को अपडेट करते हैं, तो रिश्ते अब टूटा हुआ है, जिससे बच्चे को टेबल में अनाथ के रूप में छोड़ दिया जाता है। यह विदेशी कुंजी संयम में विफल रहता है।

एक लंबे हवादार उत्तर को सूखें, लेकिन उम्मीद है कि आप जो करने की कोशिश कर रहे हैं, उसके बारे में एक अच्छी व्याख्या नहीं होगी और आपको अद्यतन अद्यतन के साथ ऐसा करने का प्रयास करने में काफी समय बचाएगा। या तो ट्राइगर्स में जाएं, और ट्रिगर एक ऐसा फ़ंक्शन है जिसे आप करने की कोशिश कर रहे हैं, या इसे अपने एप्लिकेशन में संभालें। व्यक्तिगत रूप से मैं इसे ट्राइगर्स के साथ करता हूं, इसलिए डेटाबेस अपनी स्वयं की इकाई बना रहता है और डेटा अखंडता को बनाए रखने के लिए किसी भी चीज़ पर भरोसा नहीं करना पड़ता है।

delimiter // 

प्रत्येक पंक्ति के लिए db.users पर अद्यतन करने के बाद TRIGGER soft_delete_child बनाएं शुरू यदि NEW.deleted_at <> OLD.deleted_at तो अद्यतन घटनाओं सेट deleted_at = NEW.deleted_at कहां events.user_id = NEW.id; अंत IF; अंत;

// डिलीमीटर;

2

आप इस पर विचार कर रहे हैं।

या तो सिर्फ घटनाओं को हटाना सही इससे पहले कि आप उन को हटा दें:

$user->events()->delete(); 
$user->delete(); 

या एक ग्राहक उपयोगकर्ता मॉडल में समारोह को नष्ट बनाएँ:

public function customDelete(){ 
    $this->events()->delete(); 
    return $this->delete(); 
} 

तुम भी एक मॉडल पर्यवेक्षक और घड़ी जोड़ सकता है घटना को हटाने या हटाने के लिए, लेकिन ऊपर वर्णित परिदृश्य में, पिछले दो तरीकों का एक और आसान समाधान होगा।

http://laravel.com/docs/4.2/eloquent#model-observers

संबंधित मुद्दे