데이터베이스 : 시작하기

소개하기

라라벨은 직접 raw SQL을 사용할 때에도, 쿼리 빌더를 사용하거나 그리고 Eloquent ORM을 사용할 때에도 데이터베이스를 처리하는 것이 쉽도록 해줍니다. 현재 라라벨은 4가지 데이터베에스를 지원하고 있습니다:

  • MySQL
  • PostgreSQL
  • SQLite
  • SQL Server

설정하기

어플리케이션을 위한 데이터베이스 설정 파일은 config/database.php에 있습니다. 이 파일에서 모든 데이터베이스 커넥션에 대한 설정을 정의하고 기본적으로 사용할 커넥션을 지정할 수 있습니다. 이 파일에서는 지원하는 대부분의 데이터베이스 예제가 들어 있습니다.

기본적으로 라라벨의 샘플 환경 설정은 여러분의 로컬 머신에서 라라벨 개발 환경을 구축할 수 있는 편리한 방법을 제공하는 라라벨 홈스테드에 맞춰져 있습니다. 물론 로컬 데이터베이스에 맞게 변경하시면 됩니다.

SQLite 설정하기

touch database/database.sqlite 와 같은 명령어를 사용하여 SQLite 데이터베이스를 새롭게 생성한 뒤에, 데이터베이스의 절대 경로를 사용하여 새롭게 생성된 데이터베이스를 지정하는 환경 설정을 손쉽게 추가할 수 있습니다:

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

읽기 & 쓰기 커넥션

SELECT문에서 사용하는 데이터베이스와 INSERT, UPDATE 그리고 DELETE문을 사용하는 데이터 베이스에 다른 연결을 사용할고 싶은 경우도 있습니다. 라라벨은 이를 쉽게 할 수 있습니다. Raw 쿼리를 사용하든, 쿼리 빌더 또는 Eloquent ORM 을 사용하든 적절한 연결들을 사용할 수 있습니다.

다음은 어떻게 read / write 커넥션을 설정하는지에 대한 예제 입니다:

'mysql' => [
    'read' => [
        'host' => '192.168.1.1',
    ],
    'write' => [
        'host' => '196.168.1.2'
    ],
    'sticky'    => true,
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

설정 배열에 read, write 그리고 sticky 세개의 키가 추가 된것을 참고하십시오. readwrite 키는 host라는 하나의 키를 포함하는 배열 값입니다: readwrite 의 나머지 데이터베이스 옵션 값은 기본 mysql 배열에서 합쳐(merge)집니다.

따라서 메인 배열에서 재정의하고자하는 값들을 readwrite 배열에 입력하기만 하면 됩니다. 위의 경우에서는 192.168.1.1는 "read(읽기용)" 커넥션에 대한 호스트로 사용되고, 192.168.1.2는 "write(쓰기용)" 커넥션에 대한 호스트로 사용될 것입니다. 메인 mysql설정 배열에 포함된 데이터베이스 연결정보, 프리픽스, 캐릭터 셋 등 다른 모든 옵션들은 양쪽연결에서 모두 공유될 것입니다.

sticky 옵션

sticky 옵션은 현재 request-요청사이클 에서 데이터베이스에 기록된 레코드를 바로 읽을 수 있도록 하는 있어도 되고 없어도 되는 값입니다. sticky 옵션이 활성화 되어 있고 현재 request-요청사이클에서 데이터베이스에 "쓰기" 작업을 수행한 경우 이 뒤에 "읽기"작업은 "쓰기"에서 사용한 커넥션으르 사용합니다. 이렇게 되면, request-요청사이클 동안에 작성된 모든 데이터를 동일한 request-요청 중에서는 바로 데이터베이스에서 읽을 수 있습니다. 여러분의 어플리케이션에서 이러한 동작이 필요한지에 대해서 결정하는 건 여러분의 선택에 따라 달라질 수 있습니다.

여러개의 데이터베이스 커넥션 사용하기

여러개의 커넥션을 사용하는 경우, DB 파사드의 connection 메소드를 통해 각각의 커넥션에 액세스 할 수 있습니다. connection 메소드에 전달되는 nameconfig/database.php 설정 파일에 나열되어 있는 이름이어야 합니다:

$users = DB::connection('foo')->select(...);

또한 커넥션 인스턴스에서 getPdo 메소드를 사용하여 PDO 인스턴스로 액세스 할 수 있습니다:

$pdo = DB::connection()->getPdo();

Raw 쿼리 실행

일단 데이터베이스 연결을 설정하면 DB 파사드를 사용해서 쿼리를 실행 할 수 있습니다. DB 파사드는 각각 쿼리 타입에 해당하는 메소드 : select, update, delete 그리고 statement 메소드를 제공합니다.

Select 쿼리 실행하기

기본적인 쿼리를 실행하기 위해서 DB 파사드의 select 메소드를 사용할 수 있습니다:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show a list of all of the application's users.
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::select('select * from users where active = ?', [1]);

        return view('user.index', ['users' => $users]);
    }
}

