영원한사랑

인터넷정보 +1252
// 쿠키의 값을 가져오는 함수입니다.
// GetCookie(쿠키이름);
function GetCookie (name) {  
        var arg = name + "=";  
        var alen = arg.length;  
        var clen = document.cookie.length;  
        var i = 0;  
        while (i < clen) {    
        var j = i + alen;    
        if (document.cookie.substring(i, j) == arg)      
                return getCookieVal! (j);    
                i = document.cookie.indexOf(" ", i) + 1;    
                if (i == 0) break;   
        }  
        return null;
}

// 쿠키를 굽는 함수입니다.
// php 의 setcookie() 함수와 동일하게 사용하면 됩니다.
// SetCookie (쿠키이름,값,보관시간,디렉토리,도메인,....);
function SetCookie (name, value) {  
        var argv = SetCookie.arguments;  
        var argc = SetCookie.arguments.length;  
        var expires = (argc > 2) ? argv[2] : null;  
        var path = (argc > 3) ? argv[3] : null;  
        var domain = (argc > 4) ? argv[4] : null;  
        var secure = (argc > 5) ? argv[5] : false;  
        document.cookie = name + "=" + escape (value) + 
        ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + 
        ((path == null) ? "" : ("; path=" + path)) +  
        ((domain == null) ? "" : ("; domain=" + domain)) +    
        ((secure == true) ? "; secure" : "");
}


// 쿠키를 지우는 함수 입니다.
// DeleteCookie (쿠키이름);
function DeleteCookie (name) {  
        var exp = new Date();  
        exp.setTime (exp.getTime() - 1);  
        // This cookie is history  
        var cval = GetCookie (name);  
        document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
}

//GetCookie() 에서 사용하는 함수 따로 쓸일은 없습니다.:)
function getCookieVal! (offset) {  
        var endstr = document.cookie.indexOf (";", offset);  
        if (endstr == -1)    
                endstr = document.cookie.length;  
                return unescape(document.cookie.substring(offset, endstr));
}


<script>
top.moveTo(0,0);
y=-30;
function drop1() {top.resizeTo(screen.availWidth,y); y=y+30; if(y>=screen.availWidth)clearInterval(timerID);}
function drop2(){timerID=setInterval('drop1()',100) }
drop2();
</script>







  1. <script>
  2. <!--
  3. document.write(screen.width+"*"+screen.height)
  4. //-->
  5. </script>













보통 자바스크립트 함수를 링크 시킬때 보통 "#"을 링크시킵니다.


근데 이걸 쓸때 맨처음 즉, 문서 최 상위로 스크롤됨니다.


이걸 방지하려면  href="#" 을 href="#None" 이렇게 하시거나,


아니면 "a href=함수명" 이나,


"onCilck="location.href='http://'" style="cursor:hand"


이렇게 하시면됨니다.


<?php $sum=0;
for($i=1; $i<=9; $i++){
        echo "========== 구구단 $i 단 =========<br>\n";
for($j=1; $j<=9; $j++){
$sum=$i * $j;
echo "$i * $j = $sum ";
echo "<br>";
}
echo "<p>\n";
}
?>

<form method="post" action="cycle.php">
<input type="text" name="number">
<input type="submit" value="send">
<input type="reset" value="clear">
</form>


cycle.php

<?php
$sum=$_POST["number"] * $_POST["number"] * M_PI;
printf("%d", $sum);
?>



<?php

$number = "7";

$number%=2;

if ($number > 0) echo "홀수입니다.";

else echo "짝수입니다.";

?>





<?php
function multi()
{
$sum=func_get_arg(0); //NULL 값을 입력해도 된다.
for($i = 0; $i < func_num_args(); $i++)
if ($sum<func_get_arg($i))
$sum=func_get_arg($i);
echo $sum;
}
multi(-5, -3, 8,12, -2, 3);
?>








<?php
$file="org.jpg";
if(file_exists($file)){
echo "$file exists<br>";
$size=(int)(filesize($file)/1024);
$lastAccessed = date ("F d Y H:i:s.", fileatime($file));
$lastChanged = date ("F d Y H:i:s.", filectime($file));
$lastModified = date ("F d Y H:i:s.", filemtime($file));
echo "last accessed: $lastAccessed<br>";
echo "last changed: $lastChanged<br>";
echo "last modified: $lastModified<br>";
echo "filesize: " . $size . " Kbytes";
}
else
echo "$file does not exist";
?>

org.jpg exists
last accessed: November 18 2004 00:38:29.
last changed: November 18 2004 00:38:29.
last modified: November 14 2004 17:15:34.
filesize: 35 Kbytes

fopen() // 파일을 열고 파일 핸들을 돌려주는 함수
예) $fp = fopen("./data.txt","r");
--> r : 파일을 읽기 전용으로 연다. 파일 위치 지정자는 파일의 맨 처음을 가리킨다.
--> r+ : 파일을 읽기 및 쓰기 모드로 연다. 파일 위치 지정자는 역시 파일의 맨 처음을 가리킨다.
--> w: 파일을 쓰기 전용으로 연다. 기존 데이터는 모두 삭제되며 파일이 존재하지 않으면 새로 만든다.
--> w+: 파일을 읽기 및 쓰기 모드로 연다. 기존 데이터는 모두 삭제되며 파일이 존재하지 않으면 새로 만든다.
--> a: 파일을 추가 전용 모드로 연다. 새로운 데이터는 기존 데이터 다음에 추가되며 파일이 존재하지 않으면 새로 만든다.
--> a+: 파일을 읽기 및 추가 모드로 연다. 새로운 데이터는 기존 데이터 다음에 추가되며 파일이 존재하지 않으면 새로 만든다.

fread() // 파일에서 문자열을 읽어오는데 사용하는 함수
예) $data = fread($fp,10);

fwrite() // 파일에 문자열을 써주는 함수
예) fwrite($fp, "ABCCxyz");

fgetc() // 파일에서 문자를 한 개씩 읽어들이는 함수
이함수가 fread와 다른점은 fread의 경우 인수를 붙여서 스트링값을 지정해주는 반면 fgetc는 한문자씩 출력하기때문에 while문을 써서 전체 스트링을 출력하게 한다.

