일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- MySQL
- 업비트
- C
- TiL
- upbit
- Laravel
- Ubuntu 20.04
- FMS
- 20.04
- 라즈비안
- 옵지
- 옵티머스 g
- 라라벨
- 옵G
- 회고
- codeigniter
- 코드이그나이터
- 맥
- 옵티머스g
- Selenium
- ubuntu
- 맛집
- 제주도
- 셀레니움
- 우분투 20.04
- 프레임워크
- 우분투
- php
- 라즈베리파이
- Raspberry Pi
- Today
- Total
평범한 이야기들
[TIL] PHP Laravel - Database #4 엘로퀀트(Eloquent) - 1 본문
엘로퀀트 #1
엘로퀀트 (Eloquent) 액티브 레코드 ORM : 테이블에 연결된 클래스를 이용해 CRUD를 쉽게 할 수 있음
여러 데이터베이스 작업을 하나의 인터페이스로 처리할 수 있는 데이터베이스 추상화 레이어
// 간단한 엘로퀀트 예
public function save(Request $request)
{
// 사용자의 입력으로부터 새로운 연락처 데이터를 생성하고 저장
$contact = new Contact();
$contact->first_name = $request->input('first_name');
$contact->last_name = $request->input('last_name');
$contact->email = $request->input('email');
$contact->save(); // 저장
return redirect('contacts');
}
관례에 의해 테이블명을 알아내고 이를 통해 테이블을 제어한다 (모델이 Contact면 테이블명은 contacts )
모델명은 Camel 표기법, 테이블명은 snake 표기법 (BillingAccount → billing_accounts)
엘로퀀트 모델 생성
~ php artisan make:model Contact
# app/Models/Contact.php 파일 생성, 모델 기본구조로 되어있음.
#모델 생성시 해당 모델 마이그레이션도 함께 하기
~ php artsaan make:model Contact --migration
엘로퀀트 모델이 연결되는 테이블 명을 변경할 때
protected $table = '변경할 테이블명';
라라벨은 기본적으로 테이블에 id라는 자동으로 증가되는 정수형 기본 키가 있다고 가정
테이블의 기본 키 이름이 다른 경우 모델 클래스에서 변경
// 기본 키 지정
protected $primaryKey = '필드명';
// 자동증가 되지 않게 막으려면
public $incrementing = false;
라라벨은 모든 테이블에 created_at, updated_at 타임스탬프 칼럼을 가지고 있다고 생각
// created_at, updated_at 칼럼이 없을때
public $timestamps = false;
// 유닉스 타임을 기반으로 한 초 형태 (time()과 동일한 형태)
protected $dateFormat = "U";
엘로퀀트를 사용해 데이터 조회
// 전체 데이터 가져오기
$allContacts = Contact::all();
// 조건 추가
$vipContacts = Contact::where('vip',true)->get();
first()
, firstOrFail()
, find()
, findOrFail()
메서드와 같이 하나의 레코드를 반환하는 경우에는 엘로퀀트 클래스의 인스턴스 반환
get()
은 여러 개의 레코드를 반환
많은 양의 레코드를 처리할 때 chunk()
메서드를 이용해서 작업
Contact::chunk(100, function($contacts) {
foreach($contacts as $contact) {
// 작업 진행
}
}
엘로퀀트를 사용해 데이터 추가 / 수정
데이터 추가
$contact = new Contact;
$contact->name = 'HongGilDong';
$contact->email = 'hong@hong.com';
$contact->save();
// 또는
$contact = new Contact([
'name' => 'HongGilDong',
'email' => 'hong@hong.com',
]);
$contact->save();
// 또는
$contact = Contact::create([
'name' => 'HongGilDong',
'email' => 'hong@hong.com',
]);
위 2가지 방법은 save() 메서드 호출 전까지 DB 저장 안 함, 마지막 방법은 바로 DB에 저장
데이터 수정
$contact = Contact::find(1);
$contact->email = 'hong2@hong.com';
$contact->save();
엘로퀀트 인스턴스를 조회하고 updqte 메서드에 배열을 전달해 수정하는 방법
Contact::where('created_at', '<', now()->subYear())->update(['longevity' => 'ancient']);
// 또는
$contact = Contact::find(1);
$contact->update(['longevity' => 'ancient']);
대량 할당
fillable 속성 값은 메서드에 배열을 전달할 때, 변경하면 안 되는 속성 값이 실수로 변경되는 일을 막기 위해 존재
fillable에 정의된 속성 값만 변경됨
class Contact
{
protected $fillable = ['name', 'email']; // 정의된 내용만 수정 가능
// 또는
protected $guarded = ['id','created_at','owner_id']; // 정의된 내용은 수정 불가
}
firstOrCreate()
, firstOrNew()
는 값을 가지고 있는 데이터를 조회, 없으면 새로 만드는 메서드
firstOrCreate()
는 DB에 저장 후 인스턴스 반환 firstOrNew()
는 인스턴스만 반환
엘로퀀트를 사용한 데이터 삭제
기본적인 삭제
$contact = Contact::find(4);
$contact->delete();
Contact::destroy(1);
// 또는
Contact::destroy([1,5,6]);
// 체이닝으로도 가능
Contact::where('updateed_at','<',now()->subYear())->delete();
소프트 삭제
소프트 삭제는 실제 삭제되지 않고 플래그를 이용해 삭제된 것처럼 보이는 기능
소프트 삭제 활성화 방법
- deleted_at 칼럼 추가
- 엘로퀀트 모델에서 SoftDeletes 트레이트를 추가
- 모델의 $dates 속성에 deleted_at 칼럼을 추가
// 1. 마이그레이션에서 소프트 삭제 칼럼 추가
Schma::table('contact',function(Blueprint $table){
$table->softDeletes();
});
// 2. 트레이트 추가
// 3. $dates 속성에 칼럼 추가.
class Contact extends Model
{
use SoftDeletes; // 트레이트 사용
protected $dates = ['deleted_at']; // 이 칼럼이 date 포맷이라고 알려준다.
}
소프트 삭제된 레코드 조회
// 삭제된 레코드도 포함되서 조회
$allHistoryContacts = Contact::withTrashed()->get();
// `trashed()` 메서드를 이용해 삭제 여부 확인
if($contact->trashed()){
// 로직 수행
}
//삭제된 레코드만 조회
$deletedContacts = Contact::onlyTrashed()->get();
소프트 삭제된 레코드 복원
$contact->restore();
//또는
Contact::onlyTrashed()->where('vip', true)->restore();
소프트 삭제된 레코드 완전 삭제
$contact->forceDelete();
// 또는
Contact::onlyTrashed()->forceDelete();
스코프-범위 제한 기능
로컬 스코프
// 두조건을 한번에 처리하는 방법 "로컬스코프"
$activeVips = Contact::where('vip',true)->where('trial',false)->get();
// app/Models/Contact.php
...
public function scopeActiveVips($query)
{
return $query->where('vip',true)->where('trial',false);
}
...
// 그 후 호출
$activeVips = Contact::activeVips()->get();
인자를 요하는 로컬 스코프
public function scopeStatus($query, $status)
{
return $query->where('status',$status);
}
// 호출
$friends = Contact::status('friend')->get();
라라벨 5.8 이상에서는 스코프 2개 사이에 orWhere() 메서드를 체이닝 가능함.
글로벌 스코프
글로벌 스코프를 정의하는 데에는 클로저를 사용하는 방법, 별도의 클래스를 사용하는 방법 2가지 존재
두 가지 모두 정의된 스코프를 적용하고자 하는 엘로퀀트 모델의 boot()
메서드에서 등록
클로저를 사용해 글로벌 스코프 추가 방법
...
class Contact extends Model
{
protected statisc function boot()
{
parent::boot();
static::addGlobalScope('active', function(Builder $builder) {
$builder->where('active', true);
});
}
}
// active 라는 글로벌 스코프 추가
// 이 모델을 사용해 쿼리를 작성하면 모든 쿼리가 active가 true인 데이터에만 적용되도록 범위 제한
클래스를 추가해 글로벌 스코프 추가 방법
<?php
namespace App\Models\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
return $builder->where('active',true);
}
}
// 위와 같이 클래스를 생성 후 사용하고자 하는 엘로퀀트 모델의 boot() 메서드에서 스태틱 addGlobalScope() 메서드 인자로 전달.
...
protected statisc function boot()
{
parent::boot();
static::addGlobalScope(new ActiveScope);
}
...
글로벌 스코프 적용하지 않기
withoutGlobalScope()
, withoutGlobalScopes()
메서드 사용
$allContacts = Contact::withoutGlobalScope('active')->get();
// 별도의 스코프 클래스를 사용해 등록한 경우
Contact::withoutGlobalScope(ActiveScope::class)->get();
Contact::withoutGlobalScopes([ActiveScope::class, VipScope::class])->get();
// 모든 글로벌 스코프를 적용하지 않는 방법
Contact::withoutGlobalScopes()->get();