linux + apache + php 에서 MsSql 에 접속하기 위해서는 freeTDS 를 사용하면 쉽게 연결 할 수 있다.

freeTDS 가 뭔지는 공식 사이트인 http://www.freetds.org/ 를 잘 읽어 보고

바로 설치 하겠다 하는 분은 여기서 파일을 다운로드 하면 된다.
ftp://ftp.freetds.org/pub/freetds/stable/freetds-patched.tar.gz

위 링크 주소가 의심스러우면 공식 사이트로 들어가서 링크를 타고 이동해도 된다.

freeTDS 설치
다운로드 했으면 설치를 해보자
configure --prefix=/usr/local/freetds --enable-msdblib --with-gnu-ld --enable-shared 
make 
make install 


모든 프로그램이 그렇듯 설치를 했으면 MsSql 서버에 대한 정보를 설정을 해야 한다.
설정 파일의 경로는 /usr/local/freetds/etc/freetds.conf 에 있다.

vi 에디터로 파일을 열어보자
vi /usr/local/freetds/etc/freetds.conf 


MsSql DB 정보가 다음과 같다고 했을 때
디비 접속 변수 이름 : mydatabase
디비 IP : 192.168.0.2
디비 포트 : 1433
캐릭터셋 : UTF-8

디비 계정: userid
디비 비번: userpwd
[mydatabase] 
host = 192.168.0.2 
port = 1433 tds 
version = 8.0 
client Charset = UTF-8 


설정이 끝났으면 php 에서 정상적으로 접근이 되는지 확인해보자
mssql_dbcon.php
[mydatabase]
        host = 192.168.0.2
        port = 1433
        tds version = 8.0
        client Charset = UTF-8


여기서 알수 있듯 hostname 부분만freeTDS 설정으로 변경되고 디비 계정과 비밀번호는 mssql_connect() 함수에 직접 넣어 줘야 한다.

웹서버 응답제한시간 초과에 대처하는 php 의 방안

모든 웹 언어는 아무리 늦어도 수초 안에 동적인 페이지지 생성을 끝내고 웹서버 혹은 WAS 에서 바로 웹 브라우저로 내보내기(flush)를 처리하지만

동보메일 처럼 여러 사람에게 수천통의 메일발송을 웹페이지로 구현해야 하는 경우
처리 시간이 길어저 웹서버에 설정된 응답 제한시간 초과하는 일이 발생한다.

이럴때는 웹서버 응답시간 이내에 브라우저로 뭔가를 지속적으로 보내주는 처리를 해야 한다.

이럴때 사용하는 명령이 flush() 입니다.

사용법은 아주 간단하다.

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "
====1===
"; flush(); sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송) echo "
====2===
"; flush(); sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송) echo "
====3===
"; flush();


뭥미?
이게 전부임?

뭘 바랬는지 모르지만 이게 전부다.
다른 언어도 이와 비슷한 함수들이 있으니 언어별로 조금만 바꾸면 모두 적용 할 수 있다.


여기서 끝내면 뭔가 찝찝하다. 마치 화장실 갔다가 휴지가 없어서 알아서(?) 뒷처리를 하고 나온 것 처럼...

실제로 딱 위 내용 까지만 적용했다가 고객 클레임 전화를 받고 이라이더에게 전화나 카톡, 이메일 (최신 연락처는 언제든 블로그 하단이나 공지사항에 공개 되어 있다)로 항의 할지도 모르다.

실제로 해보면 내가 테스트 할때는 퍼펙트하게 잘 되지만 서비스에 적용해 놓으면 여기 저기서 전화오고 난리가 날것이다.
여기에 하나 빠진것이 있는데 사용자의 브라우저 종류와 버전 이다.

여기서 기초적인 웹페이지를 가져오는 방식을 알아야 한다.
사용자는 브라우저가 웹서버에 웹페이지를 요청하고
웹서버는 요청한 페이지를 동적으로 생성해서 버퍼에 넣고 끝나면 자동으로 버퍼의 내용을 브라우저에 전송하고 웹페이지가 끝났다고 신호를 같이 보낸다

하지만 flush() 는 웹서버의 현재 버퍼에 있는 데이터(웹페이지)를 먼저 사용자의 브라우저에 보내지만 끝났다는 신호는 안 보낸다는것이 문제다.
(왜? 아직 페이지를 동적으로 생성중이니까!)

그래서 어떤 브라우저는 화면에 아무 출력도 없이 끝났다는 신호가 들어올때까지 마냥 기다리거나 아니면 응답없음으로 접속을 끊어 버린다.

그럼 flush() 는 처음 부터 쓸수 없는 것이였나?
결론만 얘기하면 아니다.