select 메소드의 첫번째 인자는 raw SQL 쿼리이고, 두번째는 쿼리에 바이딩될 매개변수 입니다. 일반적으로 매개 변수들은 where 절을 위한 값들입니다. 매개변수 바인딩은 SQL 인젝션을 방지하기 위해 제공됩니다.

select 메소드는 항상 결과를 배열로 반환합니다. 배열안의 값들은 PHP 의 StdClass 객체 형태로 다음과 같이 결과 값에 엑세스 할 수 있습니다.

foreach ($users as $user) {
    echo $user->name;
}

이름이 부여된 바인딩 사용하기

? 를 사용하는 매개변수 바인딩 대신에, 이름을 지정한 바인딩을 사용한 쿼리를 실행시킬 수 있습니다:

$results = DB::select('select * from users where id = :id', ['id' => 1]);

Insert 문 실행하기

insert 쿼리문을 실행하기 위해서는 DB 파사드의 insert 메소드를 사용하면 됩니다. select 메소드와 마찬가지로, 이 메소드는 첫번째 인자로 raw SQL 쿼리를, 두번째로 바인딩할 인자들을 전달 받습니다:

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

Update 쿼리 실행하기

update 메소드는 데이터베이스에 존재하는 레코드 업데이트 하는데 사용되어집니다. 그 결과 영향을 받은 레코드들의 갯수가 반환될 것입니다:

$affected = DB::update('update users set votes = 100 where name = ?', ['John']);

Delete 쿼리 실행하기

delete 메소드는 데이터베이스에서 레코드를 삭제하는데 사용됩니다. update 와 같이, 영향을 받은 레코드 갯수가 반환됩니다:

$deleted = DB::delete('delete from users');

일반적인 구문의 쿼리 실행하기

몇몇 데이터베이스 구문은 값을 반환하지 않습니다. 이러한 유형의 작업들을 위해서는 DB 파사드의 statement 메소드를 사용할 수 있습니다:

DB::statement('drop table users');

쿼리 이벤트 리스닝

어플리케이션에서 실행되는 각각의 쿼리를 확인하고자 한다면 listen 메소드를 사용하면 됩니다. 이 메소드는 쿼리를 로그로 남기거나, 디버깅 할 때 유용합니다. 서비스 프로바이더에서 쿼리 리스너를 등록할 수 있습니다:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

데이터베이스 트랜잭션

일련의 쿼리들을 하나의 데이터베이스 트랜잭션으로 실행시키기 위해서 DB 파사드의 transaction메소드를 사용할 수 있습니다. 트랜잭션 메소드에 전달된 Closure 안에서 예외-exception 이 발생하게 되면 트랜잭션은 자동으로 롤백됩니다. Closure가 성공적으로 실행되면 트랜잭션은 자동으로 커밋됩니다. transaction 메소드를 사용하게 되면 일일이 롤백과 커밋에 대해서 걱정할 필요가 없습니다:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
});

데드락 처리하기

transaction 메소드는 데드락이 발생하면 트랜젝션을 재시도 해야 하는 횟수를 정의하는 두번째 인자를 선택적으로 받아들입니다. 이러한 시도가 모두 종료되면, exception이 발생합니다:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
}, 5);

수동으로 트랙잭션 사용하기

트랜잭션을 직접 시작하고 롤백과 커밋을 제어하고 싶은 경우는 DB 파사드의 beginTransaction 메소드를 사용하면 됩니다:

DB::beginTransaction();

rollBack 메소드는 트랜잭션을 롤백 할 수 있습니다:

DB::rollBack();

마지막으로 commit 메소드는 트랜잭션을 커밋 할 수 있습니다:

DB::commit();

{tip} DB 파사드의 트랜잭션 메소드는 쿼리 빌더Eloquent ORM에 모두에서, 트랜잭션을 제어 할 수도 있습니다.