데이터베이스에서 데이터 가져오기(2)

minah moon·2023년 9월 1일

PHP

목록 보기
45/58
post-thumbnail

SQL 쿼리에 변경할 수 있는 데이터 사용하기

페이지가 요청할 때마다 데이터베이스에서 다른 데이터를 가져오도록 SQL 쿼리에 다른 값을 사용할 수 있다. 이 경우, SQL 쿼리를 먼저 준비한 다음에 실행해야 한다.

1단계: 준비

SQL 문이 실행될 때마다 변경될 수 있는 값을 나타내기 위해 플레이스홀더placeholder를 사용한다. SQL 플레이스홀더는 변수처럼 동작하지만 이름에 $ 기호가 아닌 콜론으로 시작한다.

SQL 쿼리가 플레이스홀더를 포함하면 PDO 객체의 query() 메서드를 호출하여 쿼리를 실행하는 것이 아니라 PDO 객체의 prepare() 메서드를 호출한다.

prepare() 메서드 역시 PDOStatement 객체를 반환하지만, 여기서 PDOStatement 객체는 결과 세트가 아닌 SQL 문을 나타낸다.

2단계: 실행

다음으로 PDOStatement 객체의 execute() 메서드를 호출하여 SQL 문을 실행한다. 이 메서드의 하나의 인수는 플레이스홀더를 대체할 값이 포함된 배열이다.

플레이스홀더 이름과 사용될 값은 연관 배열로 제공할 수 있다.

  • 키는 SQL 쿼리에서의 플레이스홀더 이름이다.

  • 값은 플레이스홀더를 대체할 값이다(값은 종종 변수에 이미 저장되어 있음).

$sql = "SELECT forename, surname FROM member WHERE id = :id;";
$statement = $pdo->prepare($sql);
$statement->execute(['id' => $id]);

위의 SQL 쿼리에는 :id라는 플레이스홀더가 있다. execute() 메서드는 :id를 $id 변수에 저장된 값으로 바꾼다. 이것을 프리페어드 스테이트먼트prepared statement라고 한다.

프리페어드 스테이먼트는 SQL 주입 공격의 위험을 차단한다.


SQL 쿼리에 값 바인딩

PDOStatement 객체의 bindValue()와 bindParam() 메서드는 프리페어드 스테이트먼트를 생성하고 SQL 쿼리에서 플레이스홀더를 대체하는 또 다른 방법을 제공한다.

bindValue()와 bindParam() 메서드를 SQL 쿼리에 플레이스홀더를 대체하는 데 사용하려면, PDOStatement 객체의 prepare() 메서드 다음에, 그리고 execute() 메서드 전에 호출해야 한다.

이 메서드는 세 개의 매개변수를 갖는다.

  • 플레이스홀더의 이름

  • 플레이스홀더를 대체하는 값을 가진 변수

  • 값의 데이터 타입을 나타내는 값(PDO::PARAM_STR, PDO::PARAM_INT, PDO::PARAM_BOOL)

bindValue()와 bindParam()의 차이점은 PHP 인터프리터가 변수에서 값을 가져와서 SQL 쿼리에 있는 플레이스홀더를 대체하는 데 사용하는 시점이다.

  • bindValue()는 bindValue()가 호출될 때 인터프리터가 변수에서 값을 가져온다.

  • bindParam()는 execute()가 호출될 때 인터프리터가 변수에서 값을 가져온다. 따라서, bindParam()과 execute()가 호출되는 중간에 변수에 저장된 값이 변경되면 업데이트된 값이 사용된다.

$sql = "SELECT * FROM member WHERE id = :id;";
$statement = connection->prepare($sql);
$statement->bindValue('id', $id, PDO::PARAM_INT);

위의 SQL 쿼리에 있는 :id 플레이스홀더는 $id라는 변수가 가진 값으로 대체될 것이다.


단일 파일을 사용하여 여러 페이지 표시하기

단일 PHP 파일을 사용하여 사이트의 여러 페이지를 표시할 때, URL 끝에 쿼리 문자열을 추가하여 데이터베이스에서 수집해야 하는 데이터를 PHP 파일에 알려 줄 수 있다.

PHP 페이지는 쿼리 문자열로부터 값을 받아서 SQL 쿼리에서 그 값을 사용하여 데이터베이스에서 수집해야 하는 데이터를 지정할 수 있다.

<a href="member.php?id=1">Ivy Stone</a>

member.php에 대한 위의 링크는 id라는 이름과 1의 값을 포함하는 쿼리 문자열을 가지고 있다. 이 값은 member 테이블의 id 열에 해당한다.

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if (!$id) {
	include 'page-not-found.php';
}

member.php 페이지는 PHP의 filter_input() 함수를 사용하여 쿼리 문자열에서 값을 가져온다. 데이터베이스의 id 열은 모두 정수이므로 함수는 정수 필터를 사용한다. 반환되는 값은 $id라는 변수에 저장된다.

  • 반환되는 값이 정수라면 $id는 그 정수를 저장한다.

  • 반환되는 값이 정수가 아니라면 $id는 false를 저장한다.

  • id가 쿼리 문자열에 없다면 $id는 null을 저장한다.

if 문은 $id가 false 또는 null을 담고 있는지 확인한다. 만약에 그렇다면 페이지는 데이터베이스에서 회원 데이터를 가져올 수 없으므로, page-not-found.php 파일이 인클루드된다. 이 파일은

  • HTTP 응답 코드로 404 값을 보낸다.

  • 페이지를 찾을 수 없음을 방문자에게 알린다.

  • exit 명령을 사용하여 코드 실행을 멈춘다.

만일 쿼리 문자열이 유효한 정수를 포함했다면, 페이지는 데이터베이스에서 데이터를 가져와 $member라는 변수에 저장한다. 두 번째 if 문은 회원 데이터가 발견되지 않았는지를 확인한다. 만약에 회원 데이터가 없다면 page-not-found.php가 인클루드되며 페이지 실행이 중지될 것이다.


HTML 페이지에서 데이터베이스 데이터 표시하기

먼저 데이터베이스에서 데이터를 가져와서 변수에 저장한다. 그 후 HTML 페이지를 생성하기 위해 해당 변수의 데이터를 사용한다.

파일에서 HTML 페이지를 생성하는 부분은 가능한 PHP 코드가 거의 없어야 한다. 다음은 가장 빈번하게 필요로 하는 세 가지 유형의 코드다.

함수

함수는 데이터가 올바른 형식이 되도록 하는 데 종종 사용된다. html_escape() 함수는 HTML의 예약 문자를 엔티티로 사용하여 XSS 공격을 방지하기 위해 많이 사용된다.

function format_date(string $string): string
{
	$date = strtotime($string);
    return date('F d, Y', $date);
}

이 함수는 데이터베이스가 생성한 날짜를 일정하고, 사람이 읽을 수 있는 형식으로 만드는 데 사용한다.
먼저 데이터베이스가 저장하는 날짜와 시간은 PHP의 strtotime() 함수를 사용하여 유닉스 타임스탬프로 변환된다. 그런 다음 PHP의 date() 함수를 사용하여 사람이 읽을 수 있는 형식으로 변환된다.

조건문

조건문은 데이터베이스에서 반환된 데이터를 살펴보고 HTML 코드가 표시할 내용을 결정하는 데 사용할 수 있다.

html_escape($member['picture'] ?? 'blank.png';

반복문

반복문은 데이터베이스가 반환한 결과 세트의 각 행을 가지고 작업하는 데 주로 사용된다.






출처 - 존 두켓, <백엔드 프로그래밍을 위한 PHP & MySQL>, Jpub, 2022

0개의 댓글