flush() 는 웹서버 입장에서 정상적으로 동작한것인데 문제는 웹브라우저에 있다.
크롬, 오페라 같은 브라우저는 flush() 로 내보낸 데이터를 바로 받아서 화면에 뿌려주지만(화면 출력을 이렇게도 표현한다)
FF(Fire Fox : 파이어폭스) 는 1024byte 가 다 찰때까지 기다리고
IE 10(Internet Explorer 10)은 4096byte 가 다 찰때까지 기다리는것이 문제다.

브라우저 별로 정리하면 다음과 같다. (IE11 이나 엣지, 사파리 같은 나머지 최신 브라우저는 알아서 조사해서 댓글로 좀 알려 주세요)
 * IE 10 : 4096 바이트
 * FF 21.0 : 1024 바이트 / 하위버젼 호환성을 위해 최초 제일 뒤에 "\n" 넣을것
 * 크롬 29.0 : 상관없음
 * Opera 16.0 : 상관없음


이렇다 보니 개발자가 크롬에서 개발할 때는 아주 잘 되다가
서비스에 올리면 사용자의 브라우저에 따라서 화면에 아무것도 출력이 안될 수 있다.

그럼 해결 방법은 아주 간단하다.
웹서버 버퍼에 강제로 4096 byte 이상을 넣은 후에 flush() 를 하면 된다.
sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "
====1===
"; echo str_repeat(' ', 4096). "\n"; flush(); sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송) echo "
====2===
"; echo str_repeat(' ', 4096). "\n"; sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송) echo "
====3===
"; echo str_repeat(' ', 4096). "\n"; flush();

참 쉽죠?
오류, 오타, 건의 사항은 이메일, 카톡으로 연락 부탁드립니다. (글 하단이나 공지사항에 연락처 있음)

 



2016년 11월 15일 추가 :

str_repeat(' ', 4096)  중간에 ' ' 사이에 공백이 있습니다.

모든 웹 언어에서 그렇듯 php 에서도 브라우저의 버젼을 확인하기 위해서는 브라우저에서 보내온 사용자 에이전트(User Agent) 문자열을 분석해서 판별하게 됩니다.

다른 언어 request 에 해당하는것이 php 에서는 대부분 $_SERVER[] 에 있습니다.
자세한것은 php 메뉴얼 http://php.net/manual/en/reserved.variables.server.php 를 참고하세요

주로 많이 쓴는것만 적어보면
$_SERVER["REMOTE_ADDR"] // 사용자 IP
$_SERVER["HTTP_REFERER"] // 이전 페이지
$_SERVER["HTTP_USER_AGENT"] // 브라우저 정보


그럼 본격적으로 브라우저 버전을 확인하는 소스입니다.
$userAgent = $_SERVER["HTTP_USER_AGENT"]; 

if ( preg_match("/MSIE*/", $userAgent) ) { 
	// 익스플로러

	if ( preg_match("/MSIE 6.0[0-9]*/", $userAgent) ) {
		$browser = "Explorer 6"; 
	}elseif ( preg_match("/MSIE 7.0*/", $userAgent) ) {
		$browser = "Explorer 7";
	}elseif ( preg_match("/MSIE 8.0*/", $userAgent) ) {
		$browser = "Explorer 8"; 
	}elseif ( preg_match("/MSIE 9.0*/", $userAgent) ) {
		$browser = "Explorer 9"; 
	}elseif ( preg_match("/MSIE 10.0*/", $userAgent) ) {
		$browser = "Explorer 10"; 
	}else{
		// 익스플로러 기타
		$browser = "Explorer ETC"; 
	}

} elseif ( preg_match("/Trident*/", $userAgent &&  preg_match("/rv:11.0*/", $userAgent &&  preg_match("/Gecko*/", $userAgent) ) ) ) {
	$browser = "Explorer 11"; 

} elseif ( preg_match("/(Mozilla)*/", $userAgent) ) { 
	// 모질라 (파이어폭스)
	$browser = "mozilla";

} elseif ( preg_match("/(Nav|Gold|X11|Mozilla|Nav|Netscape)*/", $userAgent) ) { 
	// 네스케이프, 모질라(파이어폭스)
	$browser = "Netscape/mozilla";

} elseif ( preg_match("/Opera*/", $userAgent) ) { 
	// 오페라 
	$browser = "Opera";

} else {
	$browser = "Other"; 
}

echo $browser;


IE11 에서는 User Agent 에 "MSIE" 문구가 삭제 되었습니다.
이제 더이상 "MSIE" 만으로는 IE 유무를 판단할 수 없습니다.
("MS의 Internet Explorer 11 소개 및 업그레이드" 문서에도 User Agent String 변경이 자세히 실려 있습니다)
// IE11 의 User-Agent 입니다. (Windows 10 버전이라서 Windows NT 10.0 가 들어갑니다
// "MSIE"를 대체하는 "Trident"  가 들어가 있고 버전인 "rv:11.0" 그리고 "Gecko" 가 추가 되었습니다.

