1. 쿼리빌더
SQL을 쉽게작성하며 SQL injection방지를 위해 사용
인스턴스 생성
DB::table('테이블명')으로 쿼리빌더 인스턴스취득
결과추출예제
$results = DB::table('users')->where('votes', '>', 100)->get();
// select('컬럼명')은 where앞에 들어갈수있지만 선택사항이다
데이터 형태
Illuminate\Support\Collection 리스트 >> stdClass 객체의 인스턴스
2. ELOQUENT ORM
ORM이다
DB의 테이블을 모델 객체로 관리할수있게 함
모델은 대부분의 쿼리빌더의 메서드를 사용할수있다 (모델 == 쿼리빌더 인스턴스)
모델에 생성 및 사용
$users = User::where('votes', '>', 100)->get();
foreach ($users as $user) {
echo $user->name;
}
데이터 형태
Illuminate\Database\Eloquent\Collection 리스트 >> 모델 인스턴스
3. 꼭 알면 좋은점
쿼리빌더는 결과로 stdClass를 반환한다
엘로퀀트는 결과로 모델인스턴스를 반환한다
엘로퀀트의 모델은 쿼리빌더의 기능을 포함하기때문에 where등의 쿼리빌더 기능이 사용 가능하다
( → 그러나 같은 쿼리빌더를 사용하는 아님)
둘다 where등의 기능은 같지만 쿼리빌더의 네임스페이스가 다르다
그래서 기능은 같은데 반환하는 값이 다르다 (쿼리빌더면 stdClass, 엘로퀀트면 모델인스턴스)
쿼리빌더의 DB::table('users')->where의 where과 엘로퀀트의 User::where의 where은 둘다 builder(쿼리빌더)인스턴스를 반환한다 그러나 이 둘은 각자 다른 쿼리빌더의 인스턴스이다 쿼리빌더 -> Illuminate\Database\Query\Builder 엘로퀀트 -> Illuminate\Database\Eloquent\Builder 동작하는 기능은 둘다 쿼리빌더의 where과 동일하지만 반환하는 값은 다르다 쿼리빌더 -> Illuminate\Database\Query\Builder -> get()사용시 -> stdClass 엘로퀀트 -> Illuminate\Database\Eloquent\Builder -> get()사용시 -> 모델인스턴스
같은 기능의 where이지만 각각 쿼리와 엘로퀀트에 속하는 where이라서 get()을 사용하는 경우 반환 받는 값이 쿼리는 stdClass와 엘로퀀트는 model인스턴스로 달라진다
3. 대량할당과 fillable
일반적인 데이터 저장 vs 대량할당
// 일반데이터 저장
$user = new User();
$user->name = 'John Doe';
$user->email = 'johndoe@example.com';
$user->password = 'secret';
$user->save();
// 대량할당 1
$user = User::create([
'name' => 'John Doe',
'email' => 'johndoe@example.com',
'password' => 'secret'
]);
// 대량할당 2
$user = new User();
$user->fill([
'name' => 'John Doe',
'email' => 'johndoe@example.com',
'password' => 'secret'
]);
$user->save();
일반적인 데이터의 저장은 하나하나 객체의 프로퍼티를 지정한뒤 저장해야한다
그러나 대량할당같은 경우는 (키/값)배열의 형태로 저장이 가능하다
그렇기 때문에 대량할당이 매우 간단하지만 보안적으로 취약하다
보안적으로 예방하기 위해 $fillable을 사용한다
// name과 email은 대량할당을 허용한다는 뜻임 (화이트리스트방법)
// 반대로 $guarded를 사용해서 특정칼럼만 막을수있다(블랙리스트방법)
class User extends Model
{
protected $fillable = ['name', 'email'];
}
엘로퀀트 모델의 이벤
엘로퀀트의 모델이 등록,수정,검색등의 처리가 일어날때 발생됨
retrieved, creating, created, updating, updated, saving, saved, deleting, deleted
create를 예로 들면 -ing로 끝나는 경우 새로운 모델객체가 생성된기 전
-ed로 끝나는건 새로운 모델객체가 생성된 후에 발생한다는 뜻이다
아래의 예제를 새로운 게시글 모델이 생성되기 전 단계에서 postId라는 컬럼에 uuid를 생성한다는 의미가 된다
protected static function booted()
{
// 게시글의 생성되기전에 호출됨
static::creating(function ($posts) {
$posts->postId = Str::uuid()->toString();
});
}
취득 가능한 사용자 컬럼 추가
엘로퀀트 모델의 Accessors기능이며 해당 컬럼의 값을 조회할시 사용자 정의가 가능하다
contentShort라는 메서드명이라면 $post->content_short로 취득가능하다
// 취득가능한 사용자 칼럼 추가 (Accessors)
protected function contentShort(): Attribute
{
return Attribute::make(
get: function () {
// HTML태그제거후 HTML엔터티도 제거후,첫 100글자만 저장
return mb_substr(html_entity_decode(strip_tags($this->attributes['content'])), 0, 150);
},
);
}
칼럼의 기본값 설정
postViewCount컬럼이 있다는 가정하에 해당 컬럼의 기본값으 0이 된다
// 칼럼 기본값 설정
protected $attributes = [
'postViewCount' => 0,
];
엘로퀀트가 기본적으로 제공하는 데이터 컬럼변경
created_at,updated_at등의 기본 데이터 컬럼이 테이블과 연동이 되어있는데
해당 제공 컬럼이 아니라 내가 작성한 createdDate컬럼등과 연동하고싶을때 사용
// 기본 날짜 속성명 변경
const CREATED_AT = 'createdDate';
const UPDATED_AT = 'updatedDate';
테이블 생성시 기억하면 좋은점
아래를 지키면 엘로퀀트를 사용하기 좋다
테이블명은 복수형
기본키명은 id가 좋다 (1:N등의 연관관계 추정시 편리 // id)
칼럼명은 스네이크 케이스 (1:N등의 연관관계시 자동으로 추정해서 연관시켜줌 // 외래키등록시 자동으로 post_id등으로 찾음)
생성시간,수정시간은 자동으로 생성해준다 (created_at컬럼명 안쓰면 모델에 const CREATED_AT = 'createdDate';등으로 직접적어야함)
마이그레이션사용
엘로퀀트 관련 자주쓰이는 함수 (쿼리빌더가 아님/쿼리빌더랑 중복해서 사용되는 함수있음)
1. `all()`: 모델에 해당하는 모든 레코드를 가져옵니다.
// 쿼리빌더에선 get()가 같은 기능을 한다
2. `find($id)`: 주어진 기본 키(id)에 해당하는 레코드를 가져옵니다.
// 쿼리빌더에선 where()이 같은 기능을 한다
// DB::table('posts')->where('id', 1)->first(); // id가 1인 레코드를 검색
3. `findOrFail($id)`: 주어진 기본 키에 해당하는 레코드를 가져오지만, 레코드가 없을 경우 `ModelNotFoundException` 예외를 발생시킵니다.
4. `create(array $attributes)`: 새로운 레코드를 생성하고 데이터베이스에 저장합니다.
5. `update(array $attributes)`: 기존 레코드의 속성을 업데이트합니다.
6. `delete()`: 레코드를 삭제합니다.
7. `where($column, $operator = null, $value =
`: 조건절을 추가하여 레코드를 필터링합니다.
8. `first()`: 첫 번째 레코드를 가져옵니다.
9. `pluck($column)`: 지정된 컬럼의 값들을 배열로 반환합니다.
10. `count()`: 조회된 레코드의 수를 반환합니다.
11. `orderBy($column, $direction = 'asc')`: 지정된 컬럼을 기준으로 정렬합니다.
12. `limit($value)`: 결과의 개수를 제한합니다.
13. `with($relationship)`: Eager Loading을 사용하여 관계를 사전에 로드합니다.
14. `whereHas($relationship, $callback)`: 관계를 사용하여 서브 쿼리를 수행합니다.
15. `has($relationship)`: 지정된 관계가 있는 레코드만 가져옵니다.
16. `firstOrCreate($attributes)`: 주어진 속성으로 레코드를 검색하고, 없으면 새로운 레코드를 생성하여 저장합니다.
(디비에 저장하고 반환)
17. `firstOrNew($attributes)`: 주어진 속성으로 레코드를 검색하고, 없으면 새로운 모델 인스턴스를 생성합니다. 저장은 하지 않습니다.
(디비에 저장은 안하고 생성한 모델인스턴스만 반환)
18. increment('컬럼명') // 해당컬럼명의 데이터를 1씩 증가시킨다
$post->increment('postViewCount');
참조
https://zetawiki.com/wiki/Laravel_%EC%BF%BC%EB%A6%AC%EB%B9%8C%EB%8D%94
https://zetawiki.com/wiki/Laravel_%EC%97%98%EB%A1%9C%ED%80%80%ED%8A%B8_%EB%AA%A8%EB%8D%B8
https://zetawiki.com/wiki/Laravel_%EC%97%98%EB%A1%9C%ED%80%80%ED%8A%B8%EC%99%80_%EC%BF%BC%EB%A6%AC%EB%B9%8C%EB%8D%94_%EC%B0%A8%EC%9D%B4%EC%A0%90
https://laravel.kr/docs/9.x/eloquent-relationships#1:N(%EC%9D%BC%EB%8C%80%EB%8B%A4)%20%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84%20%EC%A0%95%EC%9D%98%ED%95%98%EA%B8%B0