이 구문을 사용하여 행을 삭제할 때 :
$user->delete();
예를 들어 자동으로 수행 할 수 있도록 일종의 콜백을 첨부하는 방법이 있습니까?
$this->photo()->delete();
가급적 모델 클래스 내부.
이 구문을 사용하여 행을 삭제할 때 :
$user->delete();
예를 들어 자동으로 수행 할 수 있도록 일종의 콜백을 첨부하는 방법이 있습니까?
$this->photo()->delete();
가급적 모델 클래스 내부.
답변:
이것이 Eloquent 이벤트 ( 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()
각 어린이가 어떤 이유로 인해 한 명만 제거되는 대신 모든 수준에서 어린이를 제거하도록해야했습니다.
Photos
있다 tags
당신은에서 동일한 작업을 수행 Photos
(에 즉 모델 deleting
방법 $photo->tags()->delete();
)은 트리거를 얻을 수 없다. 그러나 내가 그것을 for
루프로 만들고 다음과 for($user->photos as $photo) { $photo->delete(); }
같이하면 tags
또한 삭제됩니다! 단지 참고
마이그레이션에서 실제로 설정할 수 있습니다.
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
출처 : http://laravel.com/docs/5.1/migrations#foreign-key-constraints
제약 조건의 "삭제시"및 "업데이트시"속성에 대해 원하는 작업을 지정할 수도 있습니다.
$table->foreign('user_id') ->references('id')->on('users') ->onDelete('cascade');
참고 :이 답변은 Laravel 3 용으로 작성되었습니다 . 따라서 최신 버전의 Laravel에서 잘 작동하거나 작동하지 않을 수 있습니다.
실제로 사용자를 삭제하기 전에 관련된 모든 사진을 삭제할 수 있습니다.
<?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();
}
}
도움이 되었기를 바랍니다.
사용자 모델에서의 관계 :
public function photos()
{
return $this->hasMany('Photo');
}
기록 및 관련 삭제 :
$user = User::find($id);
// delete related
$user->photos()->delete();
$user->delete();
이 문제를 해결하는 방법에는 세 가지가 있습니다.
1. 모델 부팅시 Eloquent 이벤트 사용 (참조 : 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();
});
}
}
2. Eloquent 이벤트 옵저버 사용하기 (ref : https://laravel.com/docs/5.7/eloquent#observers )
AppServiceProvider에서 다음과 같이 관찰자를 등록합니다.
public function boot()
{
User::observe(UserObserver::class);
}
다음으로 다음과 같이 Observer 클래스를 추가합니다.
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');
Laravel 5.2부터 문서에는 이러한 종류의 이벤트 핸들러가 AppServiceProvider에 등록되어야한다고 명시되어 있습니다.
<?php
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::deleting(function ($user) {
$user->photos()->delete();
});
}
더 나은 애플리케이션 구조를 위해 클로저 대신 별도의 클래스로 이동한다고 가정합니다.
photos()
, 당신은 또한 조심해야합니다 -이 과정 것 없는 당신이 모델을 삭제 손자를로드하지 않을 때문이다. 삭제 관련 이벤트를 발생 시키 려면 루프를 반복하고 photos
(가 아니라 참고 photos()
) delete()
메서드를 모델로 실행해야합니다.
이에 대한 delete
방법을 재정의하는 것이 좋습니다 . 이렇게하면 delete
메서드 자체에 DB 트랜잭션을 통합 할 수 있습니다 . 이벤트 방식을 사용하는 경우 delete
호출 할 때마다 DB 트랜잭션 으로 메서드 호출을 가려야합니다 .
당신의에서 User
모델.
public function delete()
{
\DB::beginTransaction();
$this
->photo()
->delete()
;
$result = parent::delete();
\DB::commit();
return $result;
}
선택한 답변에 대해 자세히 설명하려면 관계에 삭제해야하는 하위 관계가있는 경우 먼저 모든 하위 관계 레코드를 검색 한 다음 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();
});
}
}
관계 ID 열만 쿼리하여 성능을 향상시킬 수도 있습니다.
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();
});
}
}
제 경우에는 데이터베이스 테이블이 삭제시 Cascade가있는 외래 키가있는 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);
}
기본 laravel db 연결을 사용하지 않는 경우 다음을 수행해야합니다.
DB::connection('connection_name')->pdo->beginTransaction();
DB::connection('connection_name')->pdo->commit();
DB::connection('connection_name')->pdo->rollBack();
예,하지만 @supersan이 주석에서 상단에 언급했듯이 QueryBuilder에서 delete ()하면 모델 자체를로드하지 않고 해당 모델에서 delete ()를 호출하기 때문에 모델 이벤트가 발생하지 않습니다.
이벤트는 모델 인스턴스에서 삭제 기능을 사용하는 경우에만 발생합니다.
그래서이 벌은 이렇게 말했습니다.
if user->hasMany(post)
and if post->hasMany(tags)
사용자를 삭제할 때 post 태그를 삭제하려면 반복 $user->posts
해서 호출해야합니다.$post->delete()
foreach($user->posts as $post) { $post->delete(); }
-> Post에서 삭제 이벤트가 발생합니다.
VS
$user->posts()->delete()
- 우리가 실제로 포스트 모델을로드하지 않기 때문에>이 게시물의 삭제 이벤트가 발생하지 않습니다는 (우리는 같은 SQL을 실행 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()
액세스 할 수 있도록 쿼리 에 추가해야했습니다. 예 : SourceUser::where('id', '=', $id)->first()->delete();