기타/웹 2.02016. 5. 5. 00:30

현재... GPX 파일(XML 파일의 일종입니다.)을 해석해서 mySQL DB에 넣기 위해 고민 중에 있었습니다. 


제가 예전에 만들어 둔 프로그램에서는 그냥 javascript - ajax로 읽어 들인 후 사용했었습니다. 원래는 이 부분을 사용하려고 했습니다. 그런데, 이 기능을 이용할 경우, 한 개의 waypoint를 추출해서 배열을 만들고, ajax를 통해 PHP로 넘겨주면, PHP속에서 mySQL에 INSERT 시키는 방법을 사용해야 합니다. 그러면 당연히 터무니 없이 속도가 떨어질 것으로 예상됩니다.


그러던 중, W3C PHP 투토리얼 사이트에서 XML Parser에 관한 내용을 보게 되었습니다. 이걸 이용하면 그냥 PHP에서 XML(GPX파일)을 Parsing 한 후, 바로 MySQL로 넣어줄 수 있으니, 훨씬 작업이 간편할 것이라 생각했습니다.


PHP XML Parser는 두 가지 종류가 있습니다. 하나는 SimpleXML Parser이고, 다른 하나는 XML expat 입니다. SimpleXML은 말 그대로 아주 간단합니다. 그냥 파일이나 string을 지정하면, 전체를 구조체로 읽어 들이는 방식입니다. 그 다음엔 $xml->book[0]->title 과 같이 간단한 참조 방식으로 사용하면 됩니다. 


이에 비해 expat는 상당히 복잡합니다. expat는 이벤트 방식의 Parser라고 하고요, 예를 들어 아래와 같은 문장이 있다면...

<from>Jani</from>

이것을 다음과 같은 3개의 이벤트(사실은 4개의 이벤트)로 보내줍니다. 이런 방식으로 파일 전체가 이벤트로 처리되는 겁니다.

    • Start element: from
    • Start CDATA section, value: Jani
    • Close element: from

언뜻 보기에는 많이 복잡해 보였습니다. 그래서 포기할까 생각했습니다. 그런데, 파일의 크기가 클 수록 이 방식이 빠르고 편하다는 설명을 보고 시도해 보기로 했습니다. (simpleXML Parser의 경우 한꺼번에 메모리로 읽어 들이는 방식이라서 시스템에 따라서 문제가 발생할 수도 있답니다.)


expat Parser는 4개의 함수만 사용하면 거의 80%의 문제는 해결할 수 있다고 합니다. 제가 설명할 것도 바로 이 4가지 함수입니다. (일단 예제는 W3C의 예제를 이용하겠습니다.)


    • $parser=xml_parser_create(); // parser를 생성합니다.
    • xml_set_element_handler($parser,"start","stop"); // 생성한 Parser에 Start event handler 와 Stop event handler를 등록. 당연히 "start"/"stop" 은 함수명입니다.
    • xml_set_character_data_handler($parser,"char"); // Parser에 Data event handler를 등록합니다. "char"가 그 함수고요, 물론 이름은 다른 이름을 사용해도 됩니다.
    • xml_parse($parser,$data,feof($fp)); // parser를 실행합니다.

아래는 W3C 사이트에 있는 예제입니다. 빨간 표시를 한게 위에서 설명한 4개의 함수입니다.

xml_parser_create() 아래로 있는 start(), stop(), char()가 바로 event 핸들러입니다. 이 함수들 3개를 적당히 이용해서 데이터를 처리해주면 됩니다.


<?php
// Initialize the XML parser
$parser=xml_parser_create();

// Function to use at the start of an element
function start($parser,$element_name,$element_attrs) {
  switch($element_name) {
    case "NOTE":
    echo "-- Note --<br>";
    break;
    case "TO":
    echo "To: ";
    break;
    case "FROM":
    echo "From: ";
    break;
    case "HEADING":
    echo "Heading: ";
    break;
    case "BODY":
    echo "Message: ";
  }
}

// Function to use at the end of an element
function stop($parser,$element_name) {
  echo "<br>";
}

// Function to use when finding character data
function char($parser,$data) {
  echo $data;
}

// Specify element handler
xml_set_element_handler($parser,"start","stop");

// Specify data handler
xml_set_character_data_handler($parser,"char");

// Open XML file
$fp=fopen("note.xml","r");

// Read data
while ($data=fread($fp,4096)) {
  xml_parse($parser,$data,feof($fp)) or 
  die (sprintf("XML Error: %s at line %d", 
  xml_error_string(xml_get_error_code($parser)),
  xml_get_current_line_number($parser)));
}

// Free the XML parser
xml_parser_free($parser);
?>


이 파일을 사용해서 note.xml을 parsing하는 순서를 보여드리면...


<?xml version="1.0" encoding="UTF-8"?>

<note>

<to>Tove</to>

<from>Jani</from>

<heading>Reminder</heading>

<body>Don't forget me this weekend!</body>

</note>


먼저 첫줄 <?xml... 은 그냥 무시됩니다. 

두번째 줄 <note>가 들어오면, start event handler로 등록된 start() 함수가 호출되는데, 이때 $element_name에는 "NOTE"가 지정됩니다. 따라서 case 문 등을 사용해 이를 처리해 줍니다.