feof() // fgetc()의 경우엔 10이되면 마지막 0이 거짓값이 되어 루프를 벗어나게되어 9까지밖에 셀수 없다.. 그렇지만 이 함수는 파일의 끝에 도달하면 참값을 돌려주게 된다.
예) while((!feof($fp)) $counter .= fgetc($fp); //.=의 의미는 왼쪽 것과 오른쪽 것을 결합한 결과를 왼쪽에 배정 ( 이것은 카운트 프로그램이니깐.. )
$counter = (int) $counter;

fgets() // 파일에서 문자열을 읽어 주는 함수

fputs() // fwrite()의 다른 이름이므로 똑같이 사용가능함..

연산자 수행하는 연산
= 오른쪽 것을 왼쪽 것에 배정
+= 오른쪽 것을 왼쪽 것에 더한 값을 왼쪽에 배정
-= 오른쪽 것을 왼쪽 것에서 뺀 값을 왼쪽에 배정
*= 오른쪽 것을 왼쪽 것에 곱한 값을 왼쪽에 배정
/= 왼쪽 것을 오른쪽 것으로 나눈 값을 왼쪽에 배정
%= 왼쪽 것을 오른쪽 것으로 나눈 나머지를 왼쪽에 배정
&= 왼쪽 것과 오른쪽 것을 비트 단위 AND로 연산한 결과를 왼쪽에 배정
|= 왼쪽 것과 오른쪽 것을 비트 단위 OR로 연산한 결과를 왼쪽에 배정
^= 왼쪽 것과 오른쪽 것을 비트 단위 XOR로 연산한 결과를 왼쪽에 배정
.= 왼쪽 것과 오른쪽 것을 결합한 결과를 왼쪽에 배정

or 또는 || : 모든 조건중 하나가 만족하면 true
and 또는 && : 모든조건이 만족해야 true
$a==$b : $a랑 $b가 같아야 true
$a!=$b : $a랑 $b가 틀려야 true
$a===$b : $a와 $b가 같고 같은 형이어야 합니다.
char형이면 둘다 char형 dobule이면 둘다 dobele

논리연산 우선순위는  괄호 -> && -> || -> 기타

<?php
// sample.txt란 파일이 있을경우엔 exists를 없을때는 does not exist 를 출력한다.
$filename = "sample.txt";
if (file_exists($filename))
        echo "$filename exists";
else
        echo "$filename does not exist";
?>

싱글로그인을 구현하기 위해 세션키를 주고 받는데,
$_COOKIE['PHPSESSID'] 값으로 주고 받았었습니다.
이것의 가장 큰 단점은,
새로 session_start() 해서 쿠키가 구워지면,
쿠키구운 프로세스내에서는 $_COOKIE 변수가 세팅되지 않는다는 것입니다.

session_start() 하고 echo SID 해 보면,
PHPSESSID=a00aije9rijoajodjflsadfj
가 나옵니다.

이건 상수기 때문에, 세팅되지 않을 일이 없습니다.
게다가 php.ini 에서 세션키 명을 PHPSESSID 가 아닌걸로 바꿔놔도
저 상수에는 알아서 지정되기 때문에, ini_get() 같은것을 사용하지 않아도 됩니다.


__FILE__, __LINE__ 등도 유용합니다.

<xmp>
<?php

print_r(get_defined_constants());

?>
</xmp>

이걸로 현재 정의된 상수를 알 수 있습니다.
php 바이너리 위치, int 최대값 등 좋은게 많이 보입니다.
__로 시작하는 특수 상수는 안나오네요.
그건 메뉴얼의 magic constants 에 있습니다.
디버깅시에 유용합니다.

 

http://www.jngent.co.kr/test.php


########
개발자 : 조일현
이메일 : ssdosso@naver.com
#########

저번에 올렸었지만,,,
미약 한것 같아서 지우고..
새로운 버젼을 올립니다.
앞으로 응용할 수 있는게 많을 것 같습니다.

Firefox 와  IE 에서 다 가능합니다.

ajax,CSS ,prototype 으로 구현 되었습니다.


ps. 본 소스를 보시면, 왜 prototype1.4 가 유용한지,굳이 왜 사용해야 하는지...에대하여
 잘 알 수 있습니다.
우선, 소스의 간결화가.. 그 첫번째 이유이고, 두번째 큰 이유는  의도 하지는 않았지만.
FF 와 IE 의 호환성 입니다.

ps2 . ajax Update 함수를 이용해서 업로드 로딩바를 구현 하였습니다 가능합니다.


<?
$pwd = './';
?>
<script language="javascript" type="text/javascript" src="<?=$pwd?>js/prototype.js"></script>
<script language="javascript">



    var MY = new Channel();
function Channel() {
    
    this.num = null;
    this.div = null;
    this.divTxt = null;
    this.div2 = null;
    this.div2Txt = null;
    this.percent_num = null;
    this.percent_num1 = null;
    this.total = 0;
    this.apName = navigator.appName;     
}
    
function Progress() {



        
        MY.total = 100;
        MY.num = '58';
        MY.num1 = '30';
        
                MY.div = $("progress_0");
                MY.divTxt = $("progreessTxt_0");
                
                MY.div2 = $("progress_1");
                MY.div2Txt = $("progreessTxt_1");
                
                MY.percent_num = 0;
                MY.percent_num1 = 0;
            
            
                Element.setStyle(MY.div, {width:MY.percent_num+'px'});
                Element.setStyle(MY.div2, {width:MY.percent_num+'px'});
            
                updateProgress();    
            
                
            }


    
    function updateProgress()
    
    {
    
        if(MY.total >= 100)
        
            {
        
                if(MY.num > 0)
                    {
                    
                    
                        if( MY.percent_num < MY.num) {
                        
                        MY.percent_num = MY.percent_num + 1;
                        if(MY.num > 20 ) {        
                            
                            if(MY.percent_num < 20) {    
                            Element.hide(MY.divTxt);    }
                            else {
                            Element.show(MY.divTxt);
                            Element.setStyle(MY.divTxt, {left:'-5px',width:MY.percent_num+'%'});
                            
                            }
                            
                        } else {
                            
                            Element.setStyle(MY.divTxt, {left:'+23px',width:MY.percent_num+'%'});
                        }
                            
                        MY.divTxt.innerHTML = MY.percent_num +"%";
                        
                        
                        if(MY.apName == 'Netscape') Element.setStyle(MY.div, {width:MY.percent_num+'%',background:'url("../images/mychannel/bg_blue_per.gif")'});
                        else Element.setStyle(MY.div, {width:MY.percent_num+'%'});
                        
                        
                        
                        }
                        
                    
                    }
        
        
                if(MY.num1 > 0)
                    {
                    
                    
                        if( MY.percent_num1 < MY.num1) {
                        
                        MY.percent_num1 = MY.percent_num1 + 1;
                    
                    
                    
                        if(MY.num1 > 20 ) {        
                            
                            if(MY.percent_num1 < 20) {    
                            Element.hide(MY.div2Txt);    }
                            else {
                            Element.show(MY.div2Txt);
                            Element.setStyle(MY.div2Txt, {left:'-5px',width:MY.percent_num1+'%'});
                            
                            }
                            
                        } else {
                            
                            Element.setStyle(MY.div2Txt, {left:'+23px',width:MY.percent_num1+'%'});
                        }
                    
                    
                    
                    
                    
                        MY.div2Txt.innerHTML = MY.percent_num1 +"%";
                    
                        
                        
                        if(MY.apName == 'Netscape') Element.setStyle(MY.div2, {width:MY.percent_num1+'%',background:'url("../images/mychannel/bg_yellow_per.gif")'});
                        else Element.setStyle(MY.div2, {width:MY.percent_num1+'%'});
                        
                        }
                    
                        
                    
                    }
                        
                 setTimeout("updateProgress()",40);
                
            }
                        
    }                
    
        


    
    
    

    
    Event.observe(window, 'load', function(event){Progress();}, false);
    
    
    
    
</script>


<link rel="stylesheet" href="test.css" type="text/css" media="SCREEN"  title="Upload"  />

<table width="298" border="0" cellspacing="0" cellpadding="0">
                    <tr>
                      <td height="23" background="<?=$pwd?>images/mychannel/bg_name.gif"style="PADDING-left: 7px;"><table width="100%" border="0" cellspacing="0" cellpadding="0">
                          <tr>
                            <td width="20"> </td>
                            <td><strong><font color="#FFFFFF">로딩바</font></strong></td>
                          </tr>
                        </table></td>
                    </tr>
                    <tr>
                      <td height="32"><table width="100%" border="0" cellspacing="0" cellpadding="0">
                          <tr>
                            <td width="95"> </td>
                            <td ><table width="100%" border="0" cellspacing="0" cellpadding="0">
                                <tr>
                                  <td height="5"> </td>
                                </tr>
                                <tr>
                                  <td align="right"> </td>
                                </tr>
                              </table>
                              <strong></strong></td>
                            <td width="20"> </td>
                          </tr>
                        </table></td>
                    </tr>
                    <tr>
                      <td height="49"><table width="265" border="0" align="center" cellpadding="0" cellspacing="0">
                          <tr>
                            <td width="6" height="20"> </td>
                            <td width="146"><table width="146" border="0" cellspacing="0" cellpadding="0">
                                <tr>
                                  <td height="11" background="<?=$pwd?>images/mychannel/bg_per.gif">
                                  <div id="pointlevel_0" ><div id="progreessTxt_0" ></div><div  id="progress_0">
                                  <table width="100%" border="0" cellspacing="0" cellpadding="0"  >
                                      <tr><!-- style="background-attachment:fixed; background-image:url(../images/mychannel/bg_blue_per.gif)" -->
                                        <td width="7"><img src="<?=$pwd?>images/mychannel/bg_blue_per_left.gif" width="7" height="11"></td>
                                        <td height="11" align="left" class="back1"><img src="../../images/mychannel/bg_blue_per.gif" width="1" height="11" /></td>
                                        <td width="6"><img src="<?=$pwd?>images/mychannel/bg_blue_per_right.gif" width="7" height="11"></td>
                                      </tr>
                                    </table></div></div>                                  </td>
                                </tr>
                              </table></td>
                            <td width="113"> </td>
                          </tr>
                          <tr>
                            <td height="20"> </td>
                            <td><table width="146" border="0" cellspacing="0" cellpadding="0">
                                <tr>
                                  <td height="11" background="<?=$pwd?>images/mychannel/bg_per.gif">
                                  <div id="pointlevel_1" ><div id="progreessTxt_1"></div><div  id="progress_1">
                                  <table width="100%" border="0" cellspacing="0" cellpadding="0">
                                      <tr>
                                        <td width="7" ><img src="<?=$pwd?>images/mychannel/bg_yellow_per_left.gif" width="7" height="11"></td>
                                        <td height="11" align="left" class="back2" ><img src="../../images/mychannel/bg_yellow_per.gif" width="1" height="11" /></td>
                                        <td width="6"><img src="<?=$pwd?>images/mychannel/bg_yellow_per_right.gif" width="7" height="11"></td>
                                      </tr>
                                    </table></div></div></td>
                                </tr>
                              </table></td>
                            <td> </td>
                          </tr>
                        </table></td>
                    </tr>
                    <tr>
                      <td height="24"> </td>
                    </tr>
                    <tr>
                      <td style="PADDING-left: 11px;"> </td>
                    </tr>
</table>

AJAX를 이용한 드래그(Drag)가 가능한 간단한 메모보드입니다.
윈도우의 바탕화면에 사용할 목적으로 만들어봤습니다.

기본기능인 메모지의 생성,수정,삭제와 메모지의 위치 기억기능만 구현하였습니다.
js 와 php 상호간의 데이터 교환은 JSON을 사용하였으며
JSON라이브러리는 소스에 포함하였습니다.

코드를 다듬질 않아서 많이 지저분하니
사용하시는 분께서 다듬어서 쓰셔야합니다~^^

소스는 링크 따라가시면 받으실 수 있습니다.


http://asrada2001.mireene.com/asrada/memoboard/memo.html


http://oxtag.com/php/p/rssReader.php

<?
// PHP RSS Reader v0.1
// Code By Jusun at 2007-01-25
// 라이센스 : FREE ... 소스로 인한 뒷일은 책임 못짐...

// RSS 읽어오기
function getRSS($url){
    $fd = fopen ($url, "r");
    while (!feof ($fd)) {
        $buffer .= fgets($fd, 4096);
    }
    fclose ($fd);
    return $buffer;
}

// 내용만 뽑아내기
function parseTag($tag,$value){
    $value =  explode("</".$tag.">",$value);
    $value = explode("<".$tag.">",$value[0]);
    return $value[1];
}

//한글 자르기
function hstrCut($msg,$cut_size,$end_str = "...") {
    if( (strlen($msg) > $cut_size) & ($cut_size > 0) ) {
            $msg = substr($msg,0,$cut_size);
            $msg = preg_replace("/(([\\x80-\\xFE].)*)[\\x80-\\xFE]?$/","\\1",$msg);
            $msg .= $end_str;
    }
    return $msg;
}

// 보여지는 부분
function RSS_reader($count,$url,$encode = "EUC-KR"){
    $channel = parseTag("channel",getRSS($url));
    // 인코딩 변환
    if($encode == "UTF-8"){
        $channel = iconv("UTF-8","EUC-KR",$channel);
    }
    $channel = str_replace("</item>","",$channel);
    $item = explode("<item>",$channel);
    // 제목 처리
    $siteTitle = parseTag("title",$item[0]);
    $siteLink = parseTag("link",$item[0]);
    $siteDescription = parseTag("description",$item[0]);
    
    //제목 출력
    $html = "[<a href=\"$siteLink\" target=\"_blank\">$siteTitle</a>]<br />";

    //각 게시물 제목 처리
    for($i=1;$i<=$count;$i++){
        if(!isset($item["$i"])) break;
        //제목 가져오기
        $title = hstrCut(parseTag("title",$item[$i]),30);
        //링크 가져오기
        $link = parseTag("link",$item[$i]);
        //내용 가져오기
        $description = parseTag("description",$item[0]);

        $html .= "<a href=\"$link\" target=\"_blank\">$title</a> <br />";    
    }

    // 출력
    echo $html;

}
?>

함수의 사용법은 다음과 같습니다.

RSS_reader("7","http://blog.jusun.org/tt/rss","UTF-8");

RSS_reader("가져올갯수","RSS주소","인코딩");

인코딩은 UTF-8 또는 생략 가능입니다. 생략하면 EUC-KR로..

RSS가 잘 안읽어지면 UTF-8 , EUC-KR 왔다갔따 바꿔보세요.. ^^


RSS 주소 모음  페이지.. 아래 링크..

http://haco.tistory.com/1924

http://oxtag.com/php/p/rssReader.php?cut=30&rss=http://rss.cbs.co.kr/nocutnews.xml

http://oxtag.com/php/p/rssReader2.php?cut=25&rss=http://rss.donga.com/stotal.xml

http://oxtag.com/html/ex/slb.html

<html>
<head>
<title>심플 라이트박스 효과</title>
<meta http-equiv="content-type" content="text/html; charset=euc-kr">
<style type="text/css">
 html { width:100%; height:100%; }
 body { width:100%; height:100%; margin: 0px; padding: 0px; font-size:9pt; }
 .SLB_center { cursor:pointer; visibility:hidden; border: solid 4px #000000; background-color: #FFF}
 .SLB_close { cursor: pointer; display:none; font-family: verdana,tahoma; font-size: 9pt; background-color:#000000; color: #ffffff; padding-bottom: 4px; }
 .SLB_caption { cursor: pointer; display:none; font-family: verdana,tahoma; font-size: 9pt; background-color:#000000; color: #ffffff; padding-bottom: 4px; }
 #SLB_loading { cursor: pointer; display:none; z-index: 99998; position:absolute; font-family: verdana,tahoma; font-size: 9pt; background-color:#000000; color: #ffffff; padding: 3px 0px 4px 0px; border: solid 2px #cfcfcf; }
</style>
<script language="javascript" type="text/javascript">
 // 심플 라이트박스 효과 by 알릭 (2007/08/22)
 // http://www.alik.info

 var SLB_cnt = 0;

 function SLB_show(url, type)
 {
  var a = document.getElementById('SLB_film');
  var b = document.getElementById('SLB_content');
  var c = document.getElementById('SLB_loading');
  if(url) {
   a.style.top = 0;
   a.style.left = 0;
   a.style.display = "";
   a.style.height = document.body.scrollHeight + 'px';
   document.getElementById('SLB_loading').style.display = "block";
   SLB_setCenter(c,true);
   if(type == 'image') {
    b.innerHTML="<img src=" + url + " class='SLB_center' onload='SLB_setCenter(this);' />";
    if(arguments[2]) a.onclick = function () { SLB_show() };
    if(arguments[3]) b.innerHTML += "<div class='SLB_caption'>"+ arguments[3] +"</div>";;
   } else if (type == 'iframe') {
    b.innerHTML="<iframe id='SLB_iframe' src=" + url + " width="+ arguments[2] +" height="+ arguments[3] +" class='SLB_center' marginwidth='0' marginheight='0' frameborder='0' vspace='0' hspace='0' onload='tryReHeight("+arguments[5]+");'/></iframe>";
    if(arguments[4]) {
     b.innerHTML += "<div class='SLB_close' onclick='SLB_show();' title='닫기'>close</div>";
    }
    b.onclick = ''; b.firstChild.style.cursor = 'default';
   } else if (type='html'){
    b.innerHTML = url;
    SLB_setCenter(b.firstChild);
    if(arguments[2]) b.onclick = '';
   }
   hideSelect();
  } else {
   a.onclick = '';
   a.style.display = "none";
   b.innerHTML = "";
   b.onclick = function () { SLB_show() };
   c.style.display = "none";
   showSelect();
   SLB_cnt = 0;
  }
 }
 
 function SLB_setCenter(obj) {
  if (obj) {
   var h = window.innerHeight || self.innerHeight || document.body.clientHeight;
   var w = window.innerWidth || self.innerWidth || document.body.clientWidth;
   var l = (document.body.scrollLeft + ((w-(obj.width||parseInt(obj.style.width)||obj.offsetWidth))/2));
   var t = (document.body.scrollTop + ((h-(obj.height||parseInt(obj.style.height)||obj.offsetHeight))/2));
   if((obj.width||parseInt(obj.style.width)||obj.offsetWidth) >= w) l = 0;
   if((obj.height||parseInt(obj.style.height)||obj.offsetHeight) >= h) t = document.body.scrollTop;
   document.getElementById('SLB_content').style.left = l + "px";
   if(SLB_cnt == 0) {
    document.getElementById('SLB_content').style.top = t + "px";
    if(document.getElementById('SLB_content').offsetHeight >= h) {
     SLB_cnt ++;
    }
   }
   obj.style.visibility = 'visible';
   if(obj.nextSibling && (obj.nextSibling.className == 'SLB_close' || obj.nextSibling.className == 'SLB_caption')) {
    obj.nextSibling.style.display = 'block';
    if(document.getElementById('SLB_content').offsetHeight < h) {
     document.getElementById('SLB_content').style.top = parseInt(document.getElementById('SLB_content').style.top) -     (obj.nextSibling.offsetHeight/2) + "px";
    }
   }
   if(!arguments[1]) {
    document.getElementById('SLB_loading').style.display = "none";
   } else {
    obj.style.left = l + "px";
    obj.style.top = t + "px";
   }
  }
 }
 
 function hideSelect() {
  var windows = window.frames.length;
  var selects = document.getElementsByTagName("SELECT");
  for (i=0;i < selects.length ;i++ )
  {
   selects[i].style.visibility = "hidden";
  }
 
  if (windows > 0) {
   for(i=0; i < windows; i++) {
    try {
     var selects = window.frames[i].document.getElementsByTagName("SELECT");
     for (j=0;j<selects.length ;j++ )
     {
      selects[j].style.visibility = "hidden";
     }
    } catch (e) {}
   }
  }
 }
 
 function showSelect() {
  var windows = window.frames.length;
  var selects = document.getElementsByTagName("SELECT");
  for (i=0;i < selects.length ;i++ )
  {
   selects[i].style.visibility = "visible";
  }
 
  if (windows > 0) {
   for(i=0; i < windows; i++) {
    try {
     var selects = window.frames[i].document.getElementsByTagName("SELECT");
     for (j=0;j<selects.length ;j++ )
     {
      selects[j].style.visibility = "visible";
     }
    } catch (e) {}
   }
  }
 }
 
 function tryReHeight(sign) {
  var getFFVersion=navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1];
  var FFextraHeight=parseFloat(getFFVersion)>=0.1? 16 : 0;
  var currentfr=document.getElementById('SLB_iframe');
  if(sign == true) {
   try {
    if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) {
     setIframeSize(currentfr.contentDocument.body.offsetHeight+FFextraHeight);
    } else if (currentfr.Document && currentfr.Document.body.scrollHeight) {
     setIframeSize(currentfr.Document.body.scrollHeight);
    }
   }catch(e) { }
  } else {
   SLB_setCenter(currentfr);
  }
 }

 function setIframeSize(h, w) {
  SLB_cnt = 0;
  var ifr = currentfr=document.getElementById('SLB_iframe');
  if (ifr) {
   if(w) {
    ifr.width = w;
   }
   if(h) {
    ifr.height = h;
   }
   SLB_setCenter(ifr);
  }
 }
 
 var prevOnScroll = window.onscroll;
 window.onscroll = function () {
  if(prevOnScroll != undefined) prevOnScroll();
  document.getElementById('SLB_film').style.height = document.body.scrollHeight + 'px';
  document.getElementById('SLB_film').style.width = document.body.scrollWidth + 'px';
  SLB_setCenter(document.getElementById('SLB_content').firstChild);
 }

 var prevOnResize = window.onresize;
 window.onresize = function () {
  if(prevOnResize != undefined) prevOnResize();
  document.getElementById('SLB_film').style.height = document.body.offsetHeight + 'px';
  document.getElementById('SLB_film').style.width = document.body.offsetWidth + 'px';
  SLB_setCenter(document.getElementById('SLB_content').firstChild);
 }
</script>
</head>

<body>

<div id="SLB_film" style="z-index: 99997; position:absolute; display:none; width:100%; height:100%; background-color:#000000; filter:Alpha(opacity=60); opacity:0.6; -moz-opacity:0.6;"></div>
<div id="SLB_content" onclick="SLB_show();" align="center" style="z-index: 99999; position:absolute;"></div>
<div id="SLB_loading" onclick="SLB_show();" title="로딩중...클릭시 취소">&nbsp;Loading...&nbsp;</div>

<div style="margin:10px 0px 0px 20px;">

<p><select><option value=1 />셀렉트 박스</select></p>

<h3><a href="./slb.js">slb.js 다운로드</a> &amp; 아래 내용은 설치법 및 사용예제!</h3>

<p style="line-height: 1.6">페이지에 slb.js 를 &lt;script language="javascript" type="text/javascript" src="/slb.js" &gt;&lt;/script&gt; 와 유사한 방식으로 추가해 주신후에 <br />
<br />
&lt;style type="text/css"&gt;<BR>&nbsp;html { width:100%; height:100%; }<BR>&nbsp;body { width:100%; height:100%; margin: 0px; padding: 0px; font-size:9pt; }<BR>&nbsp;.SLB_center { cursor:pointer; visibility:hidden; border: solid 4px #000000; background-color: #FFF}<BR>&nbsp;.SLB_close { cursor: pointer; display:none; font-family: verdana,tahoma; font-size: 9pt; background-color:#000000; color: #ffffff; padding-bottom: 4px; }<BR>&nbsp;.SLB_caption { cursor: pointer; display:none; font-family: verdana,tahoma; font-size: 9pt; background-color:#000000; color: #ffffff; padding-bottom: 4px; }<BR>&nbsp;#SLB_loading { cursor: pointer; display:none; z-index: 99998; position:absolute; font-family: verdana,tahoma; font-size: 9pt; background-color:#000000; color: #ffffff; padding: 3px 0px 4px 0px; border: solid 2px #cfcfcf; }<BR>&lt;/style&gt;
<br /><br />페이지에 위와 같이 스타일을 추가해주시구요~(css 에 추가하시거나~)<br /><br />
&lt;div id="SLB_film" style="z-index: 99997; position:absolute; display:none; width:100%; height:100%; background-color:#000000; filter:Alpha(opacity=60); opacity:0.6; -moz-opacity:0.6;">&lt;/div&gt;<br />
&lt;div id="SLB_content" onclick="SLB_show();" align="center" style="z-index: 99999; position:absolute;">&lt;/div&gt;     <br />
&lt;div id="SLB_loading" onclick="SLB_show();" title="로딩중...클릭시 취소">&nbsp;Loading...&nbsp;&lt;/div&gt;<br /><br />
위 3개 div 를 &lt;body&gt; 바로 밑에 추가해주시고 나서 아래의 예제를 참고하여 링크에 href="javascript:SLB_show('...');" 방식이나 onclick="SLB_show('...');" 으로 이용하시면 됩니다.</p>
<a onclick="SLB_show('http://i.blog.empas.com/frozen108/28257327_365x396.jpg','image',true);" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>이미지 띄우기</a><br />
실행코드: SLB_show('http://i.blog.empas.com/frozen108/28257327_365x396.jpg','image',true);<br />
설명: SLB_show('이미지주소', 'image', 반투명배경클릭시닫기?(true or false));<br /><br />
<a onclick="SLB_show('http://i.blog.empas.com/frozen108/28257327_365x396.jpg','image',false, '오~이쁘당!<i>김태희 ^^</i>');" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>이미지 띄우기 - 캡션과 함께</a><br />
실행코드: SLB_show('http://i.blog.empas.com/frozen108/28257327_365x396.jpg','image',false, '오~이쁘당!&lt;i&gt;김태희 ^^&lt;/i&gt;');<br />
설명: SLB_show('이미지주소', 'image', 반투명배경클릭시닫기?(true or false), '캡션내용');<br /><br />
<a onclick="SLB_show('http://www.yahoo.com','iframe', 600, 400, true, false);" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>아이프레임 띄우기</a> &nbsp; <a onclick="SLB_show('./blank1.html','iframe', 400, 400, true, true);" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>[1]</a> &nbsp; <a onclick="SLB_show('./blank2.html','iframe', 400, 400, true, true);" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>[2]</a><br />
SLB_show('http://www.yahoo.com','iframe', 600, 400, true, false);<br />
[1] = SLB_show('./blank1.html','iframe', 400, 200, true, true)<br />
[2] = SLB_show('./blank2.html','iframe', 400, 400, true, true)<br />
설명: SLB_show('아이프래임 src', 'iframe', 가로크기, 세로크기, 아이프렘하단에 닫기버튼표시?(true or false), 내용에 맞게 아이프레임의 높이 자동 조절?(true or false));<br /><br />
<a onclick="SLB_show('<div style=\'border:2px solid red; width:200px; height:100px; background-color:yellow\'>하하하하하<br />ㅋㅋㅋㅋ</div>','html');" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>html 띄우기1</a><br />
SLB_show('&lt;div style=\'border:2px solid red; width:200px; height:100px; background-color:yellow\'&gt;하하하하하&lt;br /&gt;ㅋㅋㅋㅋ&lt;/div&gt;','html');<br />
설명: SLB_show('html 소스', 'html', 중앙 내용클릭해도 안닫히기?(true or false));
<br /><br />
<a onclick="SLB_show('<div id=\'asd\'><div>TABLE</div><table border=1 bgcolor=#ffffff><tr><td>다른곳은</td><td> 클릭해도</td></tr><tr><td>안닫힘</td><td onclick=\'SLB_show();\' bgcolor=\'red\'>닫기는여기<br />onclick=\'SLB_show();\'</td></tr></table></div>','html', true);" style='cursor:pointer; border-bottom:2px solid blue; line-height:2;'>html 띄우기2</a>
<br />
SLB_show('&lt;div id=\'asd\'&gt;&lt;div&gt;TABLE&lt;/div&gt;&lt;table border=1 bgcolor=#ffffff&gt;&lt;tr&gt;&lt;td&gt;다른곳은&lt;/td&gt;&lt;td&gt;클릭해도&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;안닫힘&lt;/td&gt;&lt;td onclick=\'SLB_show();\' bgcolor=\'red\'&gt;닫기는여기&lt;br /&gt;onclick=\'SLB_show();\'&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;','html', true);<br />

<p><iframe width=200 height=100 id="testframe" name="testframe"></iframe></p>
<script>
 testframe.document.write('<p>아이프레임 내부의<br /><br /><select><option value=1 />셀렉트 박스</select></p>');
 testframe.document.close();
</script>
<p>
* 닫기는 SLB_show(); 를 호출하면 닫힘<br />
* 아이프래임의 내부에 있는 문서에서 닫을려면 parent.SLB_show(); 로 닫을수 있음.<br />
* 로딩중 표시를 클릭하면 로딩 취소됨<br />
* 반투명배경의 투명도 및 색상은 <br />
&lt;div id="SLB_film" style="z-index: 99997; position:absolute; display:none; width:100%; height:100%; <font style="BACKGROUND-COLOR: #ffff00" color=#fe1100>background-color:#000000; filter:Alpha(opacity=60); opacity:0.6; -moz-opacity:0.6;</font>"&gt;&lt;/div&gt;
<br />에서 수정가능<br />
* 검정색 이미지 테두리의 두께와 색상은<br />
.SLB_center { cursor:pointer; visibility:hidden; <font style="BACKGROUND-COLOR: #ffff00" color=#fe1100>border: solid 4px #000000;</font> background-color: #FFF}
<br />에서 수정가능<br />
* '내용에 맞게 아이프레임의 높이 자동 조절' 은 아이프레임 내부의 문서가 외부의 문서와 같은 도메인 안에 존재할때만 작동함.<br />
* '내용에 맞게 아이프레임의 높이 자동 조절' 을 true 로 설정해도 기본으로 아무값이나 가로, 세로 값을 넣어줘야 함!.
</p><p>&nbsp;</p>
</div>
</body>
</html>

$objSock = fsockopen(호스트, 포트, $strErrorNo, $strErrStr, 5);
if($objSock)
{
    $strHeader  = "GET http://url부분 HTTP/1.1\r\n";
    $strHeader .= "Host:호스트:포트\r\n";
    $strHeader .= "Authorization:Basic " . base64_encode("아이디:암호") . "\r\n";
    $strHeader .= "\r\n";
    fputs($objSock, $strHeader);
    $strResult = "";
    while (!feof($objSock))
    {
        $strResult .= fgets($objSock, 65535);
    }
    fclose($objSock);
...

JavaScript용 픽셀단위 문자열 자르기

// by ziecle 07.02.06
function __getText(elem)
{
    if (elem.innerText) return elem.innerText;
    if (elem.textContent) return elem.textContent;
    return elem.innerHTML.replace(/<\/?[^>]+>/gi,"");
}

function __setText(elem, text)
{
    if (elem.innerText) { elem.innerText = text; return; }
    if (elem.textContent) { elem.textContent = text; return; }
    while (elem.firstChild) elem.removeChild(elem.firstChild);
    elem.appendChild(document.createTextNode(text), elem.childNodes[0]);
}

function stringCut(elem, cutWidth, suffix)
{
    var str = __getText(elem);

    var len;
    if (!str || !(len = str.length))
        return;

    elem.style.whiteSpace = "nowrap";
    elem.style.textOverflow = "ellipsis";
    elem.style.overflow = "hidden";

    var width = elem.offsetWidth;

    if (!width || width < cutWidth - 8)
        return;

    var temp = cutWidth;

    if (suffix)
    {
        elem.innerHTML += suffix;

        cutWidth -= (elem.offsetWidth - width + 4);

        if (cutWidth < 0)
            return;
    }
    else
    {
        suffix = "";
    }

    elem.title = str;

    var cut = parseInt(cutWidth / (width / len)) + 1;

    __setText(elem, str.substr(0, cut));

    if (elem.offsetWidth > cutWidth)
    {
        while (--cut)
        {
            __setText(elem, str.substr(0, cut).replace(/(\s*$)/g, ""));

            if (elem.offsetWidth < cutWidth)
            {
                break;
            }
        }
    }
    else
    {
        while (cut++ < len)
        {
            __setText(elem, str.substr(0, cut));

            if (elem.offsetWidth > cutWidth)
            {
                __setText(elem, str.substr(0, cut - 1).replace(/(\s*$)/g, ""));
                break;
            }
        }
    }

    elem.innerHTML += suffix;
}
 

방법은 무식합니다.
IE 6, 파폭 2.0.0.1에서 테스트했습니다.
사용법:
stringCut(문자열이 들어가는 엘리먼트, 너비, 붙을단어);
예제:
랄랄랄라~라랄라~랄랄랄라~라랄라~랄랄랄라~라랄라~랄랄랄라~라랄라~

많은 분들이 크로스 브라우저를 위해 이리저리 브라우저를 띄워 디버깅을 하실껍니다.

그러나 이젠 그냥 파이어 폭스만 실행 하고 두가지 브라우저를 한꺼번에 체크하세요.

파이어 폭스로 다음 사이트를 방문하여 addon을 설치하면
탭을 익스플로러로 만들수 있습니다.

https://addons.mozilla.org/firefox/1419/

물론 설치후 툴바를 조정해서 아이콘을 보이게 해야죠~



<html>
<head></head>

<body>
    <script language="Javascript">


            /******************************************************************************
            * 만든목적: JS 롤링;
            * 만든이:허웅 [comefeel];
            * 제작시간:총 7~8시간;
            * JS 경력:현재 6개월차 -..-; 초허접;
            * last update:2007.01
            * igear.co.kr 도와준분 [zeldign] 플머 12년차;
            * e-mail : igearmall.co.kr <comefeel@daum.net> comefeel@comefeel.com 도 있지만 현재 안됨 ;
            * 이것을 사용할려고 할시에 주석을 지우면 사용할수 없음;
            * 허접한 소스를 보고 -_-+ 머라고 하면 쫏아감;
            * **
            */

            var roll_Class=function(){this.initialize.apply(this,arguments);}
            roll_Class.prototype={

            initialize:function(){

            this.className=arguments[0]?arguments[0]:null;
            this.foundit(arguments[1],'',false);
            this.contents=new Array('0');
            this.contents_delay=null;
            this.nowdelay=null;
            this.foundit(
            this.roll.childNodes,this.foundvalue ,
            function(rt,that){

            if(that.constrain_size !== null) that.foundit(rt.childNodes,'IMG',function(rt,that){rt.style[(this.moving != 'left' ? 'width' : 'height')] = that.constrain_size;});
            that.contents_delay=that.contents[that.contents.length]=that.contents_delay+-rt[(that.moving=='left'?'offsetWidth':'offsetHeight')];});

            {
            this.rollHeight=this.proll.style[(this.moving=='left'?'width':'height')]=Math.abs(this.contents[this.contents.length-1]);
            this.roll.appendChild(this.roll.cloneNode(true));
            };},


            foundit:function(tg,n){

            var temp=new Array();

                for(var v in tg)
                    switch(typeof arguments[2]){
                    case 'object':if(arguments[2].initialize(tg[v],n,this)==true) return; else break;
                    case 'function':if(tg[v].nodeName==n) arguments[2](tg[v],this); break;
                    case 'boolean':this[v]=tg[v]; break;
                    default:if(tg[v].nodeName==n) return tg[v];
                }

            return temp;},

            inaction:function(time){

            this.roll.style[this.moving]=time=time < 0 ?(this.fall==false && time <= -this.rollHeight?0:time):-this.rollHeight,null;
            this.foundit(this.contents,time,{initialize:function(rt,vrt,that){if(Math.abs(rt - vrt) <(that.fast==false?that.tick:that.ftick)){that.roll.style[that.moving]=rt; that.nowdelay=that.fast==true?that.lengthen:that.delay; that.fast=false; return true;} else that.nowdelay=that.lengthen;}});
            {var ticks=this.fast==true?this.ftick:this.tick;}
            this.control=setTimeout(this.className+".inaction("+(parseInt(this.roll.style[this.moving])+(this.fall==true?ticks:-ticks))+");",this.nowdelay);},

            stop:function(){

            this.temp=parseInt(this.roll.style[this.moving]);
            clearTimeout(this.control);}    };

    </script>


    <!-- 가로롤링 셈플 -->

    <table>
        <tr>

            <td width="3" height="115" background="http://sportbox.co.kr/images/left_move2.gif" style="padding:0px 0px 0px 15px;cursor:pointer" style="cursor:pointer"  onclick="width_class.fall=false;width_class.fast=true;"></td>
            <td>

            <div id="parent_rolltable" name="parent_rolltable" style='overflow:hidden;border:1px solid #000000;' onmouseover="width_class.stop();" onmouseout="width_class.inaction(width_class.temp);">
                <nobr id="rolltable" name="rolltable" style="position:relative;" ><span><img src="http://sportbox.co.kr/skinwiz/layout/sportbox/images/brand_08.gif" ></span><span><img src="http://sportbox.co.kr/skinwiz/layout/sportbox/images/brand_08.gif" ></span><span><img src="http://sportbox.co.kr/skinwiz/layout/sportbox/images/brand_08.gif" ></span><span><img src="http://sportbox.co.kr/skinwiz/layout/sportbox/images/brand_08.gif" ></span></nobr>
            </div>


            </td><td width="3" height="115" background="http://sportbox.co.kr/images/right_move2.gif" style="padding:0px 0px 0px 15px;cursor:pointer"  onclick="width_class.fall=true;width_class.fast=true;"></td>
            </td>
        </tr>
    </table>




    <br />


    <!-- 세로롤링 셈플 -->

    <table border="0" cellpadding="0" cellspacing="0">

            <tr>
                <td align="center"><img src="http://insetup.igear.biz/shop/common/img/bt_ps_today.gif" width="80" height="27" alt="" style="cursor:pointer"  onclick="height_class.fall=false;height_class.fast=true;"/></td>
            </tr>

            <tr>
                <td align="center">
                    <img src="http://insetup.igear.biz/shop/common/img/bt_ps_prev.gif" width="25" height="8" alt="" style="cursor:pointer"  onclick="height_class.fall=false;height_class.fast=true;" />
                </td>
            </tr>

            <tr>
                <td>

                    <div id="parent_rolltable1" name="parent_rolltable1" style='overflow:hidden;text-overflow:ellipsis;border:1px solid #ffffff' onmouseover="height_class.stop();" onmouseout="height_class.inaction(height_class.temp);">
                        <nobr  id="rolltable1" name="rolltable1" style="position:relative;">



                                <div style="text-align:center;padding-bottom:5px;">
                                    <img src="http://www.jpboom.com/shop/img/skyscraper/sign.gif" border="0">
                                </div>
                                <div style="text-align:center;padding-bottom:5px;">
                                    <img src="http://www.jpboom.com/shop/img/skyscraper/card.gif" border="0">
                                </div>
                                <div style="text-align:center;padding-bottom:5px;">
                                    <img src="http://www.jpboom.com/shop/img/skyscraper/10persale_scbanner.gif" border="0">
                                </div>
                                <div style="text-align:center;padding-bottom:5px;">
                                    <img src="http://www.jpboom.com/shop/img/skyscraper/afterboard_scbanner.gif" border="0">
                                </div>
                                <div style="text-align:center;padding-bottom:5px;">
                                    <img src="http://www.jpboom.com/shop/img/skyscraper/100perguide_scbanner.gif" border="0">
                                </div>


                        </nobr>
                    </div>


                </td>
            </tr>

            <tr>
                <td align="center">
                    <img src="http://insetup.igear.biz/shop/common/img/bt_ps_next.gif" width="25" height="8" alt="" style="cursor:pointer"  onclick="height_class.fall=true;height_class.fast=true;" />
                </td>
            </tr>
            <tr>
                <td height="20" align="center" valign="middle" bgcolor="#75BD2F" style="cursor:pointer"  onclick="height_class.fall=true;height_class.fast=true;">

                </td>
            </tr>
            <tr>
                <td align="center"><img src="http://insetup.igear.biz/shop/common/img/img_ps_bottom.gif" width="85" height="5" alt=""  /></td>
            </tr>
          </table>






        <!-- 디버그

        <table>
        <tr>
        <td>
        <iframe id="scv" name="scv" width="700" height="1000"></iframe>
        </td>
        </tr>
        </table>-->

        <script language="Javascript">

            {

                // 가로롤링 설정키
                var roll_init=new Array();
                roll_init.constrain_size=null;                            // 전체의 높이값 [기본 default]
                roll_init.tick=1;                                                    // 움직이는 칸수
                roll_init.ftick=10;                                                // 빠른 움직이는 칸수
                roll_init.lengthen=10;                                        // 1초당 움직이는 속도
                roll_init.delay=1000;                                            // 잠시멈춤 속도
                roll_init.fall=true;                                                // 이동 반대로 설정 ~
                roll_init.fast=false;                                            // 빠른속도:true 는 on 이며,false 는 off 이다.
                roll_init.foundvalue =    'SPAN';                                // Nobr 내부엘리멘트
                roll_init.moving='left';                                         // 상하좌우 움직임 설정
                roll_init.roll=document.getElementById('rolltable');                                        // roll
                roll_init.proll=document.getElementById('parent_rolltable');                            // proll

            };

            {

                // 가롤롤링 선언부분

                var width_class=new roll_Class('width_class',roll_init);
                width_class.inaction();

            };


            {

                // 세로롤링 설정키
                var roll_init1=new Array();
                roll_init1.constrain_size=null;                            // 전체의 넓이값 [기본 default]
                roll_init1.tick=1;                                                    // 움직이는 칸수
                roll_init1.ftick=10;                                                // 빠른 움직이는 칸수
                roll_init1.lengthen=10;                                        // 1초당 움직이는 속도
                roll_init1.delay=1000;                                            // 잠시멈춤 속도
                roll_init1.fall=true;                                                // 이동 반대로 설정 ~
                roll_init1.fast=false;                                            // 빠른속도:true 는 on 이며,false 는 off 이다.
                roll_init1.foundvalue =    'DIV';                                // Nobr 내부엘리멘트
                roll_init1.moving='top';                                         // 상하좌우 움직임 설정
                roll_init1.roll=document.getElementById('rolltable1');                                        // roll
                roll_init1.proll=document.getElementById('parent_rolltable1');                            // proll
            };

            {

                // 세로롤링 선언부분
                var height_class=new roll_Class('height_class',roll_init1);
                height_class.inaction();

            };

        </script>



    </body>
    </html>

http://comefeel.com/roll.html

원문 : http://kwon37xi.egloos.com/2971666
개발시 디버깅을 위해 필수적으로 필요한 것이 로그이다. 이는 개발시 뿐만 아니라 운영중에 오류가 발생했을 때도 오류의 원인을 찾는데 커다란 역할을 하는 중요한 개발 요소 중의 하나이다.

PHP에서 개발자의 로그를 어떻게 남기는지 몰라서 계속해서 var_dump($variable);로 브라우저 화면에 로그를 남겨서 본 뒤에 그 로그 출력 코드를 삭제해 버리는 방식으로 작업을 했다.
대다수의 PHP 개발자들이 var_dump(), print_r() 함수등을 이용해서 위와 같은 방식으로 로그를 기록해서 디버깅을 하는 것 같다. 하지만 이는 매우 좋지 못한 방식이다.

    * 로그를 출력 한 뒤에 로그 출력 코드를 항상 지워야만 한다. 그렇지 않으면 로그가 브라우저를 통해 사용자에게 전달 돼 버리므로.
    * 이로인해 매우 개발이 귀찮기 짝이 없는 작업이 된다.
    * 실제 운영 시간에 발생한 오류에 대해 에러 메시지만을 얻을 수 있을 뿐 그 당시 상태에 관한 로그를 전혀 얻을 수가 없다.


그러다가, 너무 짜증이나서 간단한 로깅 함수를 만들어서 바꾸었다.
그러나 여전히 맘에 안든다. 로그 레벨 지정이나, 로그 파일 날짜별로 돌리기 등 기능이 너무 부족하다.

PHP에서 로깅 전략에 대한 글을 찾아보니 우리나라에서는 거의 없는거 같고, devshed에 Logging With PHP라는 좋은 글이 있었다.
그 중에서도 PEAR Log Package를 이용하기로 하였다. PEAR에는 여러 좋은 패키지들이 많이 깔끔하게 정리되어 있는 것 같다. 근데, 우리나라 PHP 개발자들은 아직 잘 안쓰는건가? 관련 글을 찾아보기가 쉽지 않네.

그 외에도 Log4PHP가 있는데, 사실 이걸 쓰고 싶은 생각이 정말 많이 들었었다. Apache에서 만든 것이고, 이미 내게 익숙한 Log4J의 PHP 포팅이기 때문이다. 게다가 설정 파일을 통해 언제든지 로깅 방식을 변경할 수도 있다(Log4J처럼). 하지만, 참은 이유는.... 2003년 이후 버전업이 전혀 안되고 있기 때문이다. 4년씩이나 버전 업이 안되는 건 좀 이해가 안간다.

PEAR::Log 사용법과 로그 레벨 지정, 날짜별 파일로 로그 남기기, 로그를 남길 때마다 어떤 PHP파일의 몇 번째 줄에서 로그를 남겼는지 출력하기, PHP의 오류 메시지를 PEAR::Log를 이용해 로그로 남기기 등의 기법을 정리해 본다. 대부분의 내용은 PEAR::Log의 매뉴얼을 정리한 것이다.

설치

    $ pear install log



로깅 객체 얻기

    require_once 'Log.php';

    $logger = &Log::singletone('file', 'C:/temp/test.log', 'Test'); # 로깅을 위한 객체 얻기
    $logger->log('이래 저래 에러가 났잖아욧!'); # 로그 메시지 출력하기


싱글턴으로 객체를 가져옴으로써 불필요한 객체 생성과, 객체가 소유하고 있는 리소스의 중복 정의를 방지한다.

&Log::singleton($handler, $name, $ident, $conf, $maxLevel);

 * $handler : 로그 핸들러 타입. console, file 등 로그 출력을 처리하는 방식을 지정한다.$name : 파일 이름과 같이, 로그를 기록할 자원을 지정한다. 핸들러 구현체에 따라서 이 파라미터가 뭘로 사용될지 결정된다.
 * $name : 로그 파일명 등을 의미한다. $handler에 따라 의미가 달라진다.
 * $ident : 로그 구분자이다. Java의 Log4j에서 클래스 FQCN과 같은 역할을 한다.
 * $conf : 연관 배열로 핸들러에 사용자 정의 설정 정보를 넘겨준다.
 * $maxLevel : 최대 로그 레벨을 결정한다. 기본값은 PEAR_LOG_DEBUG(최대값)이다. 이 레벨보다 낮아야 로그가 기록된다.

$logger->log("로그메시지", PEAR_LOG_NOTICE);와 같은 방식으로 로그를 기록한다.

로 그 메시지 부분에는 문자열 뿐만 아니라, 일반 객체를 지정해도 된다. 객체가 getString(), toString() 혹은 __toString() 메소드를 구현하고 있다면 그 메소드를 실행해서 메시지를 기록한다. 모두 없다면 객체를 직렬화한 값을 출력할 것이다.

만약 배열과 같이 복잡한 타입의 변수 값을 제대로 찍고 싶다면 $logger->log($variable) 처럼, 문자열로 바꾸지 말고, 변수를 그대로 인자로 넘겨주면, var_dump($variable) 한 것처럼 변수 내용을 찍어준다.

로그 레벨

로그 레벨 옆의 메소드명은 log() 메소드에 로그 레벨을 지정하는 대신, 해당 메소드를 직접 호출하면, 그 로그 레벨로 로그가 남게 됨을 의미한다.
즉, $logger->log("로그메시지", PEAR_LOG_DEBUG) 는 $logger->debug(" 로그메시지") 와 동일한 역할을 한다.
 * PEAR_LOG_EMERG emerg() 시스템이 사용 불가 상태에 빠졌다.
 * PEAR_LOG_ALERT!! alert!!() 즉시 처리가 필요하다.
 * PEAR_LOG_CRIT crit() 심각한 상태이다.
 * PEAR_LOG_ERR err() 오류
 * PEAR_LOG_WARNING warning() 경고
 * PEAR_LOG_NOTICE notice() 주의
 * PEAR_LOG_INFO info() 정보
 * PEAR_LOG_DEBUG debug() 디버그 메시지

로그 레벨 마스크(mask)

특정 로그 레벨의 로그 메시지만 출력하도록 지정한다.

    $mask = Log::UPTO(PEAR_LOG_INFO);
    $logger->setMask($mask);


최소 PEAR_LOG_INFO 까지 로그 메시지만 출력한다. 즉, PEAR_LOG_EMER ~ PEAR_LOG_INFO 까지 메시지만 로그로 남긴다.

    $mask = Log::MASK(PEAR_LOG_NOTICE) | Log::MASK(PEAR_LOG_DEBUG);


PEAR_LOG_NOTICE와 PEAR_LOG_DEBUG 레벨의 메시지만을 로그로 남긴다.
 * PEAR_LOG_ALL 모든 로그 레벨을 포함하고 있는 마스크
 * PEAR_LOG_NONE 어떤 로그 레벨도 포함하지 않고 있는 마스크

    $mask =PEAR_LOG_ALL ^ Log::MASK(PEAR_LOG_NOTICE);


PEAR_LOG_NOTICE만 제외하고 로그를 남긴다.

    $logger->getMask();


현재 로거의 로그 마스크를 가져온다.

로그 이벤트 내보내기

몇몇 로그 핸들러는 로그 메시지를 버퍼링 한다. 버퍼링된 로그 메시지를 모두 출력하도록 하려면,

    $logger->flush();
    혹은,
    $logger->close();


로거를 닫아도 flush가 된다.

로그 핸들러

로그 핸들러는 로그를 어떤식으로 처리할지를 결정하는 것이다. 모든 로거는 로그 핸들러를 지정해야 한다.
로그 객체를가져올 때 'console' 하는 식으로 지정하는 것이다. 구체적인 사용법은 매뉴얼을 참조한다.
 * console : 화면상에 로그를 출력한다.
 * display : 웹 브라우저에 로그를 출력한다.
 * error_log : PHP의 error_log 함수를 사용해서 로그를 출력한다.
 * file : 파일로 로그를 출력한다.
 * mail : 이메일로 로그를 전송한다.
 * null : 로그를 무시한다.
 * sql : DB에 로그를 저장한다.
 * sqlite : SQLite DB에 로그를 저장한다.
 * syslog : PHP의 syslog() 함수를 이용해서 로그를 저장한다.
 * win : 브라우저의 새창으로 로그를 출력한다.
 * composite : 여러 핸들러를 함께 사용할 수 있게 해준다.

    $console = &Log::singleton('console', '', 'TEST');
    $file = &Log::singletone('file', 'out.log', 'TEST');
    $composite = &Log::singleton('composite');
    $composite->addChild(&console);
    $composite->addChild($file);
    $composite->log('blah blah blah...');
    $composite->removeChild($file); # 로그 핸들러 삭제



File 로그 핸들러

file 로그 핸들러를 제일 많이 사용할 것이기 때문에, 이에대해 정리한다.
 * 설정값 : 설정키(Type, 기본값)
  o append(boolean, true) : true이면 기존의 로그파일에 계속 추가해서 쓰고, false이면 기존 파일을 삭제하고 새로 쓴다.
  o mode(integer, 0644) : Unix 계열에서 파일의 허가권 지정
  o eol(string, OS default) : 줄끝 문자
  o lineFormat(string ,%1$s %2$s [%3$s] %4$s]) 로그 출력 형태 지정
  o timeFormat(string, %b %d %H:%M:%S) : 시간 출력 형태 지정(strftime 함수로 시간을 출력한다.)
 * 설정값의 lineFormat
  o %1$s : 날짜와 시간
  o %2$s : $ident
  o %3$s : 로그 레벨
  o %4$s : 로그 메시지
  o %5$s : log() 메소드를 호출한 파일명
  o %6$s : log()메소드를 호출한 줄 번호
  o %7$s : log()메소드를 호출한 함수명
 * 예제

    $conf = array('mode'=>0600, 'timeFormat'=>'%X %x');
    $logger = &Log::singletone('file', 'out.log', 'ident', $conf);
    for ($i = 0; $i < 10; $i++) {
        $logger->log("Log entry $1");
    }



표준 오류 출력을 PEAR::Log 패키지로 위임하기

PHP 사용중 발생하는 예외와 오류를 PEAR::Log 패키지를 이용해 처리하도록 지정할 수 있다.
이것은 set_error_handler() 함수를 이용해서 가능하다.

    function errorHandler($code, $message, $file, $line)
    {
        global $logger;
        /* Map the PHP error to a Log priority. */
        switch ($code) {
            case E_WARNING:
            case E_USER_WARNING:
                $priority = PEAR_LOG_WARNING;
                break;

            case E_NOTICE:
            case E_USER_NOTICE:
                $priority=PEAR_LOG_NOTICE;
                break;

            case E_ERROR:
            case E_USER_ERROR:
                $priority = PEAR_LOG_ERR;
                break;

            default:
                $priority = PEAR_LOG_INFO;
        }
        $logger->log($message . ' in ' . $file . ' at line ' . $line, $priority);
    } // end of function

    set_error_handler('errorHandler');

    # test
    trigger_error('This is an information log message.', E_USER_NOTICE);



나는 이렇게 사용한다

강력한 설정기능 등이 Log4php에 비해 많이 딸리는 편인데, 어쨌든, 나는 아래 처럼 사용한다.
아래에서 정의한 logger() 함수는 PEAR::Log를 이용해서, 날짜별로 로그 파일을 남기는 것이다.
그리고, 로그를 남길 때는 항상 로그를 찍은 소스 파일명과 로그를 찍은 코드의 줄 번호도 함께 출력하도록 하였다.
파일 이름은 logger.php라고 치자.

    <?php
    require_once 'Log.php';

    // PHP 5.1.x 의 set_error_handler()로 지정된 함수 내부에서
    // 클래스 정의를 가진 PHP 파일을 require/include 할 경우에
    // 오류가 발생하는 문제를 해결하기 위해
    // 미리 필요한 클래스를 require 해둬야 한다.
    // 관련 URL : http://bugs.php.net/35634
    require_once 'Log/file.php';

    /**
    * 사용자가 명시적으로 LOG_FILENAME 상수를 지정하지 않았다면,
    * 오류를 발생시킨다.
    */
    if (!defined('LOG_FILENAME')) {
        trigger_error("You have to define LOG_FILENAME for logger", E_USER_ERROR);
    }

    /**
    * 사용자가 명시적으로 LOG_LEVEL 상수를 정의하지 않았다면,
    * DEBUG 로그 레벨로 강제 지정한다.
    *
    * 이 파일 외부에서 로그 레벨을 지정할 경우, require_once 'Log.php'; 를 실행한
    * 이후에 상수에 PEAR_LOG_* 값을 줘야 함을 잊어서는 안된다.
    */
    if (!defined('LOG_LEVEL')) {
        define ('LOG_LEVEL', PEAR_LOG_DEBUG);
    }

    /**
    * PHP자체에서 발생하는 로그의 레벨을 지정한다.
    * errorHandler() 함수에서 이 로그레벨을 넘지 않으면, 오류를 출력하지 않도록
    * 만들어져 있다.
    *
    * 이 파일 외부에서 로그 레벨을 지정할 경우, require_once 'Log.php'; 를 실행한
    * 이후에 상수에 PEAR_LOG_* 값을 줘야 함을 잊어서는 안된다.
    */
    if (!defined('PHP_LOG_LEVEL')) {
        define('PHP_LOG_LEVEL', PEAR_LOG_WARNING);
    }

    // PHP 에러 핸들러를 PEAR::Log 를 사용하도록 변경한다.
    set_error_handler('errorHandler');

    /**
    * 파일로 로그를 저장하는 로거 객체를 리턴한다.
    * Log 클래스를 직접 호출하지 말고, 일관성 있게 get_logger() 메소드를 사용해서
    * 로거 객체를 얻도록 한다.
    *
    * LOG_FILENAME 상수로 지정된 파일 이름에 .yyyymmdd 형태로 날짜를 붙여 로그 파일을
    * 생성한다.
    *
    * @param string $ident 로거 구분 문자열. 일반적으로 "클래스명.Method명" 혹은  "function명"
    * 처럼 지정하면 된다. 이 파라미터를 지정하지 않으면 항상 get_logger를 호출한 파일의 이름으로
    * 지정된다.
    * @param integer 로그 레벨을 지정한다. PEAR_LOG_XXX 형태의 상수로 정의 되어있다.
    * @return Log 로거 객체
    */
    function logger($ident = "GlobalLogger", $logLevel = LOG_LEVEL)
    {
        $today_date = date('Ymd', mktime()); // 오늘날짜 yyyymmdd 형태
       
        $conf = array(
            'buffering' => false,
            'lineFormat' => '[%3$s] %2$s %1$s (%5$s %6$s %7$s) %4$s',
            'timeFormat' => '%Y%m%d %H:%M:%S'
        );
       
        $logger = &Log::singleton('file', LOG_FILENAME . "." . $today_date, $ident, $conf);
       
        $mask = Log::UPTO($logLevel);
        $logger->setMask($mask);

        return $logger;
    }

    /**
    * PHP 기본 에러 핸들러를 변경한다.
    */
    function errorHandler($code, $message, $file, $line)
    {
        /* Map the PHP error to a Log priority. */

        switch ($code) {
            case E_STRICT:
            case E_NOTICE:
            case E_USER_NOTICE:
                $priority = PEAR_LOG_NOTICE;
                break;
            case E_WARNING:
            case E_USER_WARNING:
                $priority = PEAR_LOG_WARNING;
                break;
            case E_ERROR:
            case E_USER_ERROR:
                $priority = PEAR_LOG_ERR;
                break;
            default:
                $priority = PEAR_LOG_WARNING;
        }
       
        $logger = logger("PHPError", PHP_LOG_LEVEL);

        $logger->log($message . ' in ' . $file . ' at line ' . $line, $priority);
    }


    /**
    * 변수를 받아서 var_export()한 결과를 문자열로 저장하여 넘겨준다.
    * 로그 메시지로 복잡한 형태의 변수나 배열을 출력하고 싶을 때 사용한다.
    *
    * @param mixed $variable 출력할 변수
    */
    function var_export_str($variable) {
        ob_start();
        var_export($variable);
        $logmsg .= ob_get_contents();
        ob_end_clean();
       
        return $logmsg;
    }
    ?>


위 logger()메소드는 다음 처럼 간단히 활용할 수 있다.

    <?php
    // 로그레벨 설정 상수가 Log.php에 들어 있기 때문에
    // 로그 레벨 설정과 logger.php보다 Log.php를 먼저 require 해줘야 한다.
    require_once 'Log.php';

    define('LOG_FILENAME', 'C:/Temp/test.log');
    define('LOG_LEVEL', PEAR_LOG_DEBUG);
    define('PHP_LOG_LEVEL', PEAR_LOG_WARNING);

    require_once 'logger.php';

    echo "Why?<br/>";

    logger()->log("하하..", PEAR_LOG_INFO);
    logger()->debug("허허.. 이건 DEBUG레벨");
    logger()->alert!!("경고야!!");
    $arr = array("key" => "value",
        "array-" => "var_export_str 함수를 이용해서 감싸서 로그를 남기세요."
    );
    logger()->info("객체나 배열같은 변수를 로깅 하는 방법은 두가지가 있다.");
    logger()->info($arr); # 이처럼 변수를 그냥 넘기는 방법과
    logger()->info("배열 : " . var_export_str($arr)); # 이렇게 var_export_str()로 감싸는 방법
    ?>


위를 실행하면 C:\Temp\test.log.오늘날짜 파일로 다음과 같이 로그가 남는다.

    [info] GlobalLogger 20070207 18:38:03 (C:\test\test.php 14 (none)) 하하..
    [debug] GlobalLogger 20070207 18:38:03 (C:\test\test.php 15 (none)) 허허.. 이건 DEBUG레벨
    [alert!!] GlobalLogger 20070207 18:38:03 (C:\test\test.php 16 (none)) 경고야!!
    [info] GlobalLogger 20070207 18:38:03 (C:\test\test.php 20 (none)) 객체나 배열같은 변수를 로깅 하는 방법은 두가지가 있다.
    [info] GlobalLogger 20070207 18:38:03 (C:\test\test.php 21 (none)) Array
    (
        [key] => value
        [array-] => var_export_str 함수를 이용해서 감싸서 로그를 남기세요.
    )

    [info] GlobalLogger 20070207 18:38:03 (E:\Workspace\ServiceCSTool2\test.php 22 (none)) 배열 : array (
      'key' => 'value',
      'array-' => 'var_export_str 함수를 이용해서 감싸서 로그를 남기세요.',
    )

사용자 삽입 이미지


해당 게시물의 인기도를 뽑아오는 클래스 입니다.

클래스 부분은 그냥 복사해서 적당한 파일로 만들어서 서버에 올리고

해당 페이지에선 인클루드 하여 사용합니다.

이하 클래스
______________________________________________________________________

<?

//게시물의 인기도를 측정하는 클래스
class favor_point {

  var $point_good;
  var $point_nogood;
  var $point_comment;
  var $point_defalut_full;

  var $set_default;
  var $set_good;
  var $set_comment;

  function favor_point($point_good=100, $point_comment=30, $point_defalut_full=5000, $set_default=70, $set_good=15, $set_comment=15){

    $this->set_point($point_good, $point_comment, $point_defalut_full);
    $this->set_setting($set_default, $set_good, $set_comment);

    if (empty($this->point_good) || empty($this->point_nogood) || empty($this->point_comment) || empty($this->point_defalut_full) || empty($this->set_default) || empty($this->set_good) || empty($this->set_comment)) {

      die('favor_point : 제대로 된 변수값이 설정되지 않았습니다.');
    }
  }

  function set_point($point_good, $point_comment, $point_defalut_full){

    if ($point_good < 1 || $point_comment < 1 || $point_defalut_full < 1 || !is_numeric($point_good) || !is_numeric($point_comment) || !is_numeric($point_defalut_full)) return;
    $this->point_good =  $point_good;
    $this->point_nogood = ceil($point_good * (-1.1));
    $this->point_comment = $point_comment;
    $this->point_defalut_full = $point_defalut_full;
  }

  function set_setting($set_default, $set_good, $set_comment){

    if ($set_default < 1 || $set_good < 1 || $set_comment < 1 || !is_numeric($set_default) || !is_numeric($set_good) || !is_numeric($set_comment)) return;

    if ($set_default + $set_good + $set_comment != 100) return;

    $this->set_default = $set_default;
    $this->set_good = $set_good;
    $this->set_comment = $set_comment;
  }

  function get_favor_point($good, $nogood, $comment, $hit, $date=''){

    $return = Array();

    if (empty($date)) $date = date("Y-m-d");
    $day = ceil((time() - strtotime($date)) / 86400);
    $rule = $this->autochange_rule($day);

    $return['default'] = ceil((($good * $rule['point_good']) + ($nogood * $rule['point_nogood']) + ($comment * $rule['point_comment']) + $hit) / $rule['point_defalut_full'] * $rule['set_default']);

    if ($return['default'] > $rule['set_default']) $return['default'] = $rule['set_default'];
    else if ($return['default'] < 0) $return['default'] = 0;

    if ($good > 0 && $good > $nogood) {

      $return['good'] = ceil((1 - ($hit / (($good * $rule['point_good']) + ($nogood * $rule['point_nogood'])))) * $rule['set_good']);

      if ($return['good'] > $rule['set_good']) $return['good'] = $rule['set_good'];
      else if ($return['good'] < 0) $return['good'] = 0;
    }
    else {

      $return['good'] = 0;
    }

    if ($comment > 0) {

      $return['comment'] = ceil((1 - ($hit / ($comment * $rule['point_comment']))) * $rule['set_comment']);

      if ($return['comment'] > $rule['set_comment']) $return['comment'] = $rule['set_comment'];
      else if ($return['comment'] < 0) $return['comment'] = 0;
    }
    else {

      $return['comment'] = 0;
    }

    $return['total'] = $return['default'] + $return['good'] + $return['comment'];
    return $return;
  }

  //글작성일에 따른 포인트 자동 변환
  function autochange_rule($day){

    $return = Array();
    $return['point_good'] = $this->point_good;
    $return['point_nogood'] = $this->point_nogood;
    $return['point_comment'] = $this->point_comment;
    $return['point_defalut_full'] = $this->point_defalut_full;

    $return['set_default'] = $this->set_default;
    $return['set_good'] = $this->set_good;
    $return['set_comment'] = $this->set_comment;

    if ($day >=31 && $day < 91) {//31일에서 90일 사이 5프로 적용

      $return = $this->calculation(5);
    }
    else if ($day >=91 && $day < 181) {//91일에서 180일 사이 10프로 적용

      $return = $this->calculation(10);
    }
    else if ($day >=181) {//181일 이상 15프로 적용

      $return = $this->calculation(15);
    }

    return $return;
  }

  function calculation($per){

    $return = Array();
    $per1 = (float)(1.00 + ($per * 0.01));
    $per2 = (float)(1.00 - ($per * 0.01));

    $return['point_good'] = ceil($this->point_good * ($per1));
    $return['point_nogood'] = ceil($return['point_good'] * (-1.1));
    $return['point_comment'] = ceil($this->point_comment * ($per1));
    $return['point_defalut_full'] = ceil($this->point_defalut_full * ($per1));

    $return['set_default'] = ceil($this->set_default * ($per2));//기본 점수 분포를 지정된 퍼센트로 낮춤
   
    $temp = (100 - $return['set_default'] - $this->set_good - $this->set_comment);
    $temp2 = ceil($temp / 2);
    $temp3 = (2 * $temp2) - $temp;
    $add_set_good = $temp2;
    $add_set_comment = $temp2 - $temp3;

    $return['set_good'] = $this->set_good + $add_set_good;
    $return['set_comment'] = $this->set_comment + $add_set_comment;

    return $return;
  }
}

?>

_______________________________________________________________________

용어는 적절하지 않을수 있습니다.

인기도를 산출하는 방식은

기본점수 와 추천점수 와 코멘트점수의 합으로서 산출합니다.


기본점수는 다음과 같은 방식으로 산출합니다.

추천 한개당 점수 산정 200 (즉 평균 페이지뷰 몇번에 추천한개 일어나는가)
비추천 한개당 점수 산정 -220 (추천한개당 점수에서 패널티를 10프로 적용해서 자동 적용)
코멘트 한개 점수 산정 100 (즉 평균 페이지뷰 몇번에 코멘트한개 일어나는가)
페이지뷰 한개 점수 1 (고정)
기본점수 만점 2000 (추천 코멘트 없이 페이지뷰가 2000이면 기본점수 만점이다라는 뜻)
기본점수 분포 70 전체 인기도 점수중 기본점수를 몇프로로 칠것인가를 지정
기본점수 = (추천점수 합 + 비추천점수 합 + 코멘트점수 합 + 히트수) / 기본점수 만점 * 기본점수 분포
기본점수는 시간이 지날수록 증가하는 값입니다. 그러나 기본점수분포를 넘을수 없습니다.


추천점수는 다음과 같은 방식으로 산출합니다.
추천점수 분포 15 전체 인기도 점수중 추천점수를 몇프로로 칠것인가를 지정
추천점수 = (1 - (전체 페이지뷰 / (추천점수 합 + 비추천점수 합))) * 추천점수 분포
추천점수의 의미는 게시물의 질을 나타냅니다.
추천점수는 시간이 지날수록 감소할수 있는 값입니다.


코멘트점수는 다음과 같은 방식으로 산출합니다.
코멘트점수 분포 15 전체 인기도 점수중 코멘트점수를 몇프로로 칠것인가를 지정
코멘트점수 = (1 - (전체 페이지뷰 / 코멘트점수 합)) * 코멘트점수 분포
코멘트점수의 의미는 게시물의 질을 나타냅니다.
코멘트점수는 시간이 지날수록 감소할수 있는 값입니다.


1개월 미만은 그대로
3개월 미만은 5프로
6개월 미만은 10프로
그이상은 15프로를 적용하여
기본점수 분포를 낮추고, 반대로 추천점수 분포와 코멘트 점수 분포를 자동으로 계산으로 올립니다.



사용법은 해당 클래스를 해당 페이지에서 인클루드 한다음
객체를 생성합니다.

//그누보드 리스트 스킨에서 사용예
//인기도 관련 클래스 인클루드
include_once("$g4[path]/lib/favor_point.lib.php");
$favor_point = new favor_point(200, 100, 2000, 70, 15, 15);

이런식으로........
이것은 페이지에서 딱 한번 실행하면 됩니다.
$favor_point = new favor_point(200, 100, 2000, 70, 15, 15);
여기의 수치에 대한 것은
200 은 추천 하나에 대한 점수입니다.
100 은 코멘트 하나에 대한 점수입니다.
2000 은 기본 점수 만점입니다.
70은 기본점수 분포입니다.
15는 추천점수 분포입니다.
15는 코멘트점수 분포입니다.
마지막 세개의 인자는 합이 100 이어야 하고 모두 양의 정수만 사용해야 합니다.


출력해줄 곳에서는

<? $return = $favor_point->get_favor_point($list[$i]['wr_good'], $list[$i]['wr_nogood'], $list[$i]['wr_comment'], $list[$i]['wr_hit'], $list[$i]['wr_datetime']); ?>
<td>
  <table cellpadding=0 cellspacing=0 border=0 width=81 height=13 background='<?=$board_skin_path?>/img/star_s_bg.gif' title='<?=$return['total']?>%' style='margin: 2 0 2 0;'>
    <tr>
      <td>
        <table cellpadding=0 cellspacing=0 border=0 width=<?=$return['total']?>% height=13 background='<?=$board_skin_path?>/img/star_s.gif'><tr><td></td></tr></table>
      </td>
    </tr>
  </table>
</td>

이런식으로 사용하면 됩니다.


<? $return = $favor_point->get_favor_point($list[$i]['wr_good'], $list[$i]['wr_nogood'], $list[$i]['wr_comment'], $list[$i]['wr_hit'], $list[$i]['wr_datetime']); ?>
이것에 대한 설명은
인자가 순서대로 추천수, 비추천수, 코멘트수, 히트수, 작성일 입니다.
작성일은 date 형식이나 datetime형식이나 관계없습니다.


점수나 분포는 자신에 맞게 설정하여 사용하세요.

파일이 두개가 필요합니다(아닐수도 있지만 전 간단히 하기 위해 두개)

---------------------------------------
main.html
---------------------------------------

<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> New Document </title>
</head>

<body>
<iframe name="menuFrame1" src="menu1.html" marginWidth=0 marginHeight=0 frameBorder=0 scrolling=no style="position:absolute;top:44;left:345;width:150;height:205; visibility:visible; filter:alpha(opacity=85); z-index:5;"></iframe>
<table>
<tr height=100>
    <td width=300></td>
    <td valign=bottom>아래의 콤보박스가 레이어에 가려져보입니다</td>
</tr>
<tr>
    <td></td>
    <td><select name=""><option>SelectBox</option></select></td>
</tr>
</table>
</body>
</html>
---------------------------------------

---------------------------------------
menu1.html
---------------------------------------
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<title>Menu</title>
</head>
<body leftmargin=0 topmargin=0 style="background-color:transparent">
<table width='150' border='0' cellspacing='0' cellpadding='0'>
<tr>
    <td width=100% valign=top>
        <TABLE cellSpacing=1 cellPadding=0 width=100% border=0 style='border:3px solid #1770CD' bgcolor='#4286CE'>
        <tr>
            <td height=5></td>
        </tr>
        <TR>
            <TD style='padding-left:4px;' valign=top height=191>
                <table width=100% border='0' cellspacing='0' cellpadding='0'>
                    <TR>
                        <TD style='padding-left:4px;' height=25><a href="링크1" target="_parent" class='menutop'>메뉴1</A></TD>
                    </tr>
                </table>    
            </TD>
        </tr>
        </table>    
    </td>
</tr>
</table>
</body>
</html>

---------------------------------------


위 파일 두개를 같은 곳에 저장한 뒤 테스트 하시기 바랍니다

분명 셀렉트 박스 위에 레이어가 올라가는걸 알수 있습니다
위에 설명했듯이 자바 애플릿 위에도 잘 올라갑니다
(일반 레이어의 경우 애플릿 경계선으로 완전히 잘려버리죠 ㅡㅡㅋ)

유용한 팁이라 생각하고 올렸으니 상처주는 말은 제발.. ㅡㅡㅋ
(이것도 팁이냐.. 장난하냐 등등.. ㅡㅡ;;)

주의사항:
1. link target은 parent로..(아실듯..)
2. 위 소스에서 아실수 있듯이 셀렉트 박스나 자바 애플릿은 투명도가 먹지 않습니다.

<?
$lotto_arr = array( "$lotto1", "$lotto2", "$lotto3", "$lotto4", "$lotto5", "$lotto6", "$lotto7" );
$cnt = array( "A", "B", "C", "D", "E" );


echo "이번주는 당신입니다..ㅋㅋㅋ<br><br>";

for ( $ii=0; $ii<5; $ii++ )    // 한판에 천원씩, 5천원치 5바퀴 돌리기
{
 echo "$cnt[$ii] 번째<br>------------------------<br>";

 for ( $i=1; $i<8; $i++ )      //  추첨번호 6개와 보너스 1개해서 7바퀴 돌리기
 {
    $out = "T";                // 초기값 설정

    while ( $out == "T" )      // $out 이 "F" 즉, 난수발생된 값이 미중복시 종료
    {
        $tmp = rand( 1, 45 );    // 난수 발생
     
      if ( !in_array($tmp, $lotto_arr) ) { $out = "F"; }  // 추첨번호배열에서
    }                                                      // 방금 얻은 난수값이 있는지 검사

    $lotto_arr[$i] = $tmp;        // 난수발생하여 얻은 값을 배열에 차곡차곡~

    if ( $i <= 6 ) { echo "$i -><font color='red'>$lotto_arr[$i]</font><br>";    }  // 추첨번호 6개
    else          { echo "보너스 -><font color='blue'>$lotto_arr[$i]</font><br>------------------------<br>";    }
 }
}
?>

페이징

인터넷정보2007. 10. 11. 23:27
<?
$PG_this = $_REQUEST[PG_this];

$PG_line = 201;// 전체 라인 수(=전체 멤버 수)
$PG_unit = 10;                // 페이지당 라인수 : 12줄=1페이지
$PG_grup = 10;                // 한 화면당 나타날 페이지 그룹 갯수 : 10개

$PG_tots = ceil($PG_line / $PG_unit); // 전체 페이지 수

$PG_this = $PG_this ? $PG_this:($PG_tots ? 1:0); // 현재 열린 페이지 또는 0(무효) 계산

$PG_strt = $PG_this ? (floor($PG_this/$PG_grup)*$PG_grup+1):0; // 페이지 그룹 시작페이지 수 계산
if($PG_strt >$PG_this) { $PG_strt -= $PG_grup; }

$PG_fnsh = $PG_strt ? ($PG_strt+$PG_grup-1):0; // 페이지 그룹 최종페이지 수 계산
if($PG_fnsh >=$PG_tots) { $PG_fnsh = $PG_tots; }

$PG_frst = ($PG_strt > $PG_grup*2) ? 1:0; // 첫페이지 그룹 1 또는 0(무효) 계산

$PG_prev = ($PG_strt > $PG_grup) ? ($PG_strt -1):0; // 이전페이지 그룹 계산

$PG_next = (($PG_strt+$PG_grup) <= $PG_tots) ? ($PG_fnsh+1):0; // 다음 페이지 그룹 계산

$PG_last = (($PG_strt+$PG_grup*2) <= $PG_tots) ? ($PG_tots):0; // 마지막 페이지 그룹 계산

// 처음 및 이전 페이지 링크 출력
$PG_link .= $PG_frst ? " <a href=".$_SERVER[PHP_SELF]."?PG_this=$PG_frst>처음</a>":"";
$PG_link .= $PG_prev ? " <a href=".$_SERVER[PHP_SELF]."?PG_this=$PG_prev>이전</a>":"";

// 현재 페이지 그룹 리스트 출력
for($i=$PG_strt; $i<=$PG_fnsh; $i++) {
  if($PG_this == $i) { $PG_link .= " <b>$i</b>"; }
  else { $PG_link .= " <a href=".$_SERVER[PHP_SELF]."?PG_this=$i>$i</a>"; }
}

// 다음 및 마지막 페이지 링크 출력
$PG_link .= $PG_next ? " <a href=".$_SERVER[PHP_SELF]."?PG_this=$PG_next>다음</a>":"";
$PG_link .= $PG_last ? " <a href=".$_SERVER[PHP_SELF]."?PG_this=$PG_last>마지막</a>":"";
// 디비에서 현재 페이지 내용 출력하기

echo $PG_link;
?>

안녕하세요~

오늘은 두번째로 올리는 초급용 씨리즈 입니다.

오늘도 초급용 씨리즈냐고 태클 거신다면.. 그래도 초급용 입니다 -_-;;

할 수 없습니다. 아시는 분은 안보셔도 됩니다 초급용입니다 -_-;;

어제는 js를 이용한 form과 관련한 내용이었는데요

오늘은 많은 초급 phper들이 게시판을 이용해서 공부하면서

가장 힘들어하고 어려워 하는 페이징의 원리를 말씀드릴까 합니다.

페이징 : 통상 이렇게 말하는데요 저는 네비게이터 라고 자주 말합니다.

게시판의 목록에 페이지를 넘겨줄 수 있는 번호 링크를 두고 하는 말이죠..

그럼 시작해 볼까요~


제가 수업시간에 네비게이터를 수업하게 되면 자주 써먹는 과제 중에 하나가

주어진 수의 범위가 있을 때
 ex ) 0~9, 10~19, 20~29

x라는 수를 입력 받으면 어느 범위에 속하는지 알아 내는 문제를 냅니다.

※ 정확히 말하자면 범위의 첫 수를 구해내는 문제입니다. (0 ,10, 20)

자! 시간 5분 드립니다 풀어보세요!

1초
2초
3초
5분 끝!

다 푸셨나요 -0-?

왜 저 문제가 페이징 (네비게이터)와 관련있을까?

우리가 통상 php를 이용하여 프로그램을 제작하면 효율성등등 감안해서 많은

부분을 생각하게 됩니다. 하지만 이런건 숙련자들의 몫이죠 초급자는 아무리

강조해도 이런거 생각 못합니다.

그럼 무엇을 가지고 초급자들이 프로그램을 제작 해야할 까요?

무엇을 보여주고 어떻게 보여줄것인가!! 이게 관건입니다.

같이 문제를 풀어보죠

가령 5라는 수가 입력 되었다고 가정하면

(어이 거기 눈돌리지말고~ 잘봐!! 계산하고있지?)

계산하지마세요 계산은 여러분들이 하는게 아니죠? 서버(컴퓨터)가 해주는거에요

우리는 컴퓨터가 계산할 일정한 규칙성(계산식)을 만들어 주면 됩니다.

그럼 젤 먼저 해야될 일! 바로 변수의 선언입니다. 모든 프로그램에 공통적으로

시작할 때 일단 사용할 변수를 선언해 주는게 프로그램을 작성하면서 변수가 꼬인다거나

잘못된 값을 계산한다거나 하는 일 (버그)를 줄여줍니다.

$psize = 10; //수의 범위 크기 입니다.
$x = 5; //입력받은 수입니다.

5가 어느 범위에 들어갈지 우리 머리속에는 이미 인지하고 있지만

논리적으로 계산식을 만드는 것은 꾀 어렵습니다.

그런데요 잘 생각해 보면 문제안에 항상 답이 있다는 거죠~

범위의 첫수 0, 10, 20 을 구하는 식을 만들자면 5, 15, 25라는 수가 있을 때

일반적인 수학을 생각하면 절대 답 없습니다.

5를 주어진 수의 범위로 일단 나누고 봅시다 0보다는 5가 크니 빼버리면 되겠지만

15가 입력된다면 15를 또 빼줘도 0이 되지 10이되지는 않겠죠?

5-5=0
15-15=0
절대 자기 자신을 빼버려서는 답이 없다!!

그래서 일단 나눠봅시다

5/10 = ? 0.5
15/10 = ? 1.5
25/10 = ? 2.5

음.. 뭔가 비슷한 모양이 나올거 같군요

왜 나누냐고요? 더하거나 곱하면 수거 더 커지지 작아 지지는 않겠죠?

그래서 나누어 봤습니다.

그럼 저렇게 구해진 값을 이제 변수로 지정해 봅시다.

$start_num = $x / $psize;

일단 이런식이 만들어 지겠네요

0.5 , 1.5, 2.5 이렇게 나온 값을 이제 php 내장 객체인 floor를 이용해서

소수점을 버려 봅시다!

$start_num = floor($x / $psize);

하니까 x의 값이 달라질 때 마다 0, 1, 2 라는 수를 start_num이 가지게 되겠죠?

그런데~ 여기서 끝난게 아닙니다. 0, 10, 20 이렇게 되도록 하고 싶은데요

저런 수에다가 주어진 범위의 크기만큼 곱셈을 하면 어떻게 될까요?

그렇습니다~

$start_num = floor($x / $psize) * $psize;

0은 아무리 큰수를 곱해도 0이고 1곱하기 10은 10, 2곱하기 10은 20이니

우리가 원하는 범위의 첫번째 수를 구하는 것을 해결했습니다.

그럼 저 공식이 왜 필요한가?

보여주는 숫자를 보니 1부터 시작하는데... 페이지 번호는 0번부터라니..

이상하자나요~ 하고 질문하는 학생 꼭 있습니다!!

그건 바로 배열과 관련된 부분과 물질수의 10진수와 수학의 10진수는

항상 1의 갭이 있다는걸 생각해야 합니다.

우리가 통상 사용하는 물질수의 10진수는 1,2,3,~10 이 겠지만

수학에서의 10진수는 0~9까지의 수를 말합니다.

그럼 배열은? 배열에서 자동으로 부여되는 (php를 포함한 특정 언어만) 인덱스 key는

0부터 시작합니다. 물론 10진수고요.


자 이제 1단계 과제가 해결되었습니다.

※ 2단계 과제
주어진 글의 개수가 534개다 페이지당 10개씩 보여준다면
페이지는 총 몇개의 페이지가 되는가?

음.. 어렵나요? 쉽죠?

10개씩 보여준다면야 당연히 10으로 나누면 총 페이지의 갯수가 나오는데요

여기서 놓치기 쉬운 부분이 마지막에 남는 글의 갯수랍니다.

534/10=? 53.4

그럼 페이지 수가 53.4개라는건데 소수점은 어떻게 해주는게 좋을까요?

그렇습니다~ 바로 소수점 무조건 올림인 ceil 함수를 이용하여

올림수인 54페이지를 만들어 줘야 마지막에 남는 0.4페이지분량의 글을

모두 보여줄 수 있다는거죠


그럼 총 페이지의 개수도 구했습니다.

이제 해야할 마지막 관문!!!

※ 문제3 그럼 한 화면에 10개씩 페이지 번호를 보여준다면
이런 단위블럭이 몇개가 나오나요?

위 문제와 유사하죠? 그렇습니다 3번문제가 요구하는 것은

네비게이터의 이전 , 다음 링크를 만들기 위한 조건으로 사용될 일정한 값을

구하기 위한 문제 입니다.

그럼 실질적 아래 예제 코드를 이용해서 확인해 복습해 봅시다.


<?
$start = $_GET[start];
$total = 534;//총 레코드수
$scale = 10;//페이지당 출력 레코드수
$page_scale = 10; // 화면당 출력할 페이지 수
if(!$start) $start = 0;//시작 페이지 번호가 없을경우 0

$total_page = ceil($total/$scale);//총 페이지수
$page = floor($total_page/$page_scale);//단위블럭페이지수
$n_page = floor($start/$page_scale);//현재 단위블럭 페이지번호

if($n_page > 0){
//이전 링크 출력 조건 현재단위블럭 페이지 번호가 0보다 클경우
    $p_start = ($n_page-1)*$page_scale;
//현재 단위블럭 페이지 -1 * 단위블럭 페이지 출력수(page_scale)
    $link = "<a href='".$_SERVER[PHP_SELF]."?start=${p_start}'>";
    $link .= "이전";
    $link .= "</a>";
    echo $link." ";
}
$is = $n_page*$page_scale;//단위블럭 페이지 시작번호 구하기 현재 페이지 번호를 이용하여 현재 단위블럭 페이지 번호를 구하고 그 값을 이용하여 단위블럭 페이지 출력수를 곱한 값
for($i=$is; $i < $is+$page_scale; $i++){
//i는 현재 단위블럭 페이지 번호*단위블럭 페이지 출력수 부터 시작하고 i는 단위블럭 페이지 출력수를 더한 값만큼만 반복하도록 지정
    if($i < $total_page){//i가 총 페이지수 보다 작을 동안만 출력하기 위한조건
        $link = "<a href='".$_SERVER[PHP_SELF]."?start=${i}'>";
        $link .= $i+1;//start값이 i로 지정됨으로 화면상 출력기준을 1부터 시작하는 10진수로 맞추기 위해 +1을 연산
        $link .= "</a>";
        echo $link." ";
    }
}

if($n_page < $page){//현재 단위블럭 페이지번호 보다 총 단위블럭 페이지 수가 작을 경우에만 다음 링크 출력
    $link = "<a href='".$_SERVER[PHP_SELF]."?start=${i}'>";//i는 상단 for문에서 이미 마지막 페이지 start번호보다 +1한 값을 가지고 있기 때문에 i를 그냥 출력함
    $link .= "다음";
    $link .= "</a>";
    echo $link;
}

?>



어떠셨나요?

선행 학습내용을 잘 읽어 보신분이라면 쉽게 이해가 되었을 것입니다.

선행 학습내용만 잘 이해한다면 어떠한 언어로로 페이징은 만들어 낼 수 있습니다.

코드가 중요한게 아니라 바로 로직 or 알고리즘이 중요하다는거 잊지맙시다.

반갑습니다.

오늘도 여지없이 돌아온 초급용 입니다.

그간 업무가 바쁜관계로.. (-_ㅡ;  전혀 죄송하지 않습니다.

세번째 초급용 함수와 클래스의 기본 개념에 대해서 써볼까 합니다.

그 첫번째 시간으로 함수에 대해서 알아 봅시다..

뭐 앞서 제가 이런 글을 쓰는 이유를 모르시는 분들은 js편을 먼저 보시기 바랍니다.

초급용이라 아시는 분은 안보셔도 됩니다. 태클은 영구반사 아이템을 사용하겠습니다.

프로그램을 제작 하다보면 많은 코드의 양때문에 혹은 반복적으로 발생되는

코드때문에 우리는 아주 열심히 잘 하는?, 안가르쳐 줘도 타고나는 재주?를 여지없이

발휘합니다. 궁극의 Ctrl + C & V 신공 (-_ㅡ)))

하지만 이런거 말고 좀더 쉬운게 없을까요? 일의 효율성을 높일 수 있는 궁극적인

해결책 그 첫번째 방법이 바로 사용자 정의 함수 (user function)! 음.. 사용자 정의

함수라는 명칭이 있는지 잘 모르겠군요 ^^; 하지만 저는 그렇게 부릅니다.

언어를 제가 개발한 언어 개발자가 아니기 때문에 만들어 놓은 문법에 따라 언어를

사용하는 사용자라는 개념에서죠. 아무튼 함수의 생성에 관한 이야기 입니다.

직접적인 코드도 있지만 개념적인 설명이 많기 때문에 다소 지겨울 수도 있습니다.

책을 통한 설명이나 개시판을 통한 학습을 하다 보면 많은 초급 개발자분들이 함수를

어떻게 만들어야 할까에 대해서 많은 고민을 하게 됩니다.

쉬운 예로

자 오늘은 페이징로직을 이용한 함수를 만들어 봅시다~

이러면 페이징을 배웠어도 어떻게 함수로 만들어야 할지 또 함수를 만들면 어떻게

함수가 동작되는가, 함수를 사용하면 어떤 이점이 있는가 등등 별의별 잡다한 생각을

하면서 결국

function paging(){
 |
}

커서를 저 위치에 놓고 궁리만 하고 있죠 -_-;;

결론부터 말씀드리면 함수를 쉽고 빨리 만들기 위해서는 먼저 기능구현부터 해야합니다.

함수부터 만들겠다고 function 함수명() 이렇게 해놓으면 다음에 뭘 해야 할지 솔직히

감 안오죠. 수십번을 만들어도 마찮가지입니다. 수백번을 만든다면 가능해질 문제이긴

합니다만.. 우리에게는 그렇게 많은 시간이 없다는것이죠.

선행 학습 내용으로 함수는 어떻게 동작되는가를 알아야 겠습니다.

php해석기(parser) 는 function을 만나게 되면 일단 메모리에 로드시켜 놓습니다.

변수를 선언했을 때 메모리의 일정 공간을 선언된 변수명으로 할당받는 것과 같은

이치 입니다. 선언된 변수와 함수는 언제든 재사용 가능하다는거 아시겠죠?

다만 php의 특성상 파일단위 프로그램이 종료되면 모든 변수와 함수는

언로드(메모리에서 삭제) 된다는 것을 유의 하시기 바랍니다.

특정 기술인 공유메모리, 세마포어 등을 이용하면 타 사용자간의 데이터 공유도
 
가능합니다만.... C언어를 먼저 공부를 해야만 메모리 접근,제어에 이해가 될 것입니다.

그럼 실질적인 예제를 통해서 함수를 만드는 방법을 읶혀 보겠습니다.

※ 기능구현 ( 구구단 3단)

아주 고전적인 예제중 구구단 만들기라는 예제가 있습니다.

아주 오래된 예제이지만 현재도 기초수업에 사용되는 이유는 각종 제어문을

다양하게 사용함으로서 문법과 로직을 효과적으로 이해하는 좋은 예제이기 때문입니다.

구구단 출력에 관한 코드는 별도의 주석을 첨부하지 않겠습니다.

$dan = 3;
$exp = 1;
$summary = 0;
while($exp < 10){
    $summary = $dan * $exp;
    echo $dan .' * '. $exp .' = '. $summary .'<br />';
    $exp++;
}

쉽죠? 이정도는 알고 계시리라 생각하고 진행 하겠습니다.

기능은 완벽했습니다. 더이상 나무랄데 없이 정확한 결과가 출력되었습니다.

우리가 원하는 기능이 구현된 상태에서 함수를 제작하겠습니다.

일단 아무 생각하지말고 function 부터선언합시다!!

※ 함수선언

function gugudan(){
    $dan = 3;
    $exp = 1;
    $summary = 0;
    while($exp < 10){
        $summary = $dan * $exp;
        echo $dan .' * '. $exp .' = '. $summary .'<br />';
        $exp++;
    }
}

음.. 뭔가 좀 되는 분위기!! 어이 수업에 불만있냐 눈돌리지마라

5분만 집중하면 1년뒤 연봉이 달라진다! ㅡ_-?? (진짜?)

그런데 이제 두번째 항목으로 생각해야 할 문제가 발생 했습니다.

이렇게 해놓으면 항상 gugudan함수를 호출할 때 마다 3단만 출력된다는게

불만입니다. 이렇게 할 거 같으면 뭐하러 함수를 쓴단 말인가 그냥 복사&붙이기신공을

쓰는거랑 뭐가 다르단 말인가?

그렇습니다~

그래서 나온게 매개변수 입니다.

함수를 만드는데 있어서 결정적으로 프로그램의 유기적 흐름을 만들기 위한 방법!

그런데 이 매개변수를 하기전에 먼저 전역변수와 지역변수에 대한 개념이 잡혀 있어야

합니다.

전역변수
<?
$toto ="전역변수다~";
$로또 = "이것도 전역변수다~";
?>

어? 변수명을 한글로???

가능합니다 ^^ php만이 가능한 기능중에 하나죠

하지만 성능적으로는 안좋습니다. 이유는 1byte처리와 2byte처리에 있습니다.

아무튼 여러분은 여지껏 전역변수만을 사용했다면 이제는 지역변수도 알아야 합니다.

<?
$toto = "전역변수";
echo $toto;
function act(){
    echo $toto;
    $toto = "지역변수";
    echo $toto;
}
?>

아니 변수명이 같자나? 그런데 엄격히 말하면 함수 안의 변수와 함수 밖의 변수는

시스템에서 다르게 인식합니다.

함수 안에서 사용하는 변수는 지역변수이기 때문에 두번째 echo는 아무것도 출력하지

못합니다.

그럼 매개변수는 뭐에요????

매개변수는 이런 지역변수와 전역변수간의 특정 data를 주고 받는 통로이자 함수 내에서

사용할 변수를 미리 선언해 놓은 것입니다. 어렵나요? 아래 예제를 보시죠~!

<?
$toto = "나 전역변수!!";
function act ( $gaga ) {//변수 $gaga 가 바로 매개 변수입니다.
    echo $gaga;
}
act ( $toto ); /// 문제의 핵심 함수를 호출할 때!!
?>
act라는 함수를 호출할 때 gaga변수가 받아야 할 정보를 가지고 있는 $toto변수를

지정해 줌으로써 toto변수의 값을 gaga변수가 가지게 되는 것이죠.

음.. 그럼 이제 매개변수를 이용해서 함수를 호출할 때 지정해준 단의 구구단을

출력해 봅시다.

※ 매개변수

<?
function gugudan($dan){
    $exp = 1;
    $summary = 0;
    while($exp < 10){
        $summary = $dan * $exp;
        echo $dan .' * '. $exp .' = '. $summary .'<br />';
        $exp++;
    }
}
gugudan( 4 );//$dan 변수가 받을 값을 직접 지정
?>

이런 코드가 되었습니까?

아니 매개 변수 자리에 그냥 4를 지정했네요?

맞습니다 함수를 호출할 때에는 매개변수의 자리에 데이터를 직접 지정해도 되고

혹은 선언된 변수를 지정해도 됩니다.

이렇게 함으로써 여러분은 이제 입력되는 수에 따라 해당 수의 구구단을 출력하는

함수를 만들었습니다.

그럼 꼭 매개변수를 써야만 함수 안과 밖의 특정 값을 주고 받을 수 있습니까?

아닙니다. 매개변수 이외에도 전역화(global) 라는 개념이 있습니다.

global로 선언된 변수들은 함수 안밖에 구애받지 않고 사용할 수 있습니다.

다시 말하면 전역변수, 지역변수의 개념이 아닌 하나의 변수를 공통적으로

사용하는 방법입니다.

※ global

<?
function gugudan(){
    global $dan;
    $exp = 1;
    $summary = 0;
    while($exp < 10){
        $summary = $dan * $exp;
        echo $dan .' * '. $exp .' = '. $summary .'<br />';
        $exp++;
    }
}
$dan = 4;
gugudan();
?>

$dan변수를 함수 내에서 global로 선언하면 더이상 $dan변수는 지역변수가 아닌

전역화 되어서 함수 안,밖에서 동일하게 취급받습니다.

함수를 호출하기 전에 $dan 변수에 4를 지정했기 때문에 정상적으로 4단이 출력되는

것을 볼 수 있습니다. 전역화도 마찮가지로 하나의 변수만을 쓰는것은 아닙니다.

global $변수명, $변수명, $변수명; 이런 형식으로 쓸 수 있습니다.


이 예제에서 사용되지 않은 return 이라던가 복수의 값을 전달하는 방법등은

여러분이 직접 생각해 보시기 바랍니다. (복수의값 리턴 힌트는 배열입니다.)

아시다 싶이 매개변수라는 것은 한개만을 사용할 수 있는 것은 아닙니다.

함수 내부적으로 어떤 데이터를 처리할 것이냐에 따라 매개변수는 여러개가 될

 수 있습니다.

이제 함수를 만들기 위한 방법을 정리를 해보죠.

1. 기능구현.

2. 함수선언.

3. 자료를 입력받을 것인가? 내부적으로 처리할 것인가?

4. 매개변수를 사용하면 몇개를 사용할 것인가?

5. 실행 결과를 함수내에서 출력할 것인가? 호출한 곳으로 되돌려 줄것인가?

1,2 항목은 일반적 진행이면 3~5항목은 여러분이 즉 함수를 만드는 사람이

선택해야 할 문제 입니다.

이번 함수 만들기편에서 많은 부분을 다루고 싶었지만 그렇게 되면 너무 깊이 들어

가게 됨으로 본래의 취지인 초급용 이상의 내용을 다루게 될 것 같아서 여기에서

마무리 짖겠습니다.

P.S) 함수를 만들 때 유의사항

1. 반복적으로 사용되는 내용인가?

2. 단편화 or 모듈화 되었는가?

위 두가지 항목은 함수를 반복적으로 만드는 연습을 하다보면 자연스레

깨우치게 될 것입니다. 다만 노파심에.. 고운하루 되시길 빕니다.

사용자 삽입 이미지
한 대의 PC에는 적게는 1만개, 많게는 수십 만개의 파일이 들어 있습니다. 이 파일들은 운영체제 또는 프로그램의 일부로서 없어서는 안 되는 역할을 하기도 하며, 사용자가 작성한 문서와 사진은 땀과 노력의 결정체입니다. 반대로 PC의 건강을 해치는 바이러스 감염 파일, 트로이목마는 애써 모은 파일을 잃어버리게 하기까지 하며, 아무 일도 하지 않고 자리만 차지하는 쓰레기 파일도 적지 않습니다. 중요한 파일은 소중하게 관리해야 하지만 악성 또는 쓰레기 파일은 치료하거나 바로 지워 PC의 건강을 지켜야 합니다.

이런 파일의 성격을 쉽게 알 수 있도록 나타내는 꼬리표가 바로 확장자입니다. 하지만 대부분의 사용자가 쓰는 윈도우 운영체제는 옵션을 고치지 않으면 파일 확장자를 숨기고 직접 파일을 실행할 수 있는 프로그램과 연결시켜 특징을 쉽게 알 수 없는 문제점이 있습니다. PC를 건강하게 관리하는 운영체제 관리의 기본으로서 이번 시간에는 유명한 확장자와 용도를 살펴보도록 하겠습니다. 파일의 확장자를 보고 용도를 확인하는 것은 효율적인 파일 관리의 기본이자, 갑자기 어떤 파일이 PC에 생겼을 때 ‘어머! 바이러스야~’라며 호들갑을 떨지 않게 하는 비결입니다.

확장자를 어떻게 하면 볼 수 있나?

현재 주력 운영체제인 윈도우 XP는 기본적으로 파일을 바로 열어볼 수 있는 연결 프로그램을 설치했을 때 파일 확장자를 숨깁니다. 그밖에 윈도우 폴더를 비롯한 시스템 폴더와 핵심 시스템 파일을 함부로 보여주지 않습니다. 그래서 이들 파일의 확장자와 내용을 보려면 옵션을 조금 손대야 합니다.

사용자 삽입 이미지

① 윈도우 탐색기 또는 내 컴퓨터 창을 엽니다. 연결된 프로그램이 있는 경우 파일 확장자가 보이지 않는 것을 알 수 있습니다.

사용자 삽입 이미지

② 도구->폴더 옵션 메뉴를 클릭해 폴더 보기 옵션을 수정합니다.

사용자 삽입 이미지

③ ‘보기’ 탭을 열고 중간 부분의 ‘보호된 운영체제 파일 숨기기’, ‘알려진 파일 형식의 파일 확장명 숨기기’ 체크를 끈 뒤 ‘확인’ 버튼을 누릅니다. 이 옵션을 끄면 윈도우 시스템 파일이 나타나며, 모든 파일의 확장자를 연결 프로그램에 관계 없이 볼 수 있게 됩니다.

사용자 삽입 이미지

④ 다시 윈도우 탐색기를 보면 모든 파일 이름 뒤에 확장자가 붙는 것을 알 수 있습니다. 이 옵션을 켜면 파일 이름을 고칠 때 확장자까지 지워지지 않도록 주의해야 합니다.

운영체제, 시스템 관련 파일 확장자

DOS 또는 윈도우 운영체제는 프로그램을 실행하는 열쇠가 되는 실행 파일, 실행파일을 보조해 여러 명령과 파일 실행을 한 번에 하는 배치파일, 그 밖의 윈도우용 보조 파일, 운영체제 시스템 파일, 환경 설정 자료의 모임입니다. 이 파일은 잘못 실행하거나 지우면 운영체제와 프로그램에 문제가 생기거나 바이러스/웜에 감염되기 때문에 항상 주의를 기울여야 합니다. 시스템 파일은 지울 때 주의해야 하고, 실행 파일, 배치파일은 수상한 것은 절대 실행하지 말고 바이러스 백신으로 확인해야 합니다.


확장자 용도 주요 프로그램
EXE 실행 파일 윈도우, DOS
COM DOS용 실행파일 MS-DOS
BAT 배치(Batch) 파일 MS-DOS
LNK 윈도우 바로가기 윈도우
MSI 윈도우 인스톨러 설치 파일 윈도우, 윈도우 인스톨러
CPL 윈도우 제어판 파일 윈도우
DLL 동적 링크 라이브러리 윈도우
CMD 윈도우 NT/2000/XP용 명령 파일 윈도우
INF 드라이버, 소프트웨어 설치 정보 윈도우
INI 소프트웨어 환경설정 파일 윈도우
PIF 프로그램 정보파일 윈도우
REG 윈도우 레지스트리 윈도우
SYS DOS/윈도우용 시스템 파일 MS-DOS, 윈도우
DRV DOS/윈도우용 드라이버 파일 MS-DOS, 윈도우
OCX 액티브X(ActiveX) 컨트롤 윈도우
AX 윈도우용 코덱 윈도우 미디어 플레이어
ACM 윈도우용 코덱 윈도우 미디어 플레이어
TTF 윈도우용 트루타입 글꼴 윈도우
FON 윈도우용 기본 글끌 윈도우

문서, 사무, 개발 관련 파일
여러 가지 글이 적힌 문서, 보고서와 수치 자료가 담긴 사무용 파일, 프로그래머의 땀과 노력이 담긴 프로그램 소스 파일은 비록 크기는 작지만 제작자의 정신 노동의 산물입니다. 그렇기 때문에 이런 파일은 운영체제를 새로 설치하거나 PC를 업그레이드할 때 가장 먼저 백업해야 할 것이 됩니다. 엑셀, 비주얼 베이식 스크립트(VBS) 등 몇몇 파일은 바이러스의 공격 대상이 되기도 하지만 나머지 파일은 기본적으로 바이러스 감염의 위험이 없기 때문에 처음 보는 문서 파일이 PC에 보인다고 크게 걱정하지 않아도 됩니다.

확장자 용도 주요 프로그램
TXT 텍스트 문서 메모장(윈도우)
DOC 마이크로소프트 워드 문서 MS워드, 워드패드
HWP 한글과컴퓨터 한글 문서 포맷 한글 2005/2007
PDF 어도비 어크로뱃 문서 어도비 리더, 어도비 어크로뱃
HTM HTML 웹 문서 인터넷 익스플로러
HTML HTML 웹 문서 인터넷 익스플로러
C C 소스 파일 터보C, 비주얼 스튜디오
CPP C++ 소스 파일 터보C++, 비주얼 스튜디오
BAS 베이식 소스 파일 비주얼 스튜디오
PAS 파스칼/델파이 소스 파일 델파이
XLS 마이크로소프트 엑셀 파일 MS 엑셀
PPT 마이크로소프트 파워포인트 문서 MS 파워포인트
ASM 어셈블리 소스 파일 비주얼 스튜디오
CAP 이야기 갈무리(캡처) 문서 이지패드, 한글2005
CDB 마이크로소프트 액세스 데이터베이스 MS 액세스
CHM 컴파일 HTML(도움말) 파일 윈도우
DBX 아웃룩 익스프레스 메일 데이터 아웃룩 익스프레스
EML 아웃룩, 아웃룩 익스프레스용 메일 파일 아웃룩, 아웃룩 익스프레스
EPS 포스트스크립트(PS) 문서 고스트스크립트
PS 포스트스크립트(PS) 문서 고스트스크립트
FOR 포트란 소스 파일 메모장
GUL 삼성전자 훈만정음 문서 포맷 훈민정음
H C, C++용 헤더(Header) 정의 파일 비주얼 스튜디오, 터보C
HLP 범용 도움말 파일 윈도우
JAR 자바(JAVA) 압축 데이터 자바유틸
JS 자바스크립트 메모장
JAVA 자바(JAVA) 소스 파일 메모장
LWD 로터스워드 문서 로터스워드
CNT 윈도우 도움말 윈도우
MDB 마이크로소프트 액세스 데이터베이스 MS 액세스
PHP PHP 스크립트 메모장
ASP 마이크로소프트 ASP 스크립트 메모장
RTF 리치 텍스트 포맷 문서 워드패드, MS워드
URL 인터넷 익스플로러 즐겨찾기 인터넷 익스플로러
VBS 비주얼베이식 스크립트 파일(VB스크립트) 비주얼 스튜디오, MS 엑셀
CGI CGI 스크립트 파일 메모장
RC C, C++용 리소스 스크립트 비주얼 스튜디오
XML XML 웹 문서 인터넷 익스플로러

압축, CD/DVD 이미지 관련 확장자

인터넷으로 주고 받는 대부분의 파일은 압축을 해 주고 받기 쉽게 만들고, 용량을 줄입니다. 하지만 압축 프로그램 종류는 많고 용도가 조금씩 다르기 때문에 한 두 가지 압축 파일 규격만 안다면 때때로 낭패를 보기 쉽습니다. CD와 DVD의 자료를 한 데 묶어 파일 형태로 만든 이미지 파일 또한 어떤 프로그램을 써야 원래대로 되돌릴 수 있는지 모르면 발만 동동 구르게 됩니다. 압축 파일은 때때로 바이러스/웜에 감염된 파일을 숨기는 용도로 쓰이지만 압축을 풀고 바로 파일을 실행하지 않거나 바이러스 검사를 제대로 해주면 별 문제가 되지 않습니다.


 

확장자 용도 주요 프로그램
TXT 텍스트 문서 메모장(윈도우)
DOC 마이크로소프트 워드 문서 MS워드, 워드패드
HWP 한글과컴퓨터 한글 문서 포맷 한글 2005/2007
PDF 어도비 어크로뱃 문서 어도비 리더, 어도비 어크로뱃
HTM HTML 웹 문서 인터넷 익스플로러
HTML HTML 웹 문서 인터넷 익스플로러
C C 소스 파일 터보C, 비주얼 스튜디오
CPP C++ 소스 파일 터보C++, 비주얼 스튜디오
BAS 베이식 소스 파일 비주얼 스튜디오
PAS 파스칼/델파이 소스 파일 델파이
XLS 마이크로소프트 엑셀 파일 MS 엑셀
PPT 마이크로소프트 파워포인트 문서 MS 파워포인트
ASM 어셈블리 소스 파일 비주얼 스튜디오
CAP 이야기 갈무리(캡처) 문서 이지패드, 한글2005
CDB 마이크로소프트 액세스 데이터베이스 MS 액세스
CHM 컴파일 HTML(도움말) 파일 윈도우
DBX 아웃룩 익스프레스 메일 데이터 아웃룩 익스프레스
EML 아웃룩, 아웃룩 익스프레스용 메일 파일 아웃룩, 아웃룩 익스프레스
EPS 포스트스크립트(PS) 문서 고스트스크립트
PS 포스트스크립트(PS) 문서 고스트스크립트
FOR 포트란 소스 파일 메모장
GUL 삼성전자 훈만정음 문서 포맷 훈민정음
H C, C++용 헤더(Header) 정의 파일 비주얼 스튜디오, 터보C
HLP 범용 도움말 파일 윈도우
JAR 자바(JAVA) 압축 데이터 자바유틸
JS 자바스크립트 메모장
JAVA 자바(JAVA) 소스 파일 메모장
LWD 로터스워드 문서 로터스워드
CNT 윈도우 도움말 윈도우
MDB 마이크로소프트 액세스 데이터베이스 MS 액세스
PHP PHP 스크립트 메모장
ASP 마이크로소프트 ASP 스크립트 메모장
RTF 리치 텍스트 포맷 문서 워드패드, MS워드
URL 인터넷 익스플로러 즐겨찾기 인터넷 익스플로러
VBS 비주얼베이식 스크립트 파일(VB스크립트) 비주얼 스튜디오, MS 엑셀
CGI CGI 스크립트 파일 메모장
RC C, C++용 리소스 스크립트 비주얼 스튜디오
XML XML 웹 문서 인터넷 익스플로러

사진 관련 확장자

디지털 카메라가 널리 퍼지고 인터넷으로 주고 받는 정보의 상당수가 이미지 형태가 되면서 사진/이미지 관련 확장자 또한 기억해두면 좋은 정보가 되고 있습니다. 흔히 쓰는 사진 파일은 흔히 쓰는 사진 뷰어 프로그램으로 열 수 있지만, 요즘 인기를 끌고 있는 디지털 SLR 카메라를 쓴다면 확장자를 반드시 기억해야 낭패를 보지 않습니다. 사진 정보를 그대로 저장하는 RAW 규격은 카메라마다 다르기 때문에 파일 확장자를 보고 어떤 카메라에서 찍었는지 알지 못하면 편집하는 데 어려움을 겪을 수 있기 때문입니다.


확장자 용도 주요 프로그램
BMP 비트맵 이미지 그림판, 포토샵, ACDSee
JPG JPEG 압축 이미지 그림판, 포토샵, ACDSee
JPEG JPEG 압축 이미지 그림판, 포토샵, ACDSee
GIF 컴퓨서브 GIF, 애니메이션 GIF 그림판, 포토샵, ACDSee
PCX 페인트브러시 비트맵 포토샵, ACDSee
PSD 포토샵 작업 이미지 포토샵, ACDSee
TIF 태그 이미지 파일(비압축) 포토샵, ACDSee
TIFF 태그 이미지 파일(비압축) 포토샵, ACDSee
RAF 후지필름 RAW 사진 파일 포토샵, ACDSee
ORF 올림푸스 RAW 사진 파일 포토샵, ACDSee,
올림푸스 스튜디오
CRW 캐논 RAW 사진 파일 포토샵, ACDSee,
캐논 디지털 프로페셔널
RAW 일반 RAW 파일(펜탁스, 파나소닉, 라이카 등) 포토샵, ACDSee
SCR 윈도우 화면보호기 윈도우
NEF 니콘 RAW 사진 파일 포토샵, ACDSee, 니콘캡처
SRF 소니 RAW 사진 파일 포토샵, ACDSee
CR2 캐논 RAW 사진 파일 포토샵, ACDSee
캐논 디지털 프로페셔널
DCR 코닥 RAW 사진 파일 포토샵, ACDSee
ERF 엡손 RAW 사진 파일 포토샵, ACDSee
NRW 코니카-미놀타(소니) RAW 사진 파일 포토샵, ACDSee
PEF 펜탁스 RAW 사진 파일 포토샵, ACDSee
DNG 어도비 디지털 네거티브 이미지 포토샵
ICO 표준 아이콘 파일 포토샵, ACDSee
JP2 JPEG 2000 규격 압축 이미지 그림판, 포토샵, ACDSee
PNG GIF 대체용 퍼블릭 네트워크 그래픽 이미지 파일 ACDSee, 포토샵
PSP 페인트샵 프로 작업 이미지 페인트샵 프로, ACDSee
TGF 타가(Targa) 이미지 파일 포토샵, ACDSee
WMF 윈도우 메타파일 포토샵, ACDSee, 그림판
CDR 코렐드로우 벡터 이미지 코렐드로우
PIC 매킨토시용 PICT 이미지 파일 ACDSee, 포토샵
SWF 플래시/쇽웨이브 오브젝트 파일 인터넷 익스플로러

멀티미디어 파일 확장자

요즘 PC 사용자들은 PC를 영화를 보고 음악을 즐기는 데 자주 씁니다. 그만큼 PC가 집안의 엔터테인먼트 기기를 대신하고 있다는 뜻이기도 합니다. 음악과 영상 기술이 발전하면서 새로운 멀티미디어 파일 규격이 속속 선보이고 있어 정보 습득을 게을리하면 어떤 프로그램으로 영화 또는 음악을 즐겨야 하는지 알 수 없게 됩니다. 흔히 쓰지 않는 멀티미디어 파일을 봤을 때 당황하지 말고 확장자를 보고 용도와 재생 프로그램을 찾는 습관을 들이면 어디서나 PC 전문가 소리를 들을 수 있습니다.


확장자 용도 주요 프로그램
AVI 마이크로소프트 동영상 파일 윈도우 미디어 플레이어,
곰플레이어
MPG MPEG-1 압축 동영성 윈도우 미디어 플레이어,
곰플레이어
MPEG MPEG-1 압축 동영상 윈도우 미디어 플레이어,
곰플레이어
ASF 윈도우 스트리밍 동영상 윈도우 미디어 플레이어,
곰플레이어
WMA 윈도우 미디어 오디오 윈도우 미디어 플레이어
WMV 윈도우 미디어 비디오 윈도우 미디어 플레이어
MOV 애플 퀵타임 오디오/비디오 애플 퀵타임
RA 리얼네트웍스 리얼오디오 리얼플레이어
RM 리얼네트웍스 오디오/비디오 리얼플레이어
MP2 MPEG-1 오디오 레이어 2 압축 음원 윈도우 미디어 플레이어,
윈앰프
, 리얼플레이어
MP3 MPEG-1 오디오 레이어 3 압축 음원 윈도우 미디어 플레이어,
윈앰프
, 리얼플레이어
WAV 비압축 웨이브 음원 윈도우 미디어 플레이어,
윈앰프
, 리얼플레이어
MID MIDI 악기 데이터 윈도우 미디어 플레이어
SMI 동적 멀티미디어 언어 파일(자막 파일) 곰플레이어, 퀵타임
윈도우 미디어 플레이어
CDA CD 오디오트랙 윈도우 미디어 플레이어
AAC MPEG-2 오디오 파일 파워DVD, 윈앰프
AC3 돌비디지털(AC3) 규격 멀티채널 오디오 파일 파워DVD, 윈DVD
ASX 인터넷 스트리밍 방송 주소 데이터 파일 윈도우 미디어 플레이어
M3U 표준 MPEG 파일 재생 목록 윈도우 미디어 플레이어
PLS 윈앰프 전용 MPEG 파일 재생 목록 윈앰프
OGG OGG Vorbis 오픈 소스 오디오 파일 윈앰프
GI 베리타스 프리모CD/DVD 글로벌 이미지 레코드나우 맥스

그 밖의 파일

PC에는 여러 가지 의미를 지닌 파일 이외에 더 이상 쓰지 않는 임시 파일, 프로그램 작동 상황을 알려주는 로그 파일, 프로그램의 일부지만 정체가 모호한 여러 데이터 파일이 존재합니다. 하드디스크 용량이 모자랄 때 이런 파일은 삭제 1순위가 되지만 몇몇 파일은 쓰레기가 아닌 소중한 자료가 되기도 하니까 지우기 전에 파일의 정체를 알아보는 것이 좋습니다.

확장자 용도 설명
LOG 로그 데이터 파일  프로그램 및 PC의 작동 상황을 기록하는 문서 파일. 지워도 무방하나 문제가 생겼을 때 확인하면 큰 도움이 됨.
TMP 임시 파일  작업용으로 잠시 쓰고 남은 파일. 작업이 끝난 뒤 삭제해도 문제 없음.
$$$ 임시 파일  작업용으로 잠시 쓰고 남은 파일. 작업이 끝난 뒤 삭제해도 문제 없음.
BIN 바이너리 파일  다른 프로그램의 데이터용으로 쓰는 파일. 연결 프로그램을 알기 전에는 함부로 지우지 않는 것을 권장함.
ROM BIOS 파일 또는 게임팩 롬파일  롬 형식의 게임 에뮬레이터의 게임 데이터가 많으나 메인보드 BIOS도 이 확장자