User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; SMTE; rv:11.0) like Gecko
  1. zaxguy 2017.05.12 17:16

    21번째줄 괄호한개 부족.

    }else if(preg_match("/Trident*/", $userAgent && preg_match("/rv:11.0*/", $userAgent && preg_match("/Gecko*/", $userAgent)))) {.

php 스위치 switch 문 사용법입니다.

어느 언어에서나 switch 문은 거의 동일한 문법이죠

switch (비교에 사용할 변수) 를 적고 case (조건): 을 만족하는것을 실행 합니다.
주의해야할 것은 php 는 case 조건에 맞는 부분과 함께 default: 부분도 실행됩니다.
디폴트를 실행 하기 싫다면 해당 case 조건 마지막에 꼭 break 를 넣어 주세요

다음 소스는 앞에 case 조건을 만족하면 default 부분이 실행 되지 않습니다.
switch ($my_status) {
case ($my_status == "W"):
	$print_status = "대기";
	break;
case ($my_status == "P" || ($my_status == "E")):
	$print_status = "진행중";
	break;
case "E":
	$print_status = "완료";
	break;
case "R":
	$print_status = "보류";
	break;
default:
	$print_status = "없음";
}


다음 소스는 앞에 case 조건을 만족하더라도 default 가 무조건 실행 됩니다.
switch ($my_status) {
case ($my_status == "W"):
	$print_status = "대기";
case ($my_status == "P" || ($my_status == "E")):
	$print_status = "진행중";
case "E":
	$print_status = "완료";
case "R":
	$print_status = "보류";
default:
	$print_status = "없음";
}

php 에서 mysql 접속하는 방법입니다.


이렇게 기초적인 간단한걸 왜 포스팅 하냐고요?

요즘은 php 도 대부분 프레임워크를 사용하기 때문에 이렇게 직접 디비에 접속하고 쿼리문 작성하고 결과를 처리할 일이 없기 때문에 너무 안 써서 까먹으니까 기록으로 남겨 놓으려고 합니다.



php 에서 mysql 접속하는 방법입니다.

배열이 아닌 일반 변수로 처리해도 상관 없습니다.


$mysql["host"] = "localhost"; // 서버아이피 또는 도메인
$mysql["port"] = "3306";
$mysql["conn"] = "";
$mysql["user"] = "user_name"; // 디비계정
$mysql["pass"] = "password"; //	비밀번호
$mysql["database"] = "database_name"; // 디비이름

$mysql["conn"] = @mysql_connect($mysql["host"], $mysql["user"], $mysql["pass"]) or die('DATABASE CONNECT ERROR!');
mysql_select_db($mysql["database"], $mysql["conn"]) or die('DATABASE CONNECT ERROR!');



쿼리문을 작성하고 실행 합니다.

$query = "SELECT *  FROM 테이블 WHERE uid='아이디' ";

$result = mysql_query($query, $mysql["conn"]);



결과 row 개수의 가져옵니다.

$total_count = mysql_num_rows($result);



결과를 배열로 받아서 while 문으로 반복하면서 row 별로 처리해볼까요

while( $row = mysql_fetch_array($result) ){
	$uid = $row["uid"];
	$user_name = $row["user_name"];
	$user_tel = $row["user_tel"];
}



배열의 인텍스로 값을 가져올 수 있습니다.  이렇게요.

while($row = mysql_fetch_array($result)){
	$uid = $row[0];
	$user_name = $row[1];
	$user_tel = $row["user_tel"];
}




결과를 받아서 for 문으로 반복해볼까요

$query = "SELECT *  FROM 테이블 WHER uid='아이디' ";

$result = mysql_query($query, $mysql["conn"]);
$total_count = mysql_num_rows($result);

for($i = 0; $i <= $total_count; $i++) {
	$uid = mysql_result($result, $i, 0);
	$user_name = mysql_result($result, $i, 1);
	$user_tel = mysql_result($result, $i, 2);
}



list 를 이용하여 변수로 바로 받을 수도 있습니다.

while( list($uid, $user_name, $user_tel) = mysql_fetch_row($result) )  {

}



테이블에 insert 후 자동증가 값인 pk 값을 가져옵니다.

$query = "INSERT INTO (seq, name, tel) VALUES ('', '홍길동', '010-1234-5678') ";

$result = mysql_query($query, $mysql["conn"]);

$total_count = mysql_affected_rows();


+ Recent posts