function start($parser,$element_name,$element_attrs) {

  switch($element_name) {

    case "NOTE":

    echo "-- Note --<br>";

    break;

    case "TO":

    ....


그 다음엔 data event handler가 호출됩니다. (<NOTE>의 경우에는 data에 공백 "  " 만 전달됩니다.)


function char($parser,$data) {

  echo $data;

}


그 다음엔 <to>Tove</to>가 처리될 차례죠. 이것도 비슷한 방식으로 아래와 같은 순서로 처리됩니다.


TO ->start event

Tove -> data event

TO ->end event

" " -> data event


이런 식으로 계속 이벤트를 처리하는 방식으로 처리하면 됩니다. 하나의 노드가 여러개의 이벤트로 나눠오기 때문에 데이터를 처리하는 게 복잡합니다만, 그래도 가능합니다.


====

아래는 제가 테스트해본 프로그램입니다. W3C의 books 예제파일 을 읽어들여서 이를 mySQL 에 삽입하는 예제입니다. 


여기에서 약간 중요한 점이 두 가지 있습니다. 위의 예제와는 달리, xml에 attribute가 있어서 이를 처리하는 부분이 추가되었는데요, 여기에서 each() 함수를 사용했습니다. 또 다른 하나는, mySQL에 입력할 때, prepared statement를 사용했습니다. $stmt=$conn->prepare()를 사용하여 미리 구문만 mySQL로 보내어 미리 최적화를 시킨 후, $stmt->execute();로 실행시켰습니다. 이렇게 해야 실행속도가 빨라진 답니다.



나머지는 아래의 코멘트를 참고하세요.


민, 푸른하늘


<?php


// mySQL DB 연결

require_once 'mySQL_login.php'; //이 파일은 각자의 환경에 맞게 준비해야 함

$conn = new mysqli($db_hostname,$db_username,$db_password, $db_database);

if($conn->connect_errno) {

    die("Connection failed: " . $connection->connect_error);

}


// Table이 미리 있다면 삭제함


$sql = "DROP TABLE IF EXISTS books";

if (!$conn->query($sql)) {

die("Error droping table: " . $conn->error);

}


// Table 생성

$sql = "CREATE TABLE `books` (

  `title` varchar(50) NOT NULL,

  `category` varchar(30) NOT NULL,

  `author` varchar(30) NOT NULL,

  `lang` varchar(10) NOT NULL,

  `year` smallint(6) NOT NULL,

  `price` float NOT NULL

) ENGINE=MyISAM";


if (!$conn->query($sql)) {

die("Error creating table: " . $conn->error);

}


// bind_para 에 사용되는 변수 초기화

$b_title = $b_author = $b_category = $b_lang = "";

$b_year = $b_price = 0;


// prepared statement 준비

$stmt = $conn->prepare("INSERT INTO books (title, author, category, lang, year, price) VALUES (?, ?, ?, ?, ?, ?)");

$stmt->bind_param("ssssid", $b_title, $b_author, $b_category, $b_lang, $b_year, $b_price);


// XML parser 생성

$parser=xml_parser_create();


// XML을 parsing 한 후 저장할 array 초기화

$num_books = 0;

$book = array("TITLE"=>"", "AUTHOR"=>"", "CATEGORY" => "" , "LANG" => "", "YEAR" => 0, "PRICE" => 0);

$index = "";


// Element Start event handler. 여기에서는 $index만 저장함.

function start($parser,$element_name,$element_attrs) {


    global $index,$book;

    

    switch($element_name) {

      case "BOOK":

          break;

      case "TITLE":

          $index = "TITLE";

          break;

      case "AUTHOR":

          $index = "AUTHOR";

          break;

      case "YEAR":

          $index = "YEAR";

          break;

      case "PRICE":

          $index = "PRICE";

          break;

    }


    // attribute의 경우엔 each로 처리함. 

    if(!empty($element_attrs)){

        $temp = each($element_attrs);

        $book[$temp[0]] = $temp[1];

    }

}


// Element Stop event handler. BOOK이 끝나는 시점에서 $stmt를 실행하여 $book array에 들어 있는 내용을 mySQL로 저장. 

function stop($parser,$element_name) {

    

    global $num_books, $book, $index, $stmt;

    global $b_title, $b_author, $b_category,$b_lang, $b_year, $b_price;

    $b_title = $book['TITLE'];

    $b_author = $book['AUTHOR'];

    $b_category = $book['CATEGORY'];

    $b_lang=$book['LANG'];

    $b_year = $book['YEAR'];

    $b_price = $book['PRICE'];

    

    if($element_name == "BOOK") {

          $num_books++;

          $stmt->execute();

          print_r($book);

          echo "<br>";

    }

}


// Element Data event handler. 실제의 값을 $book 배열에 저장.

function char($parser,$data) {

  global $book, $index;

  

  if($index != "") {

    $book[$index] = $data;

    $index = "";

  }

}


// Specify element handler

xml_set_element_handler($parser,"start","stop");


// Specify data handler

xml_set_character_data_handler($parser,"char");


// Open XML file

$fp=fopen("books.xml","r");


// Read data. feof()을 만날 때까지 계속 파일을 읽어들이고 parsing 함.

while ($data=fread($fp,4096)) {

  xml_parse($parser,$data,feof($fp)) or 

    die (sprintf("XML Error: %s at line %d", 

  xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser)));

}


// Free the XML parser

xml_parser_free($parser);

?>




Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02016. 4. 30. 08:52

요즘 다시 PHP 연습중입니다. 하나 만들고 싶은 게 있어서요. 


예전에는 그냥 일반 텍스트에디터를 사용해서 연습을 했었습니다. 그런데 이번에 easyPHP를 설치하다보니, 디버거를 사용할 수 있다는 것을 알게 되어서 일단 easyPHP에 XDebug를 설치했습니다.


그런데, 디버거를 사용하는게 마땅치 않았습니다. eclipse PDT라는 통합개발환경 IDE에서 디버깅을 할 수 있다는 글을 따라해 보기도 했고, notepad++에 플러그인으로 설치했다는 글을 따라하기도 했습니다. 크롬 익스텐션을 설치해보기도 했고요. 물론 모두 실패했습니다. 


그래서 마지막이라는 심정으로 다시한번 검색을 해서 netbeans IDE와 XDebug를 연동할 수 있다는 글을 따라했습니다. 억지로 성공했네요. 


일단 NetBeans IDE는 여기에서 설치하실 수 있습니다. 저는 PHP x64 버전으로 설치했습니다.


설치한 후, NetBeans에서는 아래 그림처럼 설정합니다. Tools -> Options 에 있습니다. 여기에서 Debugger Port는 XDebug 설정값(php.ini)와 동일하게 설정해야 합니다.


한가지, Watches and Ballon Evaluation 을 켜면 변수들의 값을 확인하는데는 편하지만, 불안정하다고 하여 그냥 꺼뒀습니다.



다음으로 폴더설정... 이게 좀 까다로웠습니다. NetBeans의 Project 설정과 easyPHP의 실행환경하고 맞춰주어야만, NetBeans에서 디버거를 실행시킬 때 자동으로 실행시킬 수 있기 때문입니다.


먼저 아래가 easyPHP의 대시보드입니다. 여기에서 폴더가 두개 지정되어 있습니다. Workding Directories와 Portable Directory 입니다. 


여기에 각각 파일을 넣고 실행해보면 Working Directory의 경우, http://127.0.0.1/edsa-WD/ 로 실행되며, Portable Directory는 http://127.0.0.1/로 실행됩니다. 즉, Portable Directory로 지정되어 있는 위치가 root directory로 인식되는 것입니다.  따라서 NetBeans의 실행 디렉토리도 여기로 맞춰 주면 됩니다. (참고로, Working directory 의 경우 edsa-가 강제로 추가되어서 설정하기가 힘들었습니다.)


즉 NetBeans에서 프로젝트를 생성할 때... 먼저 File -> New Project 를 선택하면 아래와 같이 뜨고



다음으로... 프로젝트 이름과 소스 위치를 정하는 화면에서는 자신이 관리하는 위치를 지정해 줍니다. (그냥 프로젝트를 easyPHP의 Portable Directory로 지정된 위치 내에 만든다면 다음단계는 생략해도 됩니다.)



다음으로 실행환경을 아래와 같이 정해줍니다. 반드시 Source Folder의 내용을 다른 위치에 복사하도록 지정을 하고, 그 위치를 easyPHP의 Portable Directory와 맞춰줍니다. 이렇게 하면 자신이 관리하는 위치에서 작업을 하더라도 실행할 때는 해당위치로 복사가 되어, localhost에서 실행될 수 있습니다.



===

이렇게 해둔 상태에서 원하는 파일에서 마우스 오른쪽버튼을 누르고 Debug를 지정하면...



다음과 같이 웹브라우저에서 해당프로그램이 Debug 상태로 실행됩니다. 아래를 잘보면 localhost의 응답을 기다리는 중... 으로 표시됩니다.



아울러, Netbeans 편집화면에서는 아래와 같이 디버그용 버튼들이 활성화되고, PHP 첫라인인 <?php 에서 실행이 중지된 상태로 사용자의 입력을 기다리게 됩니다. 단추나 F7(Step into), F8(Step Over) 등을 이용해 한줄씩 실행시키고 변수의 상태를 확인하면서 디버깅하면 됩니다.



====

이상입니다. 아직 NetBeans를 잘 몰라서 억지로 여기까지만 설정을 했습니다. 앞으로 좀더 사용하다보면 좀 더 깔끔한 방법이 생길지도 모르겠습니다.


민, 푸른하늘

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02016. 4. 27. 10:25

