라라벨 팁 한국어

라라벨 개발자들을 위한 멋진 Laravel 팁과 트릭 모음입니다. PR 및 아이디어를 환영합니다! 이 문서는 PovilasKoropMarceauKa 의 아이디어를 번역한 문서입니다.
2021 년 1 월 29 일 업데이트 : 현재 125 개의 팁 이 14 개 섹션으로 나뉩니다.

목차

DB 모델 및 Eloquent

Eloquent 날짜 관련 검색 메서드

whereDay() , whereMonth() , whereYear() , whereDate()whereTime() 함수로 날짜를 검색하십시오.
$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', '14:13:58')->get();

값의 증가 및 감소

일부 테이블에서 일부 DB 컬럼의 값을 증가 시키려면 increment() 함수를 사용하십시오. 아, 그리고 당신은 1만큼 증가시킬 수있을뿐만 아니라 50과 같은 어떤 숫자도 증가시킬 수 있습니다.
Post::find($post_id)->increment('view_count');
User::find($user_id)->increment('points', 50);

타임 스탬프 컬럼이 없을 때

DB 테이블에 타임 스탬프 필드 created_atupdated_at가 포함되어 있지 않은 경우, $timestamps = false를 사용하여 Eloquent 모델이 이 속성을 사용하지 않도록 지정할 수 있습니다.
class Company extends Model
{
public $timestamps = false;
}

옵저버로 로그인 한 사용자 지정

현재 로그인 한 사용자를 user_id 필드에 자동으로 지정되게하려면 make:observer 를 사용하고 creating() 메서드를 추가합니다.
class PostObserver
{
public function creating(Post $post)
{
$post->user_id = auth()->id();
}
}

소프트 삭제 : 다중 복원

소프트 삭제를 사용하면 한 문장으로 여러 행을 복원 할 수 있습니다.
Post::withTrashed()->where('author_id', 1)->restore();

Model::all의 컬럼 지정

Eloquent의 Model::all() 호출 할 때 반환 할 열을 지정할 수 있습니다.
$users = User::all(['id', 'name', 'email']);

실패하거나 실패하지 않기

findOrFail() 외에도 쿼리에 대한 레코드가없는 경우 404 페이지를 반환하는 Eloquent 메서드 firstOrFail()도 있습니다.
$user = User::where('email', '[email protected]')->firstOrFail();

열 이름 변경

Eloquent Query Builder에서 "as"를 지정하여 일반 SQL 쿼리처럼 다른 이름을 가진 열을 반환 할 수 있습니다.
$users = DB::table('users')->select('name', 'email as user_email')->get();

쿼리 결과에 대한 개별 수정

Eloquent 쿼리 후에 Collections에서 map() 함수를 사용하여 행을 수정할 수 있습니다.
$users = User::where('role_id', 1)->get()->map(function (User $user) {
$user->some_column = some_function($user);
return $user;
});

기본 타임 스탬프 필드 변경

Laravel이 아닌 데이터베이스로 작업하고 있고 타임스탬프 열의 이름이 다르다면 어떻게 해야할까요? 아마도 create_time 이나 update_time 같은 열이 있을 겁니다. 다행히도 모델에서 변경 할 수 있습니다.
class Role extends Model
{
const CREATED_AT = 'create_time';
const UPDATED_AT = 'update_time';
}

created_at을 손쉽게 정렬하기

이것을
User::orderBy('created_at', 'desc')->get();
더 쉽게 할 수 있습니다.
User::latest()->get();
기본적으로 latest()created_at을 이용하여 정렬합니다.
created_at 오름차순으로 정렬하는, 반대 메소드 oldest()도 있습니다.
User::oldest()->get();
또한 정렬할 열을 바꿀 수도 있습니다. 예를 들어 updated_at 를 사용하려면 아래처럼 사용하면 됩니다.
$lastUpdatedUser = User::latest('updated_at')->first();

레코드 생성시 자동으로 생성되는 열 값

레코드 생성시 DB 컬럼 값을 생성하려면 모델의 boot() 메소드에 추가합니다. 예를 들어 "position"필드가 있고 사용 가능한 다음 위치를 새 레코드에 할당하려면 (예 Country::max('position') + 1) 과 같이하십시오.
class Country extends Model {
protected static function boot()
{
parent::boot();
Country::creating(function($model) {
$model->position = Country::max('position') + 1;
});
}
}

DB Raw 쿼리 계산을 더 빠르게

