실행하며 배우는 PHP 튜토리얼
무료 PHP 8 튜토리얼 겸 레퍼런스: 배열, foreach, 문자열 함수, 날짜, 폼, 클래스, 오류 처리. 모든 예제를 페이지에서 바로 실행할 수 있고, HTML을 출력하는 예제는 제출 가능한 폼이 있는 페이지로 보여 줍니다.
PHP 가이드 학습 시작하기시작하기
- PHP란?PHP는 서버 사이드 스크립트 언어입니다. PHP 파일은 웹 서버에서 실행되고, 만들어진 HTML이 브라우저로 전송됩니다. WordPress, Laravel 등 웹의 큰 부분을 움직이며 명령줄 스크립트로도 실행됩니다.
- PHP 설치PHP는 명령 하나로 설치합니다. Windows는 winget, macOS는 Homebrew, Linux는 apt나 dnf를 씁니다. 그런 다음 터미널에서 php -v를 실행해 동작 여부와 버전을 확인합니다.
- PHP 실행터미널에서 php index.php로 PHP 파일을 실행하거나, PHP 내장 서버 php -S localhost:8000으로 폴더를 브라우저에 띄웁니다. 어느 쪽도 Apache나 XAMPP가 필요 없습니다.
- echo와 printecho는 문자열을 하나 이상 출력합니다: echo "Hello, $name"; 또는 echo $a, $b;. 페이지에 텍스트나 HTML을 보내는 일반적인 방법입니다. print는 값 하나로 같은 일을 하고 1을 반환하며, <?= $x ?>는 HTML 안에서 쓰는 짧은 형태입니다.
- 에러 보고PHP 에러를 모두 표시하려면 스크립트 맨 위에 ini_set('display_errors', '1');과 error_reporting(E_ALL);을 넣거나, php.ini에서 display_errors = On과 error_reporting = E_ALL로 설정하세요. 운영 환경에서는 에러를 표시하지 말고 로그로 남기세요.
- PHP vs PythonPHP는 웹을 위해 만들어졌습니다. 요청마다 파일이 실행되어 페이지를 출력하고, WordPress와 Laravel을 움직입니다. Python은 범용 언어로, 웹 개발(Django, Flask)도 하며 데이터 과학, 자동화, 머신러닝을 주도합니다.
- PHP vs JavaScriptPHP는 서버에서 실행되어 완성된 HTML을 브라우저로 보냅니다. JavaScript는 브라우저에서 페이지가 로드된 뒤 화면을 바꾸고, Node.js로 서버에서도 실행됩니다. 대부분의 웹사이트는 둘 다 씁니다. PHP로 페이지와 API를, JavaScript로 상호작용을 만듭니다.
기초
- 변수PHP 변수는 $로 시작하며 값을 대입하면 만들어집니다: $name = "Ada";. 선언 키워드도 고정된 타입도 없습니다. 함수는 값을 전달하거나 global을 쓰거나 캡처하지 않으면 바깥 변수를 볼 수 없고, static은 호출 사이에 값을 유지합니다.
- 자료형PHP에는 열 가지 타입이 있습니다. 스칼라 넷(int, float, string, bool), 복합 타입 넷(array, object, callable, iterable), 특수 타입 둘(null, resource)입니다. var_dump($x)는 값의 타입과 값을 보여 주고, gettype($x)는 타입 이름을 반환합니다.
- 문자열PHP 문자열은 점 연산자로 연결하거나("Hello, " . $name) 큰따옴표 안에 변수를 바로 넣습니다("Hello, $name"). 작은따옴표는 적힌 그대로 출력합니다. 연결, .=, 배열과 객체 보간, strtoupper, strtolower, ucfirst, ucwords로 대소문자 바꾸기를 배웁니다.
- heredoc과 nowdocPHP heredoc은 <<<EOT로 시작해 EOT로 끝나는 여러 줄 문자열이며, 큰따옴표 문자열처럼 변수를 치환합니다. nowdoc(<<<'EOT')은 텍스트를 적힌 그대로 유지합니다. 문법, 들여쓰기 규칙, 배열과 객체 보간, HTML 템플릿을 배웁니다.
- 연산자PHP 연산자는 값을 다룹니다. 산술 +, -, *, /, %, **, 대입 =, +=, .=, ??=, 논리 &&, ||, !, xor, 문자열 연결 ., 비교 ==, ===, <=>, 증감 ++, --. 그룹별로 실행 가능한 예제와 and와 && 우선순위 함정을 배웁니다.
- 비교 연산자PHP는 ==(타입 변환 후 같음), ===(값과 타입이 같음), !=와 !==, < > <= >=, 우주선 연산자 <=>로 값을 비교합니다. ==가 언제 타입을 변환하는지, PHP 8에서 무엇이 바뀌었는지, 느슨한 비교와 엄격한 비교를 한 표에서 확인하세요.
- 삼항 연산자PHP 삼항 연산자는 한 줄짜리 if/else입니다: $result = $condition ? 'yes' : 'no';. 짧은 삼항 ?:(엘비스 연산자), ??와의 차이, PHP 8부터 중첩 삼항에 괄호가 필요한 이유, match가 더 깔끔한 경우를 배웁니다.
- null 병합 ??PHP null 병합 연산자는 왼쪽 값이 null이거나 설정되지 않은 경우가 아니면 왼쪽 값을 반환합니다: $name = $_GET['name'] ?? 'Guest';. 없는 변수나 배열 키에 대해 경고하지 않습니다. ?? 체인, ??= 대입, ??와 ?:의 차이, nullsafe 연산자 ?->를 배웁니다.
- 형변환PHP 문자열은 (int) $str나 intval($str)로 정수로 변환합니다. (int) "42"는 42, (int) "12abc"는 12입니다. int, float, bool, string, array로 캐스트하기, 숫자 형태 문자열, 진법을 지정한 intval, settype, 조용히 0이 되는 대신 입력을 검증하는 법을 배웁니다.
- 상수PHP 상수는 바뀌지 않는 값에 붙인 이름입니다: const MAX_USERS = 100; 또는 define('MAX_USERS', 100);. define과 const의 차이, 상수 배열, self::로 쓰는 클래스 상수, defined()로 확인하기, 매직 상수 __LINE__, __FILE__, __DIR__, __CLASS__를 배웁니다.
- isset()isset($var)는 변수가 존재하고 null이 아니면 true, 아니면 false를 반환하며 경고를 내지 않습니다. 배열 키와 객체 속성도 확인합니다: isset($user['email']). 여러 변수 확인, 중첩 키, isset과 empty, isset과 array_key_exists, 폼 제출 확인을 배웁니다.
- empty()empty($var)는 변수가 없거나 거짓으로 평가되면 true를 반환합니다: null, false, 0, 0.0, "", "0", []. 정의되지 않은 변수나 키에 대해 경고하지 않습니다. "0"이 빈 값인 이유, 빈 문자열과 빈 배열을 정확히 확인하는 법, empty와 isset, 폼 입력 검증을 배웁니다.
- 수학과 반올림round($x, 2)는 소수점 둘째 자리로 반올림하고, floor()는 항상 내림, ceil()은 항상 올림합니다. intdiv(), % 연산자, 거듭제곱 **, abs(), max(), min(), 난수용 random_int()도 다룹니다.
제어 흐름
- if, elseif, elseif (조건) { ... }은 조건이 참일 때만 블록을 실행하고, elseif는 다음 조건을 확인하며, else는 어느 것도 맞지 않을 때 실행됩니다. elseif와 else if, &&와 ||, 참으로 평가되는 값, HTML 템플릿용 if: endif; 문법을 다룹니다.
- switch문switch ($value)는 하나의 값을 여러 case 레이블과 비교하고, 처음 일치한 지점부터 break를 만날 때까지 코드를 실행합니다. 여러 case 묶기, 폴스루, default, switch(true), 그리고 switch가 느슨한 == 비교를 쓰는 이유를 다룹니다.
- match 표현식match ($x) { 1, 2 => 'low', default => 'other' }는 값을 엄격한 ===로 비교하고, 처음 일치한 갈래의 결과를 반환하며, 아무것도 일치하지 않으면 UnhandledMatchError를 던집니다. match와 switch의 차이, match(true), enum과 함께 쓰는 match를 다룹니다.
- for문for ($i = 0; $i < 10; $i++) { ... }는 블록을 정해진 횟수만큼 실행합니다. 시작값, 매번 실행 전에 확인하는 조건, 증감식으로 이루어집니다. 인덱스로 배열 순회, 거꾸로 세기, 중첩 반복문, break와 continue를 다룹니다.
- while문while (조건) { ... }은 조건이 참인 동안 블록을 반복하며, 매 회차 전에 조건을 확인합니다. do { ... } while (조건);은 나중에 확인하므로 항상 한 번 이상 실행됩니다. break와 함께 쓰는 while (true), 파일을 한 줄씩 읽기, 무한 루프 피하기를 다룹니다.
- foreach문foreach ($array as $value)는 배열의 모든 요소를 방문하고, foreach ($array as $key => $value)는 키도 함께 줍니다. 인덱스 얻기, 참조로 값 바꾸기와 unset() 함정, break와 continue, 중첩 배열, foreach 안의 list(), HTML 만들기를 다룹니다.
배열
- 배열PHP 배열은 각 값이 키 아래에 저장되는 순서 있는 목록입니다. $fruits = ['apple', 'banana'];는 $fruits[0]으로 읽습니다. 배열을 만들고, 요소를 읽고 바꾸고, 반복하고, 출력하는 방법과 어떤 배열 함수를 쓸지 알아봅니다.
- 연관 배열PHP 연관 배열은 직접 이름 붙인 키 아래에 값을 저장합니다. $user = ['name' => 'Ada', 'age' => 36];는 $user['name']으로 읽습니다. 쌍을 추가, 변경, 삭제하고, 키와 값을 반복하고, 모든 키나 값을 얻고, 키를 확인하고, 키나 값으로 정렬하는 방법을 알아봅니다.
- 다차원 배열PHP 다차원 배열은 요소가 배열인 배열이며, 단계마다 대괄호 하나로 읽습니다: $grid[1][2] 또는 $users[0]['name']. 중첩 배열을 만들고, 깊은 값을 읽고 바꾸고, 중첩 foreach로 반복하고, HTML 표를 만들고, 열을 뽑고, 행을 정렬하는 방법을 알아봅니다.
- array_push()array_push($arr, $value)는 배열 끝에 값을 하나 이상 추가합니다. $arr[] = $value는 값 하나에 대해 같은 일을 하며 더 빠릅니다. 배열의 끝, 처음, 중간에 추가하는 방법, 키와 값 추가, 반환값을 대입하는 고전적인 버그 피하기를 알아봅니다.
- count()count($arr)는 PHP 배열의 요소 개수를 반환하므로 count(['a', 'b', 'c'])는 3입니다. COUNT_RECURSIVE로 중첩 배열 세기, sizeof()와 count()의 관계, 조건에 맞는 값 세기, PHP 8부터 count(null)이 TypeError를 던지는 이유를 알아봅니다.
- in_array()in_array($needle, $haystack)는 값이 배열에 있으면 true를 반환합니다. 세 번째 인수로 true를 넘기면(in_array('1', $ids, true)) 타입까지 일치해야 하는 엄격한 확인이 됩니다. strict 플래그, 대소문자 무시 검색, 여러 값 확인, 중첩 배열, 빠른 isset 대안을 알아봅니다.
- array_search()array_search($value, $array)는 $value와 같은 첫 번째 요소의 키를 반환하고, 없으면 false를 반환합니다. 키가 0일 수 있으므로 결과는 항상 !== false로 확인하세요. 엄격한 검색, 일치하는 모든 키 찾기, array_column으로 다차원 배열 검색, 대소문자 무시 검색을 알아봅니다.
- array_key_exists()array_key_exists('key', $array)는 배열에 그 키가 있으면 값이 null이어도 true를 반환합니다. isset($array['key'])는 더 빠르지만 null 값에는 false를 반환합니다. 둘의 차이, key_exists(), 중첩 키, 여러 키 확인, 객체에 property_exists()가 필요한 이유를 알아봅니다.
- array_merge()array_merge($a, $b)는 배열을 하나로 합칩니다. 숫자 키의 값은 뒤에 붙고 번호가 다시 매겨지며, 문자열 키는 나중 배열이 이깁니다. array_merge와 + 연산자, 스프레드 문법 [...$a, ...$b]의 차이, 배열 목록 합치기, array_merge_recursive나 array_replace가 더 맞는 경우를 알아봅니다.
- array_map()array_map($callback, $array)는 모든 요소에 콜백을 호출하고 결과로 이루어진 새 배열을 반환합니다. 화살표 함수, 키, 여러 배열을 한 번에 매핑하기, array_walk나 foreach가 더 맞는 경우를 알아봅니다.
- array_filter()array_filter($array, $callback)는 콜백이 true를 반환하는 요소만 남깁니다. 빈 값 제거, ARRAY_FILTER_USE_KEY로 키 기준 필터링, array_values로 결과 번호 다시 매기기, array_reduce로 합계 내기를 알아봅니다.
- 배열 정렬sort($array)는 리스트를 그 자리에서 정렬하고, asort와 ksort는 연관 배열을 값이나 키로 정렬하며, usort는 직접 만든 비교로 정렬합니다. 모든 함수와 다차원 배열을 열로 정렬하는 방법, 고전적인 $sorted = sort($arr) 실수 피하기를 알아봅니다.
- 배열 요소 삭제unset($array[$key])는 키로 요소를 지우고, array_splice는 위치로 지우면서 번호를 다시 매기며, array_diff는 값으로 지웁니다. 각 방법과 삭제 후 인덱스 재정렬, 엉뚱한 요소를 지우는 array_search 함정을 알아봅니다.
- array_slice()array_slice($array, $offset, $length)는 원본을 바꾸지 않고 배열 일부의 복사본을 반환합니다. 마지막 항목을 위한 음수 오프셋, preserve_keys, 목록 페이지 나누기, array_splice와의 차이를 알아봅니다.
- array_unique()array_unique($array)는 중복 값을 제거하고 각 값의 첫 번째 항목을 원래 키와 함께 유지합니다. 결과 번호 다시 매기기, 대소문자 무시 중복 제거, 다차원 배열의 중복 제거, 중복 값 세고 찾기를 알아봅니다.
- array_column()array_column($rows, 'email')은 모든 행의 email 필드를 평평한 배열로 반환합니다. 인덱스 키 인수, id로 행 다시 인덱싱하기, 객체와 함께 쓰기, array_search로 행 찾기를 알아봅니다.
- 구조 분해와 list()[$a, $b] = $array는 처음 두 요소를 한 줄로 $a와 $b에 대입하고, ['name' => $name] = $user는 키로 같은 일을 합니다. list()는 옛 표기입니다. 요소 건너뛰기, 변수 교환, 여러 값 반환, foreach 안의 구조 분해, ... 스프레드 연산자를 다룹니다.
문자열
- explode()explode(',', $string)는 문자열을 쉼표마다 나누고 조각들을 배열로 반환합니다. limit 매개변수, 줄바꿈으로 나누기, 조각 trim하기, str_split나 preg_split가 더 나은 경우를 알아봅니다.
- implode()implode(', ', $array)는 배열의 값을 구분자를 사이에 넣어 하나의 문자열로 합칩니다. 키와 함께 쓰는 implode, 연관 배열, HTML 목록 만들기, implode와 join의 차이를 알아봅니다.
- str_replace()str_replace($search, $replace, $subject)는 $search가 나오는 모든 곳을 $replace로 바꿉니다. 검색값과 치환값 배열, 치환 횟수 세기, 대소문자를 무시하는 str_ireplace, 첫 번째 일치만 바꾸기를 알아봅니다.
- substr()substr($string, $offset, $length)는 문자열의 일부를 반환합니다. 음수 오프셋, 처음이나 마지막 문자 가져오기, 한글과 일본어 등 UTF-8 텍스트를 위한 mb_substr, substr_count, 말줄임표로 텍스트 줄이기를 알아봅니다.
- strpos()strpos($haystack, $needle)는 $needle이 처음 나오는 위치를 반환하고, 찾지 못하면 false를 반환합니다. !== false 확인, 대소문자를 무시하는 stripos, strrpos로 마지막 일치 찾기, 모든 위치 찾기를 알아봅니다.
- str_contains()str_contains($haystack, $needle)는 $needle이 $haystack 어딘가에 있으면 true를 반환합니다. 대소문자를 무시하는 방법, str_starts_with와 str_ends_with, 여러 단어 확인, PHP 7용 strpos 버전을 알아봅니다.
- trim()trim($string)은 문자열 양 끝의 공백, 탭, 줄바꿈을 제거하고, ltrim()과 rtrim()은 한쪽만 정리합니다. 특정 문자 trim, 전각 공백, 배열의 모든 값 trim하기를 알아봅니다.
- strlen()strlen($string)은 문자열 길이를 바이트로, mb_strlen($string)은 문자로 반환합니다. 한글, 일본어, 이모지에서 답이 다른 이유, 빈 문자열 확인, 입력 길이 검증을 알아봅니다.
- sprintf()sprintf()는 포맷과 값으로 문자열을 만듭니다: sprintf('%05.2f', 3.14159)는 "03.14"를 반환합니다. %s, %d, %f, 0 채우기, 고정 소수점, 정렬, 인수 번호, printf와 vsprintf를 알아봅니다.
- number_format()number_format(1234567.891, 2)는 "1,234,567.89"를 반환합니다. 지정한 소수점 자리로 반올림하고 천 단위 구분 기호를 넣습니다. 네 가지 매개변수, 유럽식과 일본식 형식, 반올림 방식, 결과가 문자열인 이유를 알아봅니다.
- 줄바꿈PHP에서 줄을 바꿔 출력하려면 큰따옴표 안에 "\n"을 쓰거나 PHP_EOL을 쓰세요. 웹 페이지에서는 줄바꿈이 보이지 않으므로 <br>이나 nl2br()를 씁니다. 차이점, 작은따옴표 안의 '\n'이 동작하지 않는 이유, 줄 단위로 나누거나 줄바꿈을 제거하는 방법을 알아봅니다.
- preg_match()preg_match($pattern, $subject, $matches)는 문자열을 정규 표현식과 비교해 일치하면 1, 아니면 0을 반환합니다. 캡처 그룹, 이름 있는 그룹, preg_match_all, 앵커, 검증 패턴, UTF-8과 한글을 위한 u 수식어를 알아봅니다.
- preg_replace()preg_replace($pattern, $replacement, $subject)는 정규 표현식의 모든 일치를 바꿉니다: preg_replace('/\s+/', ' ', $text)는 연속된 공백을 하나로 합칩니다. $1 같은 역참조, preg_replace_callback, 영숫자가 아닌 문자 제거, limit과 count를 알아봅니다.
함수
- 함수PHP 함수는 function name($param) { return $value; }로 정의합니다. 반환값, 기본 매개변수, 이름 있는 인수, 참조 전달, strict_types와 타입 선언, nullable 타입과 유니언 타입, 가변 인수 ...$args를 알아봅니다.
- 화살표 함수화살표 함수는 fn($x) => $x * 2처럼 쓰는 표현식 하나짜리 익명 함수입니다. use 없이 바깥 변수를 값으로 자동으로 씁니다. 문법, 캡처 방식, 타입, array_map과 usort 콜백, 대신 완전한 클로저를 써야 할 때를 알아봅니다.
- 익명 함수익명 함수(클로저)는 변수에 저장한 이름 없는 함수입니다: $greet = function ($name) { return "Hi $name"; };. use 키워드, 참조 캡처, callable, 일급 callable 문법 strlen(...), 클래스 안의 클로저를 알아봅니다.
- 제너레이터제너레이터는 yield로 값을 하나씩 돌려주는 함수라서, foreach가 배열을 만들지 않고도 백만 개의 항목을 반복할 수 있습니다. yield, 키, 메모리 절약, 무한 시퀀스, yield from, send(), getReturn()을 알아봅니다.
클래스와 객체
- 클래스와 객체PHP 클래스는 `class Name { }`로 선언하는 설계도이고, `new Name()`은 그것으로 객체를 만듭니다. 속성, 메서드, `$this`, public/private/protected, 타입이 있는 속성과 readonly 속성, `__toString`, 객체를 대입해도 복사되지 않는 이유를 알아봅니다.
- 생성자PHP 생성자는 `new ClassName(...)`을 쓸 때 자동으로 실행되는 `__construct()` 메서드입니다. 생성자 속성 승격, 기본값과 이름 있는 인수, 검증, `parent::__construct()`, 정적 팩토리 메서드로 여러 생성자를 흉내 내는 방법을 알아봅니다.
- 상속PHP에서 클래스는 `class Dog extends Animal`로 다른 클래스를 상속합니다. 부모의 public과 protected 속성과 메서드를 받고, 그것을 오버라이드할 수 있으며, `parent::method()`로 원래 것도 호출할 수 있습니다. 오버라이딩, protected, final, instanceof, private 메서드 함정을 알아봅니다.
- 인터페이스PHP 인터페이스는 클래스가 갖추겠다고 약속하는 메서드의 목록입니다: `interface Shape { public function area(): float; }`이면 `class Circle implements Shape`는 `area()`를 정의해야 합니다. 인터페이스 타입 힌트, 여러 인터페이스 구현, 인터페이스 상수, 인터페이스 확장, Countable 같은 내장 인터페이스, 인터페이스와 추상 클래스의 차이를 알아봅니다.
- 추상 클래스PHP 추상 클래스는 `abstract class Name`으로 선언하며 인스턴스를 만들 수 없습니다. 상속되기 위해 존재합니다. 속성, 생성자, 완성된 메서드를 담을 수 있고, 모든 자식 클래스가 구현해야 하는 본문 없는 `abstract` 메서드도 담을 수 있습니다.
- 트레이트PHP 트레이트는 `use TraitName;`으로 클래스에 복사해 넣는 재사용 가능한 메서드와 속성 묶음입니다. 여러 트레이트 쓰기, `insteadof`와 `as`로 이름 충돌 해결하기, 트레이트의 추상 멤버와 정적 멤버, 어떤 메서드가 이기는지, 트레이트와 인터페이스와 추상 클래스의 차이를 알아봅니다.
- enumPHP enum(8.1+)은 값의 목록이 고정된 타입입니다: `enum Status: string { case Active = 'active'; }`. 순수 enum과 backed enum, `->value`와 `->name`, `from()`과 `tryFrom()`으로 변환하기, `cases()`로 모든 case 나열하기, 메서드, 상수, 인터페이스, `match` 속의 enum을 알아봅니다.
- 정적 메서드`static` 메서드나 속성은 객체가 아니라 클래스에 속합니다. `new` 없이 `ClassName::method()`로 호출하고 `ClassName::$count`로 읽습니다. `self::`와 `static::`(늦은 정적 바인딩), `new static`, 함수 안의 정적 변수, static이 잘못된 도구인 경우를 알아봅니다.
- 네임스페이스PHP 네임스페이스는 클래스, 함수, 상수를 접두사 아래로 묶습니다. 파일 맨 위에 `namespace App\Models;`를 쓰고, 다른 곳에서 `use App\Models\User;`로 클래스를 짧은 이름으로 부릅니다. 정규화된 이름, `use ... as` 별칭, `use function`, 전역 클래스 앞의 백슬래시, PSR-4 오토로딩을 알아봅니다.
오류와 예외
- try catchPHP에서 실패할 수 있는 코드는 `try { }` 블록에 넣고, 예외가 던져지면 `catch (Exception $e) { }`가 실행되며 이유는 `$e->getMessage()`에 담깁니다. 여러 예외 타입 잡기, `finally`, `catch (Exception)`이 `TypeError`와 `DivisionByZeroError`를 놓치는 이유(`Throwable`을 잡으세요), 다시 던지기, 전역 핸들러를 알아봅니다.
- 예외PHP에서는 `throw new Exception('message');`로 예외를 던지고, 호출한 쪽은 `catch` 블록에서 `$e->getMessage()`로 읽습니다. 내장 예외 클래스, 사용자 정의 예외 만들기, `getCode()`, `getLine()`, `getPrevious()`, 표현식으로서의 `throw`, `ValueError`와 `TypeError`처럼 PHP가 직접 던지는 에러를 알아봅니다.
데이터, 파일, 웹
- json_encode()json_encode($value)는 PHP 배열, 객체, 스칼라를 JSON 문자열로 바꿉니다. 연관 배열은 JSON 객체가, 리스트는 JSON 배열이 되며, JSON_PRETTY_PRINT와 JSON_UNESCAPED_UNICODE 같은 플래그가 출력을 제어합니다.
- json_decode()json_decode($json, true)는 JSON 문자열을 PHP 연관 배열로 바꾸며, true가 없으면 stdClass 객체를 얻습니다. 중첩된 값, JSON_THROW_ON_ERROR로 에러 처리, json_validate(), json_decode가 null을 반환하는 이유를 알아봅니다.
- date()date('Y-m-d')는 오늘 날짜를 문자열로 반환하고, date('Y-m-d', $timestamp)는 어떤 유닉스 타임스탬프든 포맷합니다. time(), mktime(), strtotime(), DateTimeImmutable, 날짜 더하기, 두 날짜의 차이, 시간대를 실행 가능한 예제로 알아봅니다.
- 날짜 포맷PHP 날짜 포맷은 'Y-m-d H:i:s' 같은 문자들의 문자열입니다. Y는 4자리 연도, m은 월, d는 일, H는 시, i는 분, s는 초입니다. 모든 포맷 문자를 예제와 함께 보고, 이스케이프, ISO 8601, 일본식 날짜, 포맷 변환까지 다룹니다.
- file_get_contents()file_get_contents('notes.txt')는 파일 전체를 읽어 문자열 하나로 반환하고, 읽을 수 없으면 false를 반환합니다. 짝인 file_put_contents()는 문자열을 파일에 쓰고, file()은 줄을 배열로 반환합니다.
- fopen()fopen('data.txt', 'r')는 파일을 열고 핸들을 반환하며, 실패하면 false를 반환합니다. 핸들에서 fgets()나 fread()로 읽고, fwrite()로 쓰고, fclose()로 닫습니다. 모드('r', 'w', 'a', 'x', 'c'와 각각의 + 형태)가 할 수 있는 일을 정합니다.
- include와 requireinclude 'header.php';는 그 지점에서 다른 PHP 파일을 실행하며, 마치 그 코드를 붙여 넣은 것처럼 동작합니다. require도 같은 일을 하지만 파일이 없으면 치명적 에러로 스크립트를 멈추고, include는 경고만 하고 계속 진행합니다. include_once와 require_once는 파일을 처음 한 번만 불러옵니다.
- 폼PHP 폼은 <form method="post">로 자기 자신에게 전송되고, 스크립트는 $_SERVER['REQUEST_METHOD']가 'POST'일 때 $_POST['name']에서 필드를 읽습니다. 검증, 필드 옆 에러 메시지, 입력값 유지, 체크박스와 select, 출력 이스케이프를 알아봅니다.
- $_GET과 $_POST$_GET은 URL의 쿼리 문자열을 담고(?page=2는 $_GET['page']를 줍니다) $_POST는 method="post"로 보낸 폼의 필드를 담습니다. 둘을 안전하게 읽는 방법, http_build_query로 링크 만들기, $_SERVER['REQUEST_METHOD'] 확인, GET과 POST 중 고르는 방법을 알아봅니다.
- htmlspecialchars()htmlspecialchars($text)는 HTML에서 의미가 있는 다섯 문자(& < > " ')를 엔티티로 바꿔, 사용자 입력이 마크업으로 실행되지 않고 텍스트로 보이게 합니다. ENT_QUOTES, 속성 이스케이프, 이중 인코딩, htmlentities와 strip_tags를 알아봅니다.
- 세션과 쿠키모든 페이지 맨 위에서 session_start()를 호출한 다음 $_SESSION['key']에 값을 저장하세요. PHP는 그것을 서버에 보관하고 쿠키로 방문자를 기억합니다. setcookie('name', 'value', $options)는 작은 값을 브라우저에 저장하며, $_COOKIE로 다시 읽습니다. 로그인, 로그아웃, 플래시 메시지, 쿠키 옵션, 보안 설정을 알아봅니다.
- password_hash()password_hash($password, PASSWORD_DEFAULT)로 비밀번호를 해시하고, 60자 결과를 저장하고, password_verify($password, $hash)로 로그인을 확인하세요. 해시가 매번 바뀌는 이유, cost, password_needs_rehash, Argon2id, md5와 sha1이 비밀번호에 맞지 않는 이유를 알아봅니다.
- filter_var()filter_var($value, FILTER_VALIDATE_EMAIL)은 값이 유효하면 그 값을, 아니면 false를 반환합니다. FILTER_VALIDATE_INT, FILTER_VALIDATE_URL, FILTER_VALIDATE_BOOL, FILTER_VALIDATE_IP도 같은 방식으로 동작합니다. 옵션(min_range, default), 플래그, sanitize 필터, false와 0의 함정을 알아봅니다.
- PDOPDO는 PHP의 데이터베이스 계층입니다. new PDO('mysql:host=localhost;dbname=shop;charset=utf8mb4', $user, $pass)로 연결한 다음, 값이 들어가는 모든 쿼리를 prepare()와 execute([$value])로 실행하세요. 연결, prepared statement, 행 가져오기, 삽입, 트랜잭션, WHERE IN을 알아봅니다.
- ComposerComposer는 PHP의 패키지 관리자입니다. composer require vendor/package는 라이브러리를 vendor/에 내려받아 composer.json에 기록하고, require 'vendor/autoload.php'가 그것을 불러옵니다. Composer 설치, composer.json, 버전 제약, install과 update의 차이, 직접 만든 클래스의 PSR-4 오토로딩을 알아봅니다.
디버깅과 연습
- var_dump()와 print_r()print_r($array)는 배열을 읽기 쉬운 형태로 출력하고, var_dump($value)는 모든 타입과 길이까지 보여 주며, var_export는 올바른 PHP 코드를 출력합니다. 각각을 언제 쓰는지, print_r를 문자열로 받는 방법, HTML에서 <pre>로 보기 좋게 출력하는 방법을 알아봅니다.
- 면접 질문PHP 8 기준의 짧고 정확한 답이 달린 PHP 면접 질문 24개입니다. ==와 ===, isset과 empty부터 foreach의 참조, self와 static, 제너레이터, SQL 인젝션, 비밀번호 해싱까지 다룹니다. 대부분의 답에는 실행하고 바꿔 볼 수 있는 코드가 있습니다.