프로그램 개발을 위해서는 Debugger가 필수입니다. 특히 대형프로젝트가 될 수록 Debugger 없이는 거의 개발이 불가능합니다. 


제가 사용중인 easyPHP에도 디버거를 설치할 수 있습니다. (다만 실행은 별도의 환경이 필요합니다. 이건 다른 글에서...) 디버거는 널리 사용되고 있는 XDebug를 사용했습니다.


XDebug를 설치하려면 먼저 easyPHP에서 실행환경을 체크해야 합니다. 저는 아래와 같이 easyPHP 의 대시보디에서 "Portable Directory"로 등록된 곳에 원래 들어있는 phpinfo.php를 사용했습니다. 그냥 <?php echo phpinfo(); ?>와 같이 한줄 짜서 실행시켜도 됩니다.


 

그러면 다음과 같은 화면을 볼 수 있습니다. 여기에서 빨간 표시를 한 4가지를 체크해야 합니다.



이제 xdebug.org 다운로드 사이트 로 이동하여 적당한 dll을 다운받아야 합니다. 위에서 확인한 정보를 바탕으로 적당한 것을 선택하면 됩니다. PHP 5.6 버전이고, VC11이며, x86이니 32bit 버전입니다. 마지막으로 Thread Safety가 enabled로 되어 있으면 TS버전을 받으면 됩니다. 이렇게 다운로드 받은 파일을 적당한 곳에 복사해줍니다.(저는 easyPHP 디렉토리에 넣어주었습니다.)



다음은 설치된 내용을 설정화일에 반영해야 합니다. 이를 위해서 php.ini 파일을 편집합니다. php.ini 파일은 easyPHP 설치위치 ->eds-binaries -> php -> php버전명 속에 들어 있습니다. 저의 경우에는 아래와 같습니다.


\EasyPHP-Devserver-16.1\eds-binaries\php\php5619vc11x86x160426163245


이 php.ini 파일을 적당한 편집기로 열고, zend 를 검색해보면 #zend_extension 이라는  부분이 있습니다. 여기에 아래와 같이 추가해 줍니다. 물론 자신의 경로명과 파일명을 넣어야겠죠.


zend_extension="C:\Program Files (x86)\EasyPHP-Devserver-16.1\eds-binaries\php\php5619vc11x86x160426163245\php_xdebug-2.4.0-5.6-vc11.dll"



그리고 바로 아래에 다음과 같은 항목들을 추가해줍니다.


xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000


그 다음엔 Apache 서버를 껐다가 다시 실행시키고, 다시 phpinfo.php를 실행시킵니다. 이때 아래와 같이 Zend engine 부분에 with Xdebug... 라는 행이 추가되면 성공입니다.



====

그런데, 이렇게 실행해도 아무런 변화가 없습니다. 이 상태에서는 디버거를 실행시킬 수도 없고요. 그래서 별도의 환경을 구축해야 합니다. 이건 NetBeans 디버깅환경 설정을 읽어보시기 바랍니다.



민, 푸른하늘


Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02016. 4. 26. 20:04

예전에 반쯤 공부하다가 팽겨쳐 뒀던 PHP를 다시 공부하기로 했습니다. 


먼저 예전처럼 Zend Server를 설치하기로 했습니다. 제가 공부하는 책에서 Zend Server를 설치하여 사용하기 때문이었습니다.


그런데 그동안 업그레이드가 되면서 무료버전이 사라졌더군요. Free Trial 버전은 1개월, 기타 학생용버전 등은 1년 이후에는 정식버전을 사야하는 것 같았습니다. 뭐 그래서 과감하게 포기. 설치하다가 에러가 발생하는 게 아니었으면 계속 갔을지도 모르지만...


하여튼... 그래서 best WAMP로 검색을 좀 해봤습니다. WAMP는 Windows + Apache + MySQL + PHP 로 구성된 Suite를 말합니다. 물론 Zend Server를 순위에 올린 사이트도 있었지만, 다른 제품도 많이 있더군요. 저는 그중에서 easyPHP가 제일 마음에 들었습니다. 쉽다니까. ㅎㅎ


easyPHP.org 에 접속하면 아래와 같은 화면이 보입니다. 좌측은 DevServer 즉, 개발용 서버이고, 우측은 WebServer, 즉 단순 서버용입니다. 저는 최신버전의 DevServer를 택했습니다.



버튼을 클릭하면 설치프로그램이 다운로드 되고, 그것을 실행시키면 다음과 같은 화면이 나옵니다. 아무런 설정이 필요 없습니다. 그냥 자동으로 설치됩니다.



그런데, 설치가 끝난 후 실행시키려면 다음과 같은 화면이 뜹니다. 뭔가 설치를 해야 한다고 나오네요.



원래 첫화면에도 "Visual C++ Redistributable for Visual Studio 2015 x86 or x64 required" 라고 되어 있는데, 자신의 컴퓨터에 맞게 x86 버전이나 x64 버전을 설치하면 됩니다. 



그런데... 이 두개의 파일을 모두 설치했음에도 동일한 에러가 발생하네요. 그래서 좀 더 찾아보니, "Visual C++ Redistributable for Visual Studio 2012"도 설치해야 한답니다. 그래서... ㅠㅠ 어쨌든 이렇게 다 설치를 했더니 에러가 발생하지 않았습니다. 


자... 이제 시작.!!! 바탕화면에 깔린 아이콘을 클릭!!! 그런데 아무런 변화가 없었습니다. 잠시 기다려도 감감 무소식. 무슨 화면같은게 뜨던가, 웹브라우저에 뭔가 나타나던가... 그래야 할텐데 아무것도 나타나지 않았습니다. 또한 홈페이지에는 당연히 뭔가 문서가 있겠지 싶었는데, 아무것도 안보이니 정말 황당했습니다. 


이때 아래와 같이 윈도 오른쪽 아래에 있는 '숨겨진 아이콘'에서 DevServer 아이콘을 클릭하고 Open Dashboard를 선택하면...



웹브라우저에 아래와 같은 화면이 나타납니다. 저는 여기에서 아래처럼 3가지를 먼저 설정했습니다. phpMyAdmin은 아직 제가 몰라서 나중으로...


여기에서 HTTP SERVER를 누르고 APACHE 서버를 선택해서 Start를 눌러주고요,



DB SERVER에서 MYSQL을 선택하고 Start를 눌러주면 됩니다. 그러고 나서 다시 Dashboard로 돌아오면 아래와 같은 모습이 됩니다.



이제 마지막으로 작업공간을 지정하면 됩니다. 윗쪽은 easyPHP에서 사용하는 디렉토리명이고, 아래는 실제 사용할 폴더명을 복사해서 넣어주면 됩니다. 



====

이 정도하면, 개발용 설정은 거의(아주 간략하게만) 끝났습니다. 하나만 실험을 해보죠.

먼저 아래와 같은 내용으로 hello.php 라는 파일을 만들어 작업 디렉토리에 넣어줍니다.


<?php 

echo "Hello World!"; 

?>


이제 작업 디렉토리를 확장시켜보면 아래와 같이 hello.php 가 들어있습니다.


hello.php 오른쪽에 있는 눈모양의 그림을 클릭하면, 새로운 창이 열리고 실행됩니다.


===

2016/5/14 추가


그동안 easyPHP를 계속 사용해 왔지만, 에러가 계속 발생하여 여러번 재설치하다가 오늘 드디어 XAMPP를 설치했습니다. (참고로 easyPHP는 별도로 삭제 프로그램이 없으며, 그냥 설치된 디렉토리를 찾아 지워주기만 하면 삭제가 완료됩니다.)