whereRaw() 메서드와 같은 SQL 원시 쿼리를 사용하여 일부 DB 특정 계산을 Laravel이 아닌 쿼리에서 직접 수행하면 일반적으로 결과가 더 빠릅니다. 예를 들어, 등록 후 30 일 이상 활성 상태였던 사용자를 얻으려면 다음 코드를 사용하십시오. (역자: 단 이 경우는 ORM의 장점인 추상화의 이점을 얻지 못하고 특정 데이터베이스에 종속되는 사이드이펙트가 생길 수 있습니다. 이 부분을 감안하고 사용하시기 바랍니다. 이것은 사용하지 말라는 의미가 아닌 주의를 필요로 하는 의미로 남기는 글입니다.)
User::where('active', 1)
->whereRaw('TIMESTAMPDIFF(DAY, created_at, updated_at) > ?', 30)
->get();

한개 이상의 스코프

쿼리에서 하나 이상의 스코프를 사용하여 Eloquent에서 쿼리 스코프를 결합하고 연결할 수 있습니다.
모델:
public function scopeActive($query) {
return $query->where('active', 1);
}
public function scopeRegisteredWithinDays($query, $days) {
return $query->where('created_at', '>=', now()->subDays($days));
}
일부 컨트롤러 :
$users = User::registeredWithinDays(30)->active()->get();

카본을 전환해줄 필요가 없습니다

whereDate()를 이용해 오늘 기준의 레코드를 조회할 경우 Carbon의 now()를 사용할 수 있으며, 자동으로 날짜 형식으로 변환됩니다. 이때 ->toDateString()를 해줄 필요가 없습니다.
// 이럴땐
$todayUsers = User::whereDate('created_at', now()->toDateString())->get();
// 전환할 필요가 없습니다. 그냥 now()를 쓰세요
$todayUsers = User::whereDate('created_at', now())->get();

첫 글자로 그룹화

사용자 지정 조건별로 Eloquent 결과를 그룹화 할 수 있습니다. 사용자 이름의 첫 글자로 그룹화하는 방법은 다음과 같습니다.
$users = User::all()->groupBy(function($item) {
return $item->name[0];
});

열 업데이트 안 함

한 번만 설정하고 다시 업데이트하지 않으려는 DB 열이있는 경우 뮤 테이터를 사용하여 Eloquent Model에 해당 제한을 설정할 수 있습니다.
class User extends Model
{
public function setEmailAttribute($value)
{
if ($this->email) {
return;
}
$this->attributes['email'] = $value;
}
}

여러개를 찾기

Eloquent 메소드 find() 는 여러 매개 변수를 받아 들일 수 있으며, 하나의 모델이 아닌 발견 된 모든 레코드의 컬렉션을 반환합니다.
// Eloquent Model을 반환합니다
$user = User::find(1);
// Eloquent Collection을 반환합니다
$users = User::find([1,2,3]);

Key로 찾기

정확히 어떤 필드가 기본 키인지에 따라 자동으로 처리하는 whereKey() 메서드를 사용하여 여러 레코드를 찾을 수도 있습니다 ( 기본값은 id 지만 Eloquent 모델에서 재정의 할 수 있습니다).
$users = User::whereKey([1,2,3])->get();

자동 증가 대신 UUID 사용

모델에서 자동 증분 ID를 사용하고 싶지 않습니까?
마이그레이션:
Schema::create('users', function (Blueprint $table) {
// $table->increments('id');
$table->uuid('id')->unique();
});
모델:
class User extends Model
{
public $incrementing = false;
protected $keyType = 'string';
protected static function boot()
{
parent::boot();
User::creating(function ($model) {
$model->setId();
});
}
public function setId()
{
$this->attributes['id'] = Str::uuid();
}
}

Laravel에서 sub select 사용법

Laravel 6에서는 Eloquent 문에서 addSelect()를 사용하여 추가 된 열에 대해 계산을 할 수 있습니다.
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
])->get();

일부 열 숨기기

Eloquent 쿼리를 수행 할 때 특정 필드가 반환되는 것을 숨기려면 가장 빠른 방법 중 하나는 Collection 결과에 ->makeHidden() 을 추가하는 것입니다.
$users = User::all()->makeHidden(['email_verified_at', 'deleted_at']);

정확한 DB 오류

Eloquent Query 예외를 잡으려면 기본 Exception 클래스 대신 특정 QueryException을 사용하면 오류의 정확한 SQL 코드를 얻을 수 있습니다.
try {
// Some Eloquent/SQL statement
} catch (\Illuminate\Database\QueryException $e) {
if ($e->getCode() === '23000') { // integrity constraint violation
return back()->withError('Invalid data');
}
}

쿼리 빌더에서의 소프트 삭제

