PHP의 원리
> .html
- 웹브라우저에서 html파일을 요청 -> 웹서버가 확장자를 확인, 자신이 처리할 수 있는 html임을 판단 -> htdocs 디렉토리에서 읽고 웹브라우저에 전송
> .php
- 웹브라우저에서 php파일을 요청 -> 웹서버가 확장자를 확인, 자신이 처리할 수 없기 때문에 PHP에게 파일에 대한 처리를 위임 -> PHP가 htdocs 디렉토리에서 읽고 PHP 문법에 따라 해석하고 html파일을 생산 -> 그 html을 웹서버가 웹브라우저에게 전송
<? php //php 코드 시작
echo date('Y-m-d H:i:s')
?> //php 코드 끝
- 동적으로 웹페이지를 생성할 수 있음 (html은 정적)
PHP의 데이터 타입
> 숫자 표현
<? php
echo 1; //1출력
print(1); //1출력
echo 1+1; //2출력
?>
- 산술 연산자 : +, -, *, /
> 문자 표현
<? php
'Hello World' // error
echo 'Hello world'; // single quotes
echo "Hello world"; // double quotes
echo "Hello 'w'orld"; // Hello 'w'orld 출력
echo "Hello "w"orld"; // error
//concatenation operator
echo "Hello"."world"; // .으로 이어진 좌항과 우항을 연결해서 하나의 문자열을 만들어냄
//strlen 함수
echo strlen("Hello world"); // 문자열 길이인 11출력
?>
- 문자열 결합 연산자 : .
PHP의 변수
<?php
$a=10; // 변수 a에 10 할당
echo $a+1; // 11출력
?>
<?php
$name ="이름";
echo "name 출력".$name; // $name에 '이름'이라고 출력
?>
- 변수 선언 : $변수이름 = 값;
URL 파라미터
안녕하세요. <?php echo $_GET[‘name’]; ?>님
- 주소가 바뀜에 따라 name에 들어가는 문자가 달라짐
함수
> strlen, nl2br 함수
<?php
$str="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
echo $str;
echo strlen($str);
echo nl2br($str);
?>
- strlen 함수 : 문자열 길이 확인 함수 - nl2br 함수 : 자동으로 줄바꿈을 해주는 함수
> file_get_contents 함수
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<h1>WEB</h1>
<ol>
<li><a href="index.php?id=HTML">HTML</a></li>
<li><a href="index.php?id=CSS">CSS</a></li>
<li><a href="index.php?id=Java">Java</a></li>
</ol>
<h2>
<?php
echo $_GET['id'];
?>
</h2>
<?php
echo file_get_contents("data/".$_GET['id']);
?>
</body>
</html>
- file_get_contents 함수 : 문자열로 전체 파일을 읽어주는 함수
여기서는 id로 들어오는 값을 경로로 전환해 주고 data파일 내에 있는 해당 파일을 찾아서 표현해주는 역할을 하였다.
Boolean과 비교 연산자
<?php
var_dump(11); // 출력 : int(11)
var_dump('11'); // 출력 : string(2) "11"
var_dump(1==2); // 출력 : bool(false)
var_dump(1<2); // 출력 : bool(true)
?>
- var_dump 함수 : 괄호 내 값의 데이터 형식과 함께 같이 출력시켜주는 함수 (주로 개발할 때 쓰임)
제어문 - 조건문과 반복문
> 조건문
<?php
echo '1<br>';
if(true){
echo '2<br>'
}
else{
echo '3<br>'
}
?>
true일 경우, 1과 2가 출력되고 false일 경우, 1과 3이 출력된다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<h1><a href="index.php">WEB</a></h1>
<ol>
<li><a href="index.php?id=HTML">HTML</a></li>
<li><a href="index.php?id=CSS">CSS</a></li>
<li><a href="index.php?id=Java">Java</a></li>
</ol>
<h2>
<?php
if(isset($_GET['id'])){ //id값이 있는지
echo $_GET['id'];
}
else{
echo "Welcome";
}
?>
</h2>
<?php
if(isset($_GET['id'])){
echo $_GET['id'];echo file_get_contents("data/".$_GET['id']);
else{
echo "Hello, PHP";
}
?>
</body>
</html>
- isset 함수 : 해당 값이 존재하는 지를 판별하는 함수
> 반복문
<?php
echo '1<br>';
$i=0;
while($i<3){
echo '2<br>';
$i=$i+1;
}
?>
1 출력 후 $i가 0, 1, 2일 때 2가 총 세 번 출력된다.
> 배열
<?php
$coworkers = array('egoing', 'leezche', 'duru', 'taeho');
echo $coworkers[1].'<br>'; // 출력 : leezche
echo $coworkers[3].'<br>'; // 출력 : taeho
var_dump(count($coworkers)); // 출력 : int(4)
array_push($coworkers, 'graphittie'); // 배열에 원소 추가
?>
> 활용
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<h1><a href="index.php">WEB</a></h1>
<ol>
<?php
$list = scandir('./data'); // data 하위 파일들 읽어옴
$i = 0;
while($i < count($list)) // list 개수만큼 반복
{
if($list[$i] != '.'){ // 현재디렉토리 제외
if($list[$i] != '..'){ //부모디렉도리 제외
echo "<li><a href=\"index.php?id=$list[$i]\">$list[$i]</a></li>\n";
}
}
$i = $i + 1;
}
?>
</ol>
<h2>
<?php
if(isset($_GET['id'])){ //id값이 있는지
echo $_GET['id'];
}
else{
echo "Welcome";
}
?>
</h2>
<?php
if(isset($_GET['id'])){
echo $_GET['id'];echo file_get_contents("data/".$_GET['id']);
else{
echo "Hello, PHP";
}
?>
</body>
</html>
이 코드를 이용하면(<ol>태그 부분) data디렉토리 아래에 새로운 파일을 추가해도(데이터가 달라져도) 자동으로 웹에 추가된다.
함수
<?php
function basic(){
print("abc1<br>");
print("abc2<br>");
}
basic(); // 함수 내 코드 실행
function sum($left, $right){
print($left+$right);
print("<br>");
}
sum(2,4); // 출력 : 6
sum(4,6); // 출력 : 10
?>
> 활용
<? php
function print_title(){
if(isset($_GET['id'])){ //id값이 있는지
echo $_GET['id'];
}
else{
echo "Welcome";
}
}
function print_description(){
if(isset($_GET['id'])){
echo $_GET['id'];echo file_get_contents("data/".$_GET['id']);
else{
echo "Hello, PHP";
}
}
function print_list(){
$list = scandir('./data'); // data 하위 파일들 읽어옴
$i = 0;
while($i < count($list)) // list 개수만큼 반복
{
if($list[$i] != '.'){ // 현재디렉토리 제외
if($list[$i] != '..'){ //부모디렉도리 제외
echo "<li><a href=\"index.php?id=$list[$i]\">$list[$i]</a></li>\n";
}
}
$i = $i + 1;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
print_title();
</title>
</head>
<body>
<h1><a href="index.php">WEB</a></h1>
<ol>
<?php
print_list();
?>
</ol>
<h2>
print_title();
</h2>
<?php
print_description();
?>
</body>
</html>
함수로 코드를 정리하였다.
Form과 POST
<!doctype html>
<html>
<body>
<form action="form.php" method="post">
<p><input type="text" name="title" placeholder="Title"></p>
<p><textarea name="description"></textarea></p>
<p><input type="submit"></p>
</form>
</body>
</html>
<?php
file_put_contents('data/'.$_POST['title'], $_POST['description']);
?>
URL을 통해 데이터를 전송하는 방식은 사용자가 서버로 데이터를 보낼 때 쓰면 안된다. 데이터를 서버쪽으로 전송할 때, 주소의 title 혹은 파라미터 정보가 포함되어 있으면 사용자들이 자신이 원하지 않았는데 글이 써지는 등의 일이 발생할 수 있기 때문이다. -> 해결 방법 : form 태그에 method를 post로 지정
글 생성, 수정, 삭제
//index.php
<?php
function print_title(){
if(isset($_GET['id'])){
echo $_GET['id'];
} else {
echo "Welcome";
}
}
function print_description(){
if(isset($_GET['id'])){
echo file_get_contents("data/".$_GET['id']);
} else {
echo "Hello, PHP";
}
}
function print_list(){
$list = scandir('./data');
$i = 0;
while($i < count($list)){
if($list[$i] != '.') {
if($list[$i] != '..') {
echo "<li><a href=\"index.php?id=$list[$i]\">$list[$i]</a></li>\n";
}
}
$i = $i + 1;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
<?php
print_title();
?>
</title>
</head>
<body>
<h1><a href="index.php">WEB</a></h1>
<ol>
<?php
print_list();
?>
</ol>
<a href="create.php">create</a>
<?php if(isset($_GET['id'])) { ?> //인자로 들어오는 값이 있는지 확인
<a href="update.php?id=<?=$_GET['id']?>">update</a>
<form action="delete_process.php" method="post">
<input type="hidden" name="id" value="<?=$_GET['id']?>">
<input type="submit" value="delete">
</form>
<?php } ?>
<h2>
<?php
print_title();
?>
</h2>
<?php
print_description();
?>
</body>
</html>
update의 경우 해당 항목을 클릭했을 때만 수정항목을 보이도록 하기위해 조건문에 isset을 이용해 인자로 들어오는 값이 있는지를 확인해준다.
//create, update.php
<?php
function print_title(){
if(isset($_GET['id'])){
echo $_GET['id'];
} else {
echo "Welcome";
}
}
function print_description(){
if(isset($_GET['id'])){
echo file_get_contents("data/".$_GET['id']);
} else {
echo "Hello, PHP";
}
}
function print_list(){
$list = scandir('./data');
$i = 0;
while($i < count($list)){
if($list[$i] != '.') {
if($list[$i] != '..') {
echo "<li><a href=\"index.php?id=$list[$i]\">$list[$i]</a></li>\n";
}
}
$i = $i + 1;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
<?php
print_title();
?>
</title>
</head>
<body>
<h1><a href="index.php">WEB</a></h1>
<ol>
<?php
print_list();
?>
</ol>
<a href="create.php">create</a>
<?php if(isset($_GET['id'])) { ?>
<a href="update.php?id=<?=$_GET['id']?>">update</a>
<?php } ?>
<h2> //수정 폼
<form action="update_process.php" method="post">
<input type="hidden" name="old_title" value="<?=$_GET['id']?>">
<p>
<input type="text" name="title" placeholder="Title" value="<?php print_title(); ?>">
</p>
<p>
<textarea name="description" placeholder="Description"><?php print_description(); ?></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
</body>
</html>
삭제는 form을 거칠 필요 없다.
//create_process.php
<?php
file_put_contents('data/'.$_POST['title'], $_POST['description']);
header('Location: /index.php?id='.$_POST['title']);
?>
header를 이용해서 사용자를 다른페이지로 보낼 수 있다.
//update_process.php
<?php
rename('data/'.$_POST['old_title'], 'data/'.$_POST['title']); //파일명 수정
file_put_contents('data/'.$_POST['title'], $_POST['description']); //내용 수정
header('Location: /index.php?id='.$_POST['title']);
?>
submit했을 때 id가 old_title로 전송된다.
//delete_process.php
<?php
unlink('data/'.$_POST['id']);
header('Location: /index.php');
?>
unlink를 통해 내용을 삭제할 수 있다.
파일의 모듈화 - require
- 중복의 제거
재사용할만한 코드를 정리정돈하여 사용
<?php
require('lib/print.php'); //재사용할만한 코드 정리
?>
-> 모든 페이지를 통합적으로 관리할 수 있다.
cf) 한번 만들어진 함수는 다시 재정의할 수 없다. -> error
-> 해결방법 : require을 require_once로 변경
보안 XSS
> Cross Site Scripting : 웹사이트에 스크립트 태그를 주입하는 것
<script>
location.href="https://opentutorials.org/course/";
</script>
위와 같은 코드를 작성하여 버튼을 누르면 아예 다른 웹페이지로 넘어가게 된다.
> 문제점
- 로그인을 대신 하는 경우 발생
- 글을 지우는 경우 발생
- 정보 유출 경우 발생
-> 사용자가 입력한 정보는 모두 불신해야 한다.
> 예방 방법
<?php
echo htmlspecialchars('<script>alert("babo");</script>');
?>
'<'를 특수한 코드로 바꾸어버려 그 자바스크립트를 인식하지 못하도록 한다.
보안 파일 경로 보호
<?php
function print_title(){
if(isset($_GET['id'])){
echo htmlspecialchars($_GET['id']);
} else {
echo "Welcome";
}
}
function print_description(){
if(isset($_GET['id'])){
$basename = basename($_GET['id']);
echo htmlspecialchars(file_get_contents("data/".$basename));
} else {
echo "Hello, PHP";
}
}
function print_list(){
$list = scandir('./data');
$i = 0;
while($i < count($list)){
$title = htmlspecialchars($list[$i]);
if($list[$i] != '.') {
if($list[$i] != '..') {
echo "<li><a href=\"index.php?id=$title\">$title</a></li>\n";
}
}
$i = $i + 1;
}
}
?>
- basename 함수 : 파일의 경로에서 파일명을 추출해주는 함수
이를 이용해 부모디렉토리로 가는 등의 악용을 막을 수 있다.