XAMPP도 설치는 그다지 까다로울 것이 없습니다. 그냥 AphacheFriends 사이트에서 원하는 파일을 다운로드 받아 실행만 시키면 됩니다. 저는 PHP the right way의 권고에 따라 PHP7 버전으로 설치했습니다. Backward compatibility의 문제가 거의 없고, 속도도 빠르다고 하니까요.


다만 설치 초기에 UAC 설정으로 인해 잘 돌아가지 않을 수 있다... 는 경고가 뜨는데, Program Files(x86)에 설치하지 말고 별도의 폴더 (예: c:\xampp)에 설치해주면 문제가 없다고 합니다.



그 다음에는 easyPHP와 그다지 다를 건 없었습니다. xamppcontrol.exe을 실행시켜 보면 아래와 같은 창이 뜨는데, 여기에서 Apache와 MySQL (실제로는 MariaDB)를 실행시킬 수 있고, 설정도 바꿀 수 있습니다. Port 번호만 유의하면 문제가 없습니다.



또한 XDebug 설정도 EasyPHP의 경우와 거의 동일합니다. 자신의 버전에 맞는 XDebug 파일을 복사해 두고, php.ini 파일을 적당하게 수정만 해주면 완료입니다. 


머... 이상으로 대충~~


민, 푸른하늘

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02014. 6. 26. 16:24

이제 PHP 투토리얼 시리즈 마지막입니다. AJAX네요. 어차피 클라이언트와 데이터를 주고 받으려면 AJAX를 제일 많이 쓰지 않을까... 하는 생각이 듭니다. 써봐야 알겠지만요.


AJAX의 개념


  • Asynchronous Javascript and XML
  • 빠르고 동적인 웹페이지를 만드는 기술
  • 서버간에 작은 데이터만 교환하면서 웹페이지가 비동기적으로 갱신되도록. 즉, 화면의 일부만 갱신 가능
  • GoogleMaps, Gmail, Youtube 등이 모두 AJAX 활용
  • AJAX는 인터넷 표준에 기초함
    • XMLHttpRequest (데이터를 비동기적으로 서버와 주고 받음)
    • Javascript/DOM (정보의 표현)
    • CSS (데이터 스타일)
    • XML (데이터 전달 포맷)