소프트 삭제는 Eloquent를 사용할 때는 삭제된 항목을 제외하지만 Query Builder를 사용하면 작동하지 않는다는 것을 잊지 마십시오.
// Will exclude soft-deleted entries
$users = User::all();
// Will NOT exclude soft-deleted entries
$users = DB::table('users')->get();

올바른 오래된 SQL 쿼리

DB 스키마에서 무언가를 변경하는 것과 같은 결과를 얻지 않고 간단한 SQL 쿼리를 실행해야하는 경우 DB::statement() 됩니다.
DB::statement('DROP TABLE users');
DB::statement('ALTER TABLE projects AUTO_INCREMENT=123');

DB 트랜잭션 사용 <a id="use-db-transactions></a>

두 개의 DB 작업을 수행하고 두 번째 작업에서 오류가 발생할 수있는 경우 첫 번째 작업을 롤백해야합니다.
이를 위해 DB 트랜잭션을 사용하는 것이 좋습니다. Laravel에서는 정말 쉽습니다.
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});

업데이트 또는 생성

레코드가 있는지 확인한 다음 업데이트하거나 새 레코드를 만들어야하는 경우 한 문장으로 수행 할 수 있습니다. Eloquent 메서드 updateOrCreate()를 사용합니다.
// Instead of this
$flight = Flight::where('departure', 'Oakland')
->where('destination', 'San Diego')
->first();
if ($flight) {
$flight->update(['price' => 99, 'discounted' => 1]);
} else {
$flight = Flight::create([
'departure' => 'Oakland',
'destination' => 'San Diego',
'price' => 99,
'discounted' => 1
]);
}
// Do it in ONE sentence
$flight = Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);

저장시 캐시 삭제

@pratiksh404 가 제공 한 팁
컬렉션을 제공하는 posts 과 같은 캐시 키가 있고 새 저장소 또는 업데이트에서 해당 캐시 키를 잊고 싶다면 모델에서 정적 saving 기능을 호출 할 수 있습니다.
class Post extends Model
{
// Forget cache key on storing or updating
public static function boot()
{
parent::boot();
static::saving(function () {
Cache::forget('posts');
});
}
}

Created_at 및 Updated_at의 형식 변경

@syofyanzuhad 가 제공 한 팁
created_at 형식을 변경하려면 다음과 같이 모델에 메소드를 추가 할 수 있습니다.
public function getCreatedAtFormattedAttribute()
{
return $this->created_at->format('H:i d, M Y');
}
따라서 필요할 때 $entry->created_at_formatted 사용할 수 있습니다. 다음과 같이 created_at 속성이 반환됩니다 : 04:19 23, Aug 2020 .
또한 updated_at 속성의 형식을 변경하려면 다음 메소드를 추가 할 수 있습니다.
public function getUpdatedAtFormattedAttribute()
{
return $this->updated_at->format('H:i d, M Y');
}
따라서 필요할 때 $entry->updated_at_formatted 사용할 수 있습니다. 다음과 같이 updated_at 속성이 반환됩니다 : 04:19 23, Aug 2020 .

JSON에 배열 유형 저장

@pratiksh404 가 제공 한 팁
배열을 사용하는 입력 필드가 있고이를 JSON으로 저장해야하는 경우 모델에서 $casts 속성을 사용할 수 있습니다. 여기 images 는 JSON 속성입니다.
protected $casts = [
'images' => 'array',
];
따라서 JSON으로 저장할 수 있지만 DB에서 검색하면 배열로 사용할 수 있습니다.

모델 사본 만들기

두 개의 매우 유사한 모델 (배송 주소 및 청구 주소)이 있고 서로 사본을 만들어야하는 경우 replicate() 메서드를 사용하고 그 후에 일부 속성을 변경할 수 있습니다.
$shipping = Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
$billing->save();

모델 관계

Eloquent 관계에 대한 OrderBy

Eloquent 관계에서 직접 orderBy()를 지정할 수 있습니다.
public function products()
{
return $this->hasMany(Product::class);
}
public function productsByName()
{
return $this->hasMany(Product::class)->orderBy('name');
}

조건부 관계

추가 "where"조건과 함께 동일한 관계를 자주 사용하는 경우 별도의 관계 방법을 만들 수 있습니다.
모델:
public function comments()
{
return $this->hasMany(Comment::class);
}
public function approved_comments()
{
return $this->hasMany(Comment::class)->where('approved', 1);
}

Raw DB 쿼리: havingRaw()

havingRaw() 이후의 groupBy() 함수를 포함하여 다양한 위치에서 RAW DB 쿼리를 사용할 수 있습니다.
Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();

Eloquent has()를 더 깊게

