আমি যখন এই বাক্য গঠনটি ব্যবহার করে একটি সারি মুছব:
$user->delete();
বাছাইয়ের কলব্যাক সংযুক্ত করার কোনও উপায় আছে, যাতে এটি উদাহরণস্বরূপ স্বয়ংক্রিয়ভাবে এটি করতে পারে:
$this->photo()->delete();
প্রায়শই মডেল-শ্রেণীর ভিতরে।
আমি যখন এই বাক্য গঠনটি ব্যবহার করে একটি সারি মুছব:
$user->delete();
বাছাইয়ের কলব্যাক সংযুক্ত করার কোনও উপায় আছে, যাতে এটি উদাহরণস্বরূপ স্বয়ংক্রিয়ভাবে এটি করতে পারে:
$this->photo()->delete();
প্রায়শই মডেল-শ্রেণীর ভিতরে।
উত্তর:
আমি বিশ্বাস করি এটি শ্রুতচিত্ত ইভেন্টগুলির জন্য একটি উপযুক্ত ব্যবহারের ক্ষেত্রে ( http://laravel.com/docs/eloquent#model-events )। আপনি ক্লিনআপটি করতে "মোছা" ইভেন্টটি ব্যবহার করতে পারেন:
class User extends Eloquent
{
public function photos()
{
return $this->has_many('Photo');
}
// this is a recommended way to declare event handlers
public static function boot() {
parent::boot();
static::deleting(function($user) { // before delete() method call this
$user->photos()->delete();
// do the rest of the cleanup...
});
}
}
রেফারেন্সিয়াল অখণ্ডতা নিশ্চিত করার জন্য আপনার সম্ভবত পুরো জিনিসটি কোনও লেনদেনের মধ্যে রাখা উচিত ..
foreach($user->photos as $photo)
, তারপরে $photo->delete()
এটি নিশ্চিত করতে যে কোনও কারণে এটি ঘটছে কেবল তার পরিবর্তে প্রতিটি সন্তানের সমস্ত স্তরে তার শিশুদের সরানো হয়েছে had
Photos
থাকে tags
এবং আপনি Photos
মডেলটিতেও একই কাজ করেন (অর্থাত্ deleting
পদ্ধতিতে $photo->tags()->delete();
) এটি কখনই ট্রিগার হয় না। তবে আমি যদি এটিকে একটি for
লুপ তৈরি করি এবং এর মতো কিছু করি for($user->photos as $photo) { $photo->delete(); }
তবে tags
তাও মুছে ফেলা হবে! সবে FYI
আপনি আপনার মাইগ্রেশনগুলিতে এটি সেট আপ করতে পারেন:
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
সূত্র: http://laravel.com/docs/5.1/migration#foreign-key-constraints
আপনি "মুছে ফেলতে" এবং "আপডেটে" সীমাবদ্ধতার বৈশিষ্ট্যগুলির জন্য পছন্দসই কর্মটি নির্দিষ্ট করতে পারেন:
$table->foreign('user_id') ->references('id')->on('users') ->onDelete('cascade');
দ্রষ্টব্য : এই উত্তরটি লারাভেল 3 এর জন্য লেখা হয়েছিল । সুতরাং সম্ভবত লারাভেলের সাম্প্রতিক সংস্করণে ভাল কাজ করতে পারে এবং নাও পারে।
ব্যবহারকারীকে প্রকৃতপক্ষে মুছে ফেলার আগে আপনি সম্পর্কিত সমস্ত ফটো মুছতে পারেন।
<?php
class User extends Eloquent
{
public function photos()
{
return $this->has_many('Photo');
}
public function delete()
{
// delete all related photos
$this->photos()->delete();
// as suggested by Dirk in comment,
// it's an uglier alternative, but faster
// Photo::where("user_id", $this->id)->delete()
// delete the user
return parent::delete();
}
}
আশা করি এটা সাহায্য করবে.
$this->photos()->delete()
। photos()
ক্যোয়ারী রচয়িতা বস্তুর ফেরৎ।
ব্যবহারকারী মডেল সম্পর্কিত:
public function photos()
{
return $this->hasMany('Photo');
}
রেকর্ড এবং সম্পর্কিত মুছুন:
$user = User::find($id);
// delete related
$user->photos()->delete();
$user->delete();
এটি সমাধানের জন্য 3 টি পদ্ধতি রয়েছে:
১. মডেল বুটে সুস্পষ্ট ইভেন্টগুলি ব্যবহার করা (রেফার্স: https://laravel.com/docs/5.7/eloquent#events )
class User extends Eloquent
{
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->photos()->delete();
});
}
}
২. স্পষ্টত ইভেন্ট পর্যবেক্ষক ব্যবহার করে (রেফার্স: https://laravel.com/docs/5.7/eloquent#observers )
আপনার অ্যাপসোসভারপ্রভাইডারে, পর্যবেক্ষককে এর মতো নিবন্ধ করুন:
public function boot()
{
User::observe(UserObserver::class);
}
এরপরে, এর মতো একটি পর্যবেক্ষক শ্রেণি যুক্ত করুন:
class UserObserver
{
public function deleting(User $user)
{
$user->photos()->delete();
}
}
3. ব্যবহার ফরেন কী বাধ্যবাধকতা (সুত্র: https://laravel.com/docs/5.7/migrations#foreign-key-constraints )
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
লারাভেল ৫.২ হিসাবে, ডকুমেন্টেশনে উল্লেখ করা হয়েছে যে এই ধরণের ইভেন্ট হ্যান্ডলারগুলি অ্যাপসোসাইসপ্রোভাইডারটিতে নিবন্ধিত হওয়া উচিত:
<?php
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::deleting(function ($user) {
$user->photos()->delete();
});
}
আমি এমনকি তাদের আরও ভাল অ্যাপ্লিকেশন কাঠামোর জন্য ক্লোজার পরিবর্তে পৃথক ক্লাসে স্থানান্তরিত মনে করি।
Eloquent::observe()
পদ্ধতিটি 5.2 তেও পাওয়া যায় এবং অ্যাপসোসভারপ্রাইভাইডার থেকে ব্যবহার করা যেতে পারে।
photos()
যত্নবান হওয়া দরকার - এই প্রক্রিয়াটি নাতি-নাতনিদের মুছবে না কারণ আপনি মডেলগুলি লোড করছেন না। মুছে ফেলা-সম্পর্কিত ইভেন্টগুলিকে আগুন জ্বালানোর জন্য আপনাকে মডেল হিসাবে লুপ ওভার করতে হবে photos
(নোট, নয় photos()
) এবং delete()
পদ্ধতিটি ফায়ার করতে হবে।
আপনি যদি এর delete
জন্য পদ্ধতিটি ওভাররাইড করেন তবে ভাল । এই পদ্ধতিতে, আপনি delete
নিজেই পদ্ধতিতে ডিবি লেনদেনকে অন্তর্ভুক্ত করতে পারেন । আপনি যদি ইভেন্টের উপায়টি ব্যবহার করেন, delete
প্রতিবার আপনি যখন কল করবেন তখন আপনাকে নিজের পদ্ধতিটির কলটি ডিবি লেনদেনের সাথে আবরণ করতে হবে।
আপনার User
মডেল।
public function delete()
{
\DB::beginTransaction();
$this
->photo()
->delete()
;
$result = parent::delete();
\DB::commit();
return $result;
}
আমার ক্ষেত্রে এটি বেশ সহজ ছিল কারণ আমার ডাটাবেস টেবিলগুলি হ'ল মুছে ফেলা ক্যাসকেড সহ বিদেশী কী সহ InnoDB।
সুতরাং এই ক্ষেত্রে যদি আপনার ফটোগুলির টেবিলটিতে ব্যবহারকারীর জন্য কোনও বিদেশী কী রেফারেন্স থাকে তবে আপনাকে যা করতে হবে তা হল হোটেলটি মুছতে হবে এবং ডেটা বেস দ্বারা ক্লিনআপ করা হবে, ডেটা বেস থেকে সমস্ত ফটো রেকর্ড মুছে ফেলা হবে বেস।
আমি বস্তুটি নিজেই মোছার আগে সবকিছুকে বিচ্ছিন্ন করে সংগ্রহের মাধ্যমে পুনরাবৃত্তি করব।
এখানে একটি উদাহরণ:
try {
$user = user::findOrFail($id);
if ($user->has('photos')) {
foreach ($user->photos as $photo) {
$user->photos()->detach($photo);
}
}
$user->delete();
return 'User deleted';
} catch (Exception $e) {
dd($e);
}
আমি জানি এটি স্বয়ংক্রিয় নয় তবে এটি খুব সাধারণ।
আরেকটি সহজ পদ্ধতির মডেলটি একটি পদ্ধতি সহ সরবরাহ করা হবে। এটার মত:
public function detach(){
try {
if ($this->has('photos')) {
foreach ($this->photos as $photo) {
$this->photos()->detach($photo);
}
}
} catch (Exception $e) {
dd($e);
}
}
তারপরে আপনি যেখানে প্রয়োজন সেখানে কেবল এটিকে কল করতে পারেন:
$user->detach();
$user->delete();
অথবা আপনি যদি এটি চান তবে এটি করতে পারেন, কেবল অন্য একটি বিকল্প:
try {
DB::connection()->pdo->beginTransaction();
$photos = Photo::where('user_id', '=', $user_id)->delete(); // Delete all photos for user
$user = Geofence::where('id', '=', $user_id)->delete(); // Delete users
DB::connection()->pdo->commit();
}catch(\Laravel\Database\Exception $e) {
DB::connection()->pdo->rollBack();
Log::exception($e);
}
দ্রষ্টব্য আপনি যদি ডিফল্ট লারাভেল ডিবি সংযোগটি ব্যবহার না করেন তবে আপনাকে নিম্নলিখিতগুলি করতে হবে:
DB::connection('connection_name')->pdo->beginTransaction();
DB::connection('connection_name')->pdo->commit();
DB::connection('connection_name')->pdo->rollBack();
নির্বাচিত উত্তরের বিশদটি জানাতে, যদি আপনার সম্পর্কের মধ্যেও এমন সম্পর্ক থাকে যা অবশ্যই মুছে ফেলা উচিত, আপনাকে প্রথমে সমস্ত শিশুর সম্পর্কের রেকর্ডগুলি পুনরুদ্ধার করতে হবে, তারপরে delete()
পদ্ধতিটি কল করুন যাতে তাদের মোছার ইভেন্টগুলিও যথাযথভাবে বরখাস্ত করা হয়।
আপনি উচ্চতর অর্ডার বার্তাগুলি দিয়ে সহজেই এটি করতে পারেন ।
class User extends Eloquent
{
/**
* The "booting" method of the model.
*
* @return void
*/
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->photos()->get()->each->delete();
});
}
}
আপনি কেবল সম্পর্কের আইডি কলামটি জিজ্ঞাসা করে কর্মক্ষমতা উন্নত করতে পারেন:
class User extends Eloquent
{
/**
* The "booting" method of the model.
*
* @return void
*/
public static function boot() {
parent::boot();
static::deleting(function($user) {
$user->photos()->get(['id'])->each->delete();
});
}
}
হ্যাঁ, তবে @ সুপারসন একটি মন্তব্যে উপরের মত বলেছেন, আপনি যদি কোয়েরি বিল্ডারে () মুছে ফেলেন তবে মডেল ইভেন্টটি বরখাস্ত করা হবে না, কারণ আমরা নিজেই মডেলটি লোড করছি না, তারপরে সেই মডেলটিতে মুছে ফেলা কল করুন।
ইভেন্টগুলি কেবল তখনই বরখাস্ত করা হয় যদি আমরা কোনও মডেল দৃষ্টান্তে মুছুন ফাংশনটি ব্যবহার করি।
সুতরাং, এই মৌমাছিটি বলেছেন:
if user->hasMany(post)
and if post->hasMany(tags)
ব্যবহারকারী মুছে ফেলার সময় পোস্ট ট্যাগ মুছতে, আমাদের পুনরাবৃত্তি করতে হবে $user->posts
এবং কল করতে হবে$post->delete()
foreach($user->posts as $post) { $post->delete(); }
-> এটি পোস্টে মোছার ইভেন্টটিকে আগুন ধরিয়ে দেবে
বনাম
$user->posts()->delete()
-> এটি পোস্টে মোছার ঘটনাকে আগুন ধরিয়ে দেবে না কারণ আমরা প্রকৃতপক্ষে পোস্ট মডেলটি লোড করি না (আমরা কেবলমাত্র এসকিউএল চালাচ্ছি: DELETE * from posts where user_id = $user->id
এবং এভাবে পোস্ট পোস্টটি এমনকি লোড হয় না)
আপনি বিকল্প হিসাবে এই পদ্ধতিটি ব্যবহার করতে পারেন।
কি হবে তা হ'ল আমরা ব্যবহারকারীর টেবিলের সাথে সম্পর্কিত সমস্ত টেবিল নিয়েছি এবং লুপিং ব্যবহার করে সম্পর্কিত ডেটা মুছে ফেলছি
$tables = DB::select("
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'users'
");
foreach($tables as $table){
$table_name = $table->TABLE_NAME;
$column_name = $table->COLUMN_NAME;
DB::delete("delete from $table_name where $column_name = ?", [$id]);
}
first()
যাতে আমি মডেল-ইভেন্ট যেমন অ্যাক্সেস করতে পারি যেমনUser::where('id', '=', $id)->first()->delete();
উত্স