<html>
<head>
<script>
function showHint(str) {        // key를 하나씩 누를때마다 실행됨
  if (str.length==0) { 
    document.getElementById("txtHint").innerHTML="";    //공백일 경우, 힌트도 공백으로
    return;
  }
  var xmlhttp=new XMLHttpRequest();
  xmlhttp.onreadystatechange=function() {        // 상태가 변할때 실행될 함수를 등록
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
      document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("GET","gethint.php?q="+str,true);    // GET 모드로 호출
  xmlhttp.send();
}
</script>
</head>
<body>

<p><b>Start typing a name in the input field below:</b></p>
<form> 
First name: <input type="text" onkeyup="showHint(this.value)">
</form>
<p>Suggestions: <span id="txtHint"></span></p>

</body>
</html>


AJAX 와 MySQL


  • AJAX를 사용하여 데이터베이스와 대화식으로 통신
  • html 파일

<html>

<head>

<script>

function showUser(str) {        // user를 선택했을 때 실행되는 함수

  if (str=="") {

    document.getElementById("txtHint").innerHTML="";

    return;

  } 

  xmlhttp=new XMLHttpRequest();

  xmlhttp.onreadystatechange=function() {      // 상태변경시 실행되는 함수 등록

    if (xmlhttp.readyState==4 && xmlhttp.status==200) {

      document.getElementById("txtHint").innerHTML=xmlhttp.responseText;

    }

  }

  xmlhttp.open("GET","getuser.php?q="+str,true);  // GET 모드로 호출

  xmlhttp.send();

}

</script>

</head>

<body>


<form>

<select name="users" onchange="showUser(this.value)">      // 폼 요소 생성. 

<option value="">Select a person:</option>

<option value="1">Peter Griffin</option>

<option value="2">Lois Griffin</option>

<option value="3">Joseph Swanson</option>

<option value="4">Glenn Quagmire</option>

<option value="5">민 허</option>

</select>

</form>

<br>

<div id="txtHint"><b>Person info will be listed here.</b></div>    // 여기에 표시됨.


</body>

</html>

  • PHP 파일

<?php

$q = intval($_GET['q']);        // integer 로 받음.


$con = mysqli_connect('localhost','id','password','db_name');  // 데이터베이스 연결

if (!$con) {

  die('Could not connect: ' . mysqli_error($con));

}


mysqli_select_db($con,"Persons");        // 테이블 선택    

$sql="SELECT * FROM user WHERE id = '".$q."'";        // id 를 기준으로 선택 (1...5)

$result = mysqli_query($con,$sql);        // query 결과는 $result


echo "<table border='1'>

<tr>

<th>Firstname</th>

<th>Lastname</th>

<th>Age</th>

<th>Hometown</th>

<th>Job</th>

</tr>";


while($row = mysqli_fetch_array($result)) {        // $result 를 배열로 변환

  echo "<tr>";

  echo "<td>" . $row['FirstName'] . "</td>";

  echo "<td>" . $row['LastName'] . "</td>";

  echo "<td>" . $row['Age'] . "</td>";

  echo "<td>" . $row['Hometown'] . "</td>";

  echo "<td>" . $row['Job'] . "</td>";

  echo "</tr>";

}

echo "</table>";


mysqli_close($con);

?>


AJAX XML


  • form에서는 거의 동일함. PHP에서 XML을 처리하는 방법만 차이남
  • XML을 직접 처리하는 방법은 많이 까다로워서... 생략
  • 차라리 XML 그 자체를 반환한 후, 클라이언트 쪽에서 JQuery로 처리하는 게 나을 듯


AJAX Live Search


  • 실시간으로 XML에서 검색하여 존재하는 것을 모두 보여주는 방식
  • 키보드를 누를때마다 계속해서 검색 결과가 바뀜





















Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02014. 6. 26. 11:45

다섯번째는 XML. 


XML Expat Parser


  • XML Parser는 두가지 종류가 있음
    • Tree 기반 parser : XML 문서를 트리구조로 변환, 문서 전체를 분석하고, 트리의 각 요소에 접근. DOM(Document Object Model)
    • Event 기반 parser : XML 문서를 이벤트의 연속으로 봄. 특정 이벤트가 발생하면 그와 연결된 함수를 호출하는 방식. 문서의 구조보다 내용에 집중. 더 빠르다. XML 구조에 문제가 있어도 문제없음. 
  • Expat Parser는 Event 기반 parser임. PHP 웹 어플에 최적
  • Expat Parser는 PHP 에 내장되어 있음


XML DOM


<!--?xml version="1.0" encoding="UTF-8"?-->

<from>Jani</from>

  • 레벨 1 : XML document
  • 레벨 2 : Root element : <from>
  • 레벨 3 : text element : "Jani"


SimpleXML


  • PHP5에서 새롭게 등장
  • XML 요소의 이름과 text를 간단하게 추출
  • 코드를 간단하게 짤 수 있음
  • XML 문서를 객체로 변환함
    • 요소는 SimpleXMLElement 객체의 속성(attribute)로 변환됨. 어느 레벨에 여러개의 요소가 있을 경우 배열에 들어가게 됨
    • 속성은 associative 배열로 접근가능 (index가 attribute의 name)
    • 요소의 text는 문자열로 변환됨. 여러개의 text 노드가 있을 경우, 순서대로 배열됨
  • SimpleXML은 XML파일로부터 데이터를 읽거나 추출하거나, 텍스트 노드/속성을 편집할 때 빠르고 간단하게 수행가능
  • 복잡한 XML의 경우, Expat이나 DOM을 사용하는 것이 나음


















Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02014. 6. 24. 17:06

이제 4번째네요... PHP로 할 수 있는 게 정말 다양하다는 걸 다시한번 느꼈습니다. 그리고... 그냥 javascript면 대충 해결되겠지... 라고 생각했는데... 참으로 거시기하네요. 오히려 웹앱을 개발하려면 서버측 개발이 더 중요한데 말이죠.


MySQL  개요


  • MySQL은 웹에서 사용되는 DBMS. 서버에서 수행됨. 크기에 관계없이 사용가능. 
  • 빠르고, 신뢰성 높고, 사용하기 쉬움. 표준 SQL의 지원, 다양한 platform 지원, 무료
  • Oracle에서 개발 보급. 이름은 공동개발자의 딸의 이름(My)를 따서 지음
  • 특히 MySQL + PHP 를 하면 cross-platform 으로 매우 유용함
  • MySQL을 어떻게 사용하는가는 SQL을 얼마나 잘 할 수 있는가에 달려있음.


MySQL 서버에 접속


<?php

$con = mysqli_connect("example.com", "peter", "abc123", "my_db");

// host, username, password, db_name

if (mysqli_connect_errno()) {

echo "Failed to connect to MySQL. : " . mysqli_connect_errno();

}


....


mysqli_close($con);

?>



Create DB / Create Table


  • cafe24 호스팅의 경우, 새로운 DB를 생성할 수 없음. 기존의 DB를 사용해야 함. 
  • 기존 DB 명은 사용자id와 동일


....

$sql = "CREATE DATABASE my_db";

if(!mysqli_query($con, $sql) {

echo "Error creating DB : " . mysqli_error($con);

} else {

echo "Successful";

}


$sql ="CREATE TABLE Persons(

PID INT NOT NULL AUTO_INCREMENT,     //

PRIMARY KEY(PID),                                // PID를 primary key!

FirstName CHAR(30), 

LastName CHAR(30), 

Age INT)";


if(!mysqli_query($con, $sql) {

echo "Error creating Table : " . mysqli_error($con);

} else {

echo "Successful";

}



Insert a row


  • INSERT INTO table_name VALUES (value1, value2, value3,...)
  • INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...)

  • 데이터 입력을 받는 폼

<html>

<body>


<form action="insert_data.php" method="post">

Firstname: <input type="text" name="firstname"><br />

Lastname: <input type="text" name="lastname"><br />

Age: <input type="text" name="age"><br />

<input type="submit">

</form>


</body>

</html>


  • 실제로 Table에 입력해 주는 php

<?php

$con=mysqli_connect("localhost","id","pw","dbname");

// Check connection

if (mysqli_connect_errno()) {

  echo "Failed to connect to MySQL: " . mysqli_connect_error();

}


// 폼에서 입력된 항목을 SQL INJECTION 을 방지하기 위해 escape 처리

$firstname = mysqli_real_escape_string($con, $_POST['firstname']);

$lastname = mysqli_real_escape_string($con, $_POST['lastname']);

$age = mysqli_real_escape_string($con, $_POST['age']);


$sql="INSERT INTO Persons (FirstName, LastName, Age)

VALUES ('$firstname', '$lastname', '$age')";


if (!mysqli_query($con,$sql)) {

  die('Error: ' . mysqli_error($con));

}

echo "1 record added";


mysqli_close($con);

?>



Read Data from MySQL


  • mysqli_query()를 사용하여 SELECT 문을 사용하면 데이터를 읽을 수 있음
  • mysqli_fetch_array를 사용하면 한 record 씩 배열로 받아짐.
  • 그 결과를 html로 표현함.

<?php

$con=mysqli_connect("localhost","id","pw","db_name");

// Check connection

if (mysqli_connect_errno()) {

  echo "Failed to connect to MySQL: " . mysqli_connect_error();

}


$result = mysqli_query($con,"SELECT * FROM Persons");


echo "<table border='1'>

<tr>

<th>Firstname</th>

<th>Lastname</th>

</tr>";


while($row = mysqli_fetch_array($result)) {

  echo "<tr>";

  echo "<td>" . $row['FirstName'] . "</td>";

  echo "<td>" . $row['LastName'] . "</td>";

  echo "</tr>";

}


echo "</table>";


mysqli_close($con);

?>






















Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02014. 6. 22. 23:49

저는 요즘 자바스크립트 열공중입니다. 그런데, 자바스크립트를 공부하려니, 점점 공부할게 늘어납니다. 자바스크립트는 클라이언트용 스크립트입니다. 즉, 웹브라우저와 같은 환경에서 서버로부터 받은 정보를 처리하는 용도입니다. 


그런데, 서버에서도 여러가지 작업이 필요합니다. 이를 위해서 필요한 게 서버측 스크립트인 PHP입니다.  파일을 올리고 DB를 조작하는 등 서버와 통신 등을 담당합니다.


이글은 http://www.w3schools.com/php/에 있는 PHP 5 투토리얼을 제 마음대로 간략하게 정리한 겁니다. 참고하세요.


PHP 는 서버 스크립트용 언어로, 동적/대화식 웹페이지를 빠르게 구축할 수 있는 강력한 도구이다. PHP는 널리 사용되며, 무료이고, 마이크로소프트의 ASP와 같은 유사한 도구를 효율적으로 대체할 수 있다.


첫번째 예제: 

<!DOCTYPE html>
<html>
<body>

<?php
echo "My first PHP script!";
?>


</body>
</html>


PHP란 무엇인가?

  • PHP는 "PHP Hypertext Preprocessor"의 약어임
  • PHP는 광범위하게 사용되는 오픈소스 스크립트 언어
  • PHP 스크립트는 서버에서 실행됨
  • PHP는 무료임.

PHP 파일은 어떤 것이 있나?

  • PHP files can contain text, HTML, CSS, JavaScript, and PHP code PHP code are executed on the server, and the result is returned to the browser as plain HTML PHP files have extension ".php"
  • PHP 파일에는 텍스트, HTML, CSS, Javascript, PHP 코드가 들어갈 수 있다.
  • PHP는 서버에서 실행되며, 그 결과는 브라우저에게 일반 HTML 형식으로 반환됨.
  • PHP 파일의 확장자는 .php

PHP로 할 수 있는 것

  • PHP can generate dynamic page content PHP can create, open, read, write, and close files on the server PHP can collect form data PHP can send and receive cookies PHP can add, delete, modify data in your database PHP can restrict users to access some pages on your website PHP can encrypt data
  • PHP는 동적인 페이지를 생성할 수 있음
  • PHP는 서버에 파일을 생성하고, 열기/읽기/쓰기/닫기 등이 가능함
  • PHP는 폼 data를 수집할 수 있음
  • PHP는 쿠키를 전송/수신할 수 있음
  • PHP는 데이터베이스에서 데이터를 추가/삭제/수정할 수 있음
  • PHP는 웹사이트중 일부를 사용자가 접근하지 못하도록 막을 수 있음
  • PHP는 데이터를 암호화할 수 있음

PHP의 결과가 HTML만 나오는 건 아님. 영상, PDF, 플래시 등도 가능하다. XHTML, XML 등의 텍스트도 가능


PHP를 사용하는 이유

  • PHP는 다양한 플랫폼(윈도, Linux, Unix, Mac OS X 등)을 지원함
  • 현재 사용되는 거의 모든 서버(Apache, IIS, 등)와 사용가능
  • 다양한 데이터베이스 지원
  • 무료. www.php.net 에서 다운로드 받으면 됨.
  • 배우기 쉽고, 서버에서 효율적으로 운영됨

PHP 문법

  • PHP는 문서 어디나 있어도 됨. <?php 로 시작하고 ?>로 끝남
  • 기본 확장자는 .php
  • PHP 파일에는 일반적으로 HTML 태그와 PHP 스크립트가 들어있음

<!DOCTYPE html>
<html>
<body>

<h1>My first PHP page</h1>

<?php
echo "Hello World!";
?>


</body>
</html>


참고로 php 구문은 세미콜론으로 끝남. 

코멘트

3가지 종류가 있음

  • 라인 코멘트 : //, #
  • 블록 코멘트 : /*   */

대소문자 구별

  • 사용자 정의 함수, 클래스, 키워드(if, else, while, echo, 등)은 대소문자 구별 없음
  • 단, 모든 변수는 대소문자를 구별함

PHP 변수


  • 변수명은 $로 시작하고 그 뒤에 변수명이 따라옴
  • 변수명은 반드시 문자 혹은 밑줄로 시작해야 함
  • 변수 이름은 숫자로 시작할 수 없음
  • 변수 이름에는 영문자, 숫자, 밑줄만 사용가능(A-z, 0-9, and _ ) 
  • 변수명은 대소문자를 구별함

변수선언

  • PHP에는 별도의 변수 선언이 없음. 값을 할당하는 순간 생성됨
  • 변수타입이 정해져 있지 않음
  • 변수타입은 필요에 따라 자동으로 변환됨


<?php
$txt="Hello world!";
$x=5;
$y=10.5;
?>


변수 범위(Scope)

  • 변수는 어디에서나 선언할 수 있음. 
  • 함수 바깥쪽에서 선언한 변수는 전역범위(global scope)를 가지며, 함수 바깥쪽에서만 사용가능 
  • 함수 내부에서 선언한 변수는 지역범위(local scope)를 가지며, 해당함수 안쪽에서만 사용가능

Global 키워드

  • global 이라는 키워드를 사용하면 global 변수를 함수 내부에서 사용할 수 있음.
  • 함수 내부에서 변수명 앞에 global이라고 쓰면 됨.
  • 글로벌 변수는 $GLOBAL[index]에 보관되므로(여기에서 index는 변수명), 이를 통해 직접 접근할 수도 있음

Static 키워드

  • 로컬 변수는 함수가 종료가 되면 사라지지만, static 변수는 그대로 살아 있음. 변수 앞에 stattic 키워드를 붙이면 됨
<?php
$x=5;
$y=10;

function myTest()
{
global $x,$y;
$y=$x+$y;

// $GLOBALS['y']=$GLOBALS['x']+$GLOBALS['y']; 도 가능함
}


myTest();
echo $y; // outputs 15
?>


echo 와 print

  • 출력하기 위한 함수.
  • echo : 여러개의 string을 한꺼번에 출력 가능
  • print : 한번에 한개만 가능. 항상 1을 반환함.
  • echo "문자열" 도 가능하고, echo("문자열") 도 가능함. print 도 비슷

<?php
$txt1="Learn PHP";
$txt2="W3Schools.com";
$cars=array("Volvo","BMW","Toyota");

echo $txt1;
echo "<br>";
echo "Study PHP at $txt2";
echo "My car is a {$cars[0]}";
?>



데이터 타입

  • String, Integer, Floating point numbers, Boolean, Array, Object, NULL. 등이 있음.
  • string
    • 큰따옴표, 작은 따옴표 모두 허용. 
  • Integer
    • 10진수, 16진수 (0x로 시작), 8진수 (0으로 시작) 가 지원됨.
    • var_dump()함수를 사용하면 데이터 타입과 값이 반환됨.
  • Floating point numbers
    • 일반형(소수점) 및 지수형(2.4e4 등) 지원함
  • Bloolean
    • true, false
  • Array
    • 하나의 변수에 여러개의 값을 저장
    • index는 0부터 시작. 아래에서는 $cars(1)=="BMW".
    • $cars=array("Volvo","BMW","Toyota");
  • Object
    • 데이터와 처리방법(메소드)이 저장되어 있는 데이터 타입
    • 객체는 반드시 명시적으로 정의해야 함
    • 먼저 class 키워드를 사용하여 class를 정의해야 함.
    • this->$color 와 같은 방식으로 프로퍼터 참조.
  • NULL
    • 값이 없음을 알려주는 타입. 이 타입의 값은 NULL 하나뿐임. 
    • 변수가 값이 있는지 없는지 알아낼 수 있음. "" 과 NULL은 다름
    • 변수에 NULL을 저장하면 변수의 값을 지울 수 있음

PHP String 함수

  • strlen()
  • strpos(A, a) - 문자열 A에 a가 있는지 검색. 성공하면 첫번째 매칭 위치 반환. 아니면 false 반환

PHP 상수

  • 프로그램 시행중 값을 변경시킬 수 없는 식별자(이름)
  • 변수와는 달리 $ 표시가 없음. 범위(scope)는 자동적으로 global임
  • 상수는 define()을 사용하여 정의. 세번째 인수는 대소문자 구분여부를 설정

<?php
define("GREETING", "Welcome to W3Schools.com!", true); //case-insensitive
echo GREETING;
?>


PHP 연산자

  • 산술연산자 : +, -, *, /, %
  • 할당연산자 : =, +=, -=, *=, /=, %=
  • 문자열연산자 : . (문자열 연결) ...
  • 증가연산자, 감소연산자 : ++, --. 전치 후치 모두 가능

<?php
$a = "Hello";
$b = $a . " world!";
echo $b; // outputs Hello world! 
?>

PHP 비교연산자

  • 동등, 일치 : ==, === : 일치는 데이터 타입도 같아야 함.
  • 같지  않음 : <>, !=    : 이 두가지는 동일
  • 크다/작다  : >, <, <=, >=

<?php

$x = 100;

$y = "100";


var_dump($x==$y);   // boolean(true)

var_dump($x===$y);   // boolean(false)


?>

PHP 논리연산자

  • and, &&,          or, ||,      xor,    !

PHP 배열 연산자

  • + : 두 배열을 합침.  (단, 중복된 key를 덮어쓰지는 않음)
  • 비교연산자 : ==, ===, <>, !=, !==     : ===의 경우, key/values 일치, 순서일치, 타입일치 모두 성립해야 함

PHP 조건문

  • if()  {....}
  • if() elseif() elseif() else

<?php
$t=date("H");
if ($t<"10")
  {
  echo "Have a good morning!";
  }
elseif ($t<"20")
  {
  echo "Have a good day!";
  }
else
  {
  echo "Have a good night!";
  }
?>


PHP switch 문

  • c와 동일함

PHP 반복문

  • while (condition is true) { execute this code }
  • do { execute this code) while (condition is true)
  • for (initialize; test; increment) {execute}
  • foreach ($array as $value) {execute}

<?php 
$colors = array("red","green","blue","yellow"); 
foreach ($colors as $value)
  {
  echo "$value <br>";
  }
?>


PHP 함수

  • 함수 선언 : function functioname(arg, arg, ..) { }
    • 함수명은 대소문자를 구분하지 않음
  • default arguments  -> function(arg="10") { }  와 같이 인수에 값을 지정해 두면, 인수 없이 호출 가능
  • return 수식; 방식으로 반환값을 지정

<?php
function setHeight($minheight=50)
{
echo "The height is : $minheight <br>";
}

setHeight(350);
setHeight(); // will use the default value of 50
?>


PHP 배열

  • 배열은 여러개의 값을 한꺼번에 담을 수 있는 특수한 변수
  • 배열 생성 : array(); 세가지 종류가 있음
    • indexed array : index가 숫자임
    • Associative array : named key로 참조
    • Multidimensional array : 여러개의 배열을 담은 배열
  • Indexed array : 일반적 배열, 숫자가 인덱스. 
    • $cars=array("Volvo","BMW","Toyota");  - index가 자동으로 부여됨
    • $cars[0] 등으로 참조가능. 
  • Array의 크기(요소의 갯수)는 count($cars) 로 알 수 있음

<?php
$cars=array("Volvo","BMW","Toyota");
$arrlength=count($cars);

for($x=0; $x<$arrlength; $x++)
  {
  echo $cars[$x];
  echo "<br>";
  }

// foreach로 구현하려면

// foreach($cars as $x)

//   {

//      echo $x . "<br>";

//   }
?>

  • Associative array : 이름이 키. 자바스크립트의 객체와 비슷.
    • $age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
    • 또는  $age['Peter']="35";    $age['Ben']="37";     $age['Joe']="43"; 
    • foreach 를 사용하여 순환함.

<?php
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");

foreach($age as $x=>$x_value)
  {
  echo "Key=" . $x . ", Value=" . $x_value;
  echo "<br>";
  }
?>

  • Multidimensional array : 원소가 배열인 배열

PHP 배열 소팅

  • sort() : 오름차순
  • rsort() : 내림차순
  • asort() : Associative 배열에 대해, value 를 기준으로 오름차순
  • ksort() : Associative 배열에 대해, key 를 기준으로 오름차순
  • arsort() : Associative 배열에 대해, value 를 기준으로 내림차순
  • krsort() : Associative 배열에 대해, key 를 기준으로 내림차순

PHP 전역변수 - SuperGlobals

  • 미리 정의되어 있는 전역변수. 어디에서나 접근가능. 
  • $GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_ENV $_COOKIE $_SESSION 등이 있음.

PHP $GLOBAL

  • PHP의 전역변수를 어디에서든 접근할 수 있게 해주는 Super Global 변수
  • 모든 전역변수는 $GLOBALS[index]에 저장됨. 
    • 전역변수 $gx  는 $GLOBALS['gx'] 로 접근가능.

PHP $_SERVER

  • 헤더, 경로, 스크립트 파일의 위치 등의 정보를 담고 있는 전역변수
  • $_SERVER['PHP_SELF']  현재 수행중인 스크립트 파일명 
  • $_SERVER['SERVER_ADDR'] 호스트 서버의 IP 주소
  • $_SERVER['REQUEST_METHOD'] 해당 페이지를 호출하는 데 사용된 호출방법 (POST 등)
  • $_SERVER['QUERY_STRING'] query string으로 호출되었을 경우, 그 쿼리문
  • $_SERVER['REMOTE_ADDR'] 뷰어의 IP 주소
  • $_SERVER['SCRIPT_URI'] 현재 페이지의 URI

PHP $_REQUEST

PHP $_REQUEST 는 HTML 폼을 제출한 후, 데이터를 수집하는데 사용됨.


아래의 예는 input 필드와 submit 버튼이 있는 폼임. 사용자가 submit 버튼을 제출하면, Form 의 데이터가 <form> 태그의 action 속성에 지정된 파일에 전달됨. 이 예제에서는 자기 자신을 지정하였음 <?php echo $_SERVER['PHP_SELF']; ?> 폼데이터를 다른 PHP 파일로 처리하게 하려면 여기에 파일명을 지정하면 됨. 그 다음 input 필드의 값은 super 전역변수인 $_REQUEST 를 사용하여 수집함.


<html>
<body>

<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">

// 실행시킬 파일명으로 자기 자신을 지정함
Name: <input type="text" name="fname">
<input type="submit">
</form>

<?php 
$name = $_REQUEST['fname'];  // 제출된 form에서 fname 필드 값을 읽어옴
echo $name; 
?>

</body>
</html>


PHP $_POST

PHP $_POST는 method="post"를 사용하여 HTML 폼을 제출한 후, 데이터를 수집하는데 널리 사용됨

아래의 예는 input 필드와 submit 버튼이 있는 폼임. 사용자가 submit 버튼을 제출하면, Form 의 데이터가 <form> 태그의 action 속성에 지정된 파일에 전달됨. 이 예제에서는 폼데이터를 처리하기 위해 자기 자신을 지정하고 있음. 폼데이터를 다른 PHP 파일로 처리하게 하려면, 파일명을 바꾸면 됨. input 필드의 값을 수집하려면 super 전역변수인 $_POST 를 사용하면 됨.


    <html>

    <body>


    <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">

    Name: <input type="text" name="fname">

    <input type="submit">
    </form>


    <?php
    $name = $_POST['fname'];

    echo $name;

    ?>

    </body>

    </html>

    PHP $_GET

    PHP $_GET으로도 method="get"을 사용하여 HTML 폼을 제출한 후 데이터를 수집하는데 사용할 수있음. 

    아울러 URL에서 전송된 데이터를 수집할 수 있음. 

    다음과 같은 페이지가 있다고 가정.

    <html>
    <body>

    <a href="test_get.php?subject=PHP&web=W3schools.com">Test $GET</a>

    </body>
    </html>


    사용자가 이 페이지에서 "TEST $GET" 링크를 누르면, "subject"와 "web" 파라미터가 "test_get.php"에 보내짐. 

    "test_get.php" 파일에서는 $_GET 을 사용하여 그 값에 접근할 수 있음. 

    아래는 "test_get.php"의 소스임


    <html>
    <body>

    <?php 
    echo "Study " . $_GET['subject'] . " at " . $_GET['web'];
    ?>

    </body>
    </html>



    Posted by 푸른하늘 푸른하늘이
    TAG php

    댓글을 달아 주세요

    기타/웹 2.02013. 10. 15. 14:33

    Javascript 공부중입니다. 제가 생각하고 있는 간단한 프로그램을 짜려니... 파일을 서버에 올리는 기능이 필요한데... 이리저리 찾아봐도 마땅한 코드가 별로 없어서 많이 고민했었습니다. 


    일단 원하는 기능은 간단히 HTML + CSS + Javascript 만으로 구현 가능한 것을 찾았는데, 결국 이것만으로는 불가능하고 서버측에는 PHP 등으로 클라이언트측 Request를 처리할 수 있는 게 필요하다는 걸 알았습니다. 


    아래는 고민하던 중 찾아낸 코드를 간단히 정리한 것입니다. 윗쪽은 가장 간단한 버전. 그리고 아래쪽엔 간단 버전을 확장하여 좀더 복잡한 여러가지 기능이 들어간 코드입니다. 도움이 되면 좋겠네요. 참, 제가 참고한 자료는 여기입니다. 


    HTML Form


    제일 먼저 클라이언트쪽 HTML에 Form 요소 넣는다. <input type='file'> 을 사용하면 [파일 선택] 버튼이 생기고 이를 이용해 원하는 파일을 선택할 수 있다. 단, 이때, enctype을 반드시 'multipart/form-data'로 주어야 한다.


    <form method='post' enctype='multipart/form-data' action='upload.php'>

        File: <input type='file' name='file_upload'>

        <input type='submit'>

    </form>


    PHP


    Form 을 php로 보내면, 각각의 필드가 $_POST 에 들어간다. 하지만, 파일은 배열 $_FILES 로 들어간다. 인덱스로 input 의 name 이 사용된다. 따라서 $_FILES[file_upload] 에서 올려진 파일의 정보를 확인할 수 있다. 다음은 e4f.png 를 올렸을 때의 대략적인 구조.


    Array

    (

        [file_upload] => Array

        (

            [name] => e4f.png

            [type] => image/png

            [tmp_name] => /Applications/MAMP/tmp/php/phpodzfRk

            [error] => 0

            [size] => 328119

        )

    )


    - error가 1 이상이면 오류가 발생한 것임. 반드시 체크


    <?php


    // Check for errors 에러가 1 이상이면 오류가 발생한 것.

    if($_FILES['file_upload']['error'] > 0){

        die('An error ocurred when uploading.');

    }


    // 이미지 파일 크기 체크. 실제 image가 아니면 0으로 나오게 됨.

    if(!getimagesize($_FILES['file_upload']['tmp_name'])){

        die('Please ensure you are uploading an image.');

    }


    // Check filetype. 파일 타입 체크

    if($_FILES['file_upload']['type'] != 'image/png'){

        die('Unsupported filetype uploaded.');

    }


    // Check filesize. 파일 크기 체크

    if($_FILES['file_upload']['size'] > 500000){

        die('File uploaded exceeds maximum upload size.');

    }


    // Check if the file exists. 파일이 이미 존재하는지 체크

    // unlink("upload/$fileName"); 를 사용하여 삭제 가능???

    if(file_exists('upload/' . $_FILES['file_upload']['name'])){

        die('File with that name already exists.');

    }


    // Upload file. move_uploaded_file() 을 사용하여 최종적으로 업로드. 

    if(!move_uploaded_file($_FILES['file_upload']['tmp_name'], 'upload/' . $_FILES['file_upload']['name'])){

        die('Error uploading file - check destination is writeable.');

    }


    die('File uploaded successfully.');

    ?>


    =======

    프로그레스 바를 포함한 HTML


    위의 방식을 이용하면 파일이 업로드된 후, 화면이 바뀌게 되고, "이전"을 눌러야 원래 상태로 돌아온다. 이것은 사용자 경험을 나쁘게 만든다. 


    <div class='container'> 부분을 살펴보면, 2개의 버튼 (File 버튼과 Submit 버튼)과, 업로드 상태를 보여줄 수 있는 div 가 있다. <style> 부분에는 이들에 대한 CSS 가 있다.


    <!doctype html>

    <html>

    <head>

       <meta charset="utf-8">

    <title>JS File Upload with Progress</title>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> </script>

    <script>

    $(document).ready(function(){

    // 버튼 2개와 progress div 부분을 가져옴.

    var _submit = document.getElementById('_submit'), 

    _file = document.getElementById('_file'), 

    _progress = document.getElementById('_progress');


    function upload(){

    // 파일이 선택되었는지 확인. 선택된 파일 없으면 종료

    // 현재 선택된 파일은 1개임. 여러개를 선택하려면, multiple 필요.

    if(_file.files.length === 0){

    return;

    }


    // 동적으로 Form 을 생성함. 이것을 보내게 됨.

    var data = new FormData();

    // 'SelectedFile'은 Form의 attribute name, 뒷부분은 value 임

    data.append('SelectedFile', _file.files[0]);


    // XMLHttpRequest 객체를 생성

    var request = new XMLHttpRequest();

    // XMLHttpRequest 객체의 상태가 변경되면 실행되는 함수

    request.onreadystatechange = function(){

    if(request.readyState == 4){ //완료되었을 때.

    try {

    // 서버측에서 보낸 JSON을 해석하여 처리함.

    var resp = JSON.parse(request.response);

    } catch (e){ //에러가 발생되었다면

    var resp = {

    status: 'error',

    data: 'Unknown error occurred: [' + request.responseText + ']'

    };

    }

    // 여기는 정상적으로 업로드가 되었을 때임. resp.data에는 실제 올려진 파일명이 들어 있음. 파일을 올린 뒤 처리하는 방법을 여기에 기술하면 됨.

    console.log(resp.status + ': ' + resp.data);

    }

    };


    // 업로드 상태를 체크하기 위한 event 등록.

    request.upload.addEventListener('progress', function(e){

    _progress.style.width = Math.ceil(e.loaded/e.total) * 100 + '%';

    }, false);


    // 이제 XMLHttpRequest 객체를 서버로 보냄.

    request.open('POST', 'upload_png.php');

    request.send(data);

    }

    // submit 버튼을 'click' 했을 때, upload()가 실행되도록 event 를 등록함.

    _submit.addEventListener('click', upload);


    });

    </script>


    <style>

    .container {

    width: 500px;

    margin: 0 auto;

    }

    .progress_outer {

    border: 1px solid #000;

    }

    .progress {

    width: 20%;

    background: #DEDEDE;

    height: 20px;  

    }

    </style>


    </head>


    <body>

    <div class='container'>

    <p>

    Select File: <input type='file' id='_file'> <input type='button' id='_submit' value='Upload!'>

    </p>

    <div class='progress_outer'>

    <div id='_progress' class='progress'></div>

    </div>

    </div>

    </body>

    </html>



    PHP

    이제 서버측에서 처리해야 할 것.


    <?php

    // 처리 결과를 JSON으로 인코딩하여 보냄.

    function outputJSON($msg, $status = 'error'){

        header('Content-Type: application/json');

        die(json_encode(array(

            'data' => $msg,

            'status' => $status

        )));

    }


    // 에러체크. 

    if($_FILES['SelectedFile']['error'] > 0){

        outputJSON('An error ocurred when uploading.');

    }


    // 정말 이미지를 선택했는지 확인하는 절차. 실제 image가 아니면 0으로 나오게 됨.

    if(!getimagesize($_FILES['SelectedFile']['tmp_name'])){

        outputJSON('Please ensure you are uploading an image.');

    }


    // Check filetype

    if($_FILES['SelectedFile']['type'] != 'image/png'){

        outputJSON('Unsupported filetype uploaded.');

    }


    // Check filesize

    if($_FILES['SelectedFile']['size'] > 5000000){

        outputJSON('File uploaded exceeds maximum upload size.');

    }


    // Check if the file exists

    if(file_exists('upload/' . $_FILES['SelectedFile']['name'])){

        outputJSON('File with that name already exists.');

    }


    // Upload file

    if(!move_uploaded_file($_FILES['SelectedFile']['tmp_name'], 'upload/' . $_FILES['SelectedFile']['name'])){

        outputJSON('Error uploading file - check destination is writeable.');

    }


    // Success!

    outputJSON('File uploaded successfully to "' . 'upload/' . $_FILES['SelectedFile']['name'] . '".', 'success');

    ?>


    ======

    흠... 이걸 어떻게 정리한다... 이제부터 고민해야겠네요~~


    민, 푸른하늘

    Posted by 푸른하늘 푸른하늘이

    댓글을 달아 주세요