Eloquent has() 함수를 사용하여 두 단계의 관계를 쿼리 할 수 있습니다!
// Author -> hasMany(Book::class);
// Book -> hasMany(Rating::class);
$authors = Author::has('books.ratings')->get();

Has Many. 정확히 얼마나 많은 것을 원하나요?

Eloquent hasMany() 관계에서 지정한 양의 하위 레코드가 있는 레코드를 필터링 할 수 있습니다.
// Author -> hasMany(Book::class)
$authors = Author::has('books', '>', 5)->get();

기본 모델

$post->user가 존재하지 않는 경우 {{ $post->user->name }} 과 같이 호출 할 때 치명적인 오류를 방지하기 위해 belongsTo 관계에 기본 모델을 할당 할 수 있습니다.
public function user()
{
return $this->belongsTo('App\User')->withDefault();
}

hasMany를 이용한 다중 생성

hasMany() 관계가있는 경우 saveMany() 를 사용하여 "부모"개체의 여러 "자식"항목을 모두 한 문장으로 저장할 수 있습니다.
$post = Post::find(1);
$post->comments()->saveMany([
new Comment(['message' => 'First comment']),
new Comment(['message' => 'Second comment']),
]);

빠른 로딩에서 필요한 컬럼만 사용하기

Laravel Eager Loading을 실행할 때 관계에서 필요한 컬럼만 가져올 수 있습니다.
$users = App\Book::with('author:id,name')->get();
한단계를 거치는 관계에서도 사용 할 수 있습니다.
$users = App\Book::with('author.country:id,name')->get();

쉽게 상위 모델의 updated_at 갱신하기

레코드를 업데이트하고 상위 관계의 updated_at 열을 갱신하려면 (예 : 새 댓글을 추가하고 게시글 posts.updated_at를 갱신하려는 경우) 자식 모델에 $touches = ['post'];속성을 추가.
class Comment extends Model
{
protected $touches = ['post'];
}

관계가 존재하는지 항상 확인하세요

지금까지는 $model->relationship->field처럼 관계 객체가 여전히 존재하는지 확인하지 않고 사용했습니다.
현재 동작하는 코드 외부, 즉 다른 사람의 대기열 작업 등 어떤 이유로든 관계는 삭제 될 수 있습니다. if-else , 또는 {{ $model->relationship->field ?? '' }} 또는 (블레이드){{ optional($model->relationship)->field }}를 사용하세요.

withCount()를 사용하여 하위 관계 레코드의 갯수 확인

hasMany() 관계에서 "자식"항목을 갯수를 확인하려면 쿼리를 따로 작성하지 마세요. 예를 들어, User 모델에 대한 게시물과 댓글이 있을 경우 withCount() 사용하세요.
public function index()
{
$users = User::withCount(['posts', 'comments'])->get();
return view('users', compact('users'));
}
그런 다음 블레이드 파일에서 {relationship}_count 속성을 사용하여 해당 갯수를 가져올 수 있습니다.
@foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td class="text-center">{{ $user->posts_count }}</td>
<td class="text-center">{{ $user->comments_count }}</td>
</tr>
@endforeach
해당 필드로 정렬할 수도 있습니다.
User::withCount('comments')->orderBy('comments_count', 'desc')->get();

관계에서 필터 쿼리 추가하기

관계 데이터를 불러올때 클로저 함수에서 몇 가지 제한 또는 순서를 지정할 수 있습니다. 예를 들어, 가장 큰 도시가 3 개만 있는 국가를 얻으려면 다음과 같이 코드를 작성하면 됩니다.
$countries = Country::with(['cities' => function($query) {
$query->orderBy('population', 'desc');
$query->take(3);
}])->get();

관계를 항상 로드하지만 동적으로도 로드하기

모델과 함께 항상 로드 할 관계를 지정할 수 있을 뿐만 아니라 생성자 메서드에서 동적으로 처리할 수도 있습니다.
class ProductTag extends Model
{
protected $with = ['product'];
public function __construct() {
parent::__construct();
$this->with = ['product'];
if (auth()->check()) {
$this->with[] = 'user';
}
}
}

belongsTo 대신 hasMany를 사용하세요.

belongsTo 관계에서 하위 레코드를 만들 때 부모의 ID를 전달하는 방식 대신, hasMany 관계를 사용하여 더 짧은 문장을 만들 수 있습니다.
// 만약 Post -> belongsTo(User)이고, User -> hasMany(Post) 라면...
// user_id를 넘겨주는 대신...
Post::create([
'user_id' => auth()->id(),
'title' => request()->input('title'),
'post_text' => request()->input('post_text'),
]);
// 이렇게 사용하세요
auth()->user()->posts()->create([
'title' => request()->input('title'),
'post_text' => request()->input('post_text'),
]);

피벗 테이블 이름 바꾸기

"pivot"단어의 이름을 바꾸고 관계를 다른 이름으로 부르려면 관계에서 ->as('name') 를 사용하면됩니다.
모델:
public function podcasts() {
return $this->belongsToMany('App\Podcast')
->as('subscription')
->withTimestamps();
}
컨트롤러:
$podcasts = $user->podcasts();
foreach ($podcasts as $podcast) {
// $podcast->pivot->created_at 대신에...
echo $podcast->subscription->created_at;
}

한 줄로 상위 모델 업데이트

belongsTo() 관계일 경우 한 문장으로 Eloquent 관계 데이터를 업데이트 할 수 있습니다.
// 만약 Project -> belongsTo(User::class)이라면
$project->user->update(['email' => '[email protected]']);

Laravel 7이상에서 외래 키

Laravel 7부터 마이그레이션시 관계 필드에 대해 두 줄을 작성할 필요가 없습니다. 하나는 필드 용이고 다른 하나는 외래 키용입니다. foreignId() 메소드를 사용하십시오.
// Laravel 7 이전
Schema::table('posts', function (Blueprint $table)) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
}
// Laravel 7 부터
Schema::table('posts', function (Blueprint $table)) {
$table->foreignId('user_id')->constrained();
}
// 또는, 필드가 참조 테이블과 다른 경우
Schema::table('posts', function (Blueprint $table)) {
$table->foreignId('created_by_id')->constrained('users', 'column');
}

두 "whereHas"결합

Eloquent에서는 whereHas()orDoesntHave()을 한 문장으로 결합 할 수 있습니다.
User::whereHas('roles', function($query) {
$query->where('id', 1);
})
->orDoesntHave('roles')
->get();

관계 메서드가 있는지 확인하기

Eloquent 관계 이름이 동적이고 해당 이름과의 관계가 객체에 존재하는지 확인해야 하는 경우 PHP 함수 method_exists($object, $methodName)를 사용하세요.
$user = User::first();
if (method_exists($user, 'roles')) {
// $user->roles()-> 와 함께 관계 메서드 사용하기...
}

추가 관계가 있는 피벗 테이블

다대다 관계에서 피벗 테이블에는 추가 필드 및 다른 모델에 대한 추가 관계가 포함될 수 있습니다.
다음과 같이 별도의 피벗 모델을 생성합니다.
php artisan make:model RoleUser --pivot
그다음 ->using() 메서드를 사용하여 belongsToMany()에 지정합니다. 그러면 다음 예제와 같이 쩌는 것을 할 수 있습니다.
// app/Models/User.php 에서
public function roles()
{
return $this->belongsToMany(Role::class)
->using(RoleUser::class)
->withPivot(['team_id']);
}
// app/Models/RoleUser.php 모델은 Model이 아닌 Illuminate\Database\Eloquent\Relations\Pivot을 확장하여 사용합니다;
class RoleUser extends Pivot
{
public function team()
{
return $this->belongsTo(Team::class);
}
}
// 그러면 Controller에서 아래와 같이 실행할 수 있습니다.
$firstTeam = auth()->user()->roles()->first()->pivot->team->name;

즉석으로 관계 갯수 구해오기

관련 레코드의 갯수를 가져오기 위해 Eloquent의 withCount() 메서드 외에도 loadCount()를 사용하여 즉석으로 갯수를 가져올 수 도 있습니다.
// 만약 Book이 여러개의 Reviews를 가지고 있다면...
$book = App\Book::first();
$book->loadCount('reviews');
// $book->reviews_count; 를 사용할 수 있습니다
// 또 추가 조건과 함께도 가능합니다
$book->loadCount(['reviews' => function ($query) {
$query->where('rating', 5);
}]);

관계 순서 무작위 화

inRandomOrder()를 사용하여 Eloquent 쿼리 결과를 무작위화 할 수 있지만 이를 사용하여 쿼리로 로드하는 relationship 항목을 무작위화 할 수도 있습니다.
// 퀴즈가 있고 질문을 무작위로 선택하려는 경우...
// 1. 무작위 순서로 질문을 받고 싶다면
$questions = Question::inRandomOrder()->get();
// 2. 무작위 순서로 질문 옵션을 가져오려면 다음과 같이 사용하세요.
$questions = Question::with(['answers' => function($q) {
$q->inRandomOrder();
}])->inRandomOrder()->get();

마이그레이션