개발일정에 치여 도무지 블로깅 할 시간이 안나 미치겠네요. 새로운 것 정리하기는 힘들고 자주 사용하고 있는 Ajax 패턴 정리해 봅니다.
Ajax 구현할 때는 거의 jQuery 를 활용하고 있습니다. 모바일 웹 구현할 때 네이티브 앱과 같은 UX 를 위해 Ajax 를 많이 사용하게 됩니다.
  • 로그인
로그인은 보통 화면에서 폼 값을 입력한 후 해당 값과 함께 ajax 호출합니다.
호출된 액션에서 로그인 관련 인증 및 예외처리 프로세스를 돌인 후
인증 상태에 따라 결과 값을 출력합니다.
출력된 값에 따라 로그인 페이지에서 경고를 띄우든 다음 페이지로 진행하든 처리하죠.
ajax 루틴을 돌고 있을 때 사용할 로딩 바를 띄우는 작업도 함께 해주면 좀더 나은 UX 를 구현할 수 있겠죠.
- login view script
<script>
function checkLogin(){
    
    if( $.trim($("#userId").val()) == '' ){
        alert("아이디를 입력해 주세요.");
        $("#userId").focus();
        return;
    }
    if( $.trim($("#userPw").val()) == '' ){
        alert("비밀번호를 입력해 주세요.");
        $("#userPw").focus();
        return;
    }
    // 로그인 프로세스 호출
    $.ajax({
        type: 'post'
        , async: true
        , url: '/member.do?cmd=login'
        , data: $("#frm").serialize()
        , beforeSend: function() {
             $('#ajax_load_indicator').show().fadeIn('fast');
          }
        , success: function(data) {
            var response = data.trim();
            console.log("success forward : "+response);
            // 메세지 할당
            switch(response) {
                case "nomatch":
                    msg = "아이디 또는 비밀번호가 일치하지 않습니다."; break;
                case "fail":
                    msg = "로그인에 실패 했습니다."; break;
                default :
                    msg = "존재하지 않는 사용자입니다."; break;
            }
            // 분기 처리
            if(response=="success"){
                window.location.href = "${targetUrl}";
            } else {
                alert(msg);
            }
          }
        , error: function(data, status, err) {
         console.log("error forward : "+data);
            alert('서버와의 통신이 실패했습니다.');
          }
        , complete: function() {
         $('#ajax_load_indicator').fadeOut();
          }
    });
}
</script>
- login view html
<form id="frm" name="frm" method="post" action="" onSubmit="checkLogin();return false;">
    <fieldset>
        <legend>login</legend>
        <div class="login_item mg_top34">
            <label>id</label>
            <input id="userId" name="memberVo.xcWebMbrId" type="text" class="i_login" />
        </div>
        <div class="login_item mg_top10">
            <label>password</label>
            <input id="userPw" name="memberVo.xcPswd" type="password" class="i_login" />
        </div>
        
        <div id="ajax_load_indicator" style="display:none">
            <p style="text-align:center; padding:16px 0 0 0"><img src="/mobile/common/img/ajax-loader-line.gif" /></p>
        </div>
        <p class="keeping mg_left89">
            <input id="keepidpw" class="rd_box22" value="1" type="checkbox" name="idPswdSave" >
            <label for="keepidpw">ID/PW 저장</label>
        </p>
        <p class="keeping mg_left20">
            <input id="keepid" class="rd_box22" value="1" type="checkbox" name="idSave" >
            <label for="keepid">ID 저장</label>
        </p>
        <span class="btn_login">
            <input type="image" src="<%=imageUrl%>/btn/btn_login.jpg" title="로그인" onclick="checkLogin();return false;">
        </span>
        <p class="btn_register"><a href="/member.do?cmd=memberJoin"><img src="<%=imageUrl%>/btn/btn_join.jpg" alt="회원가입" /></a>
        <a href="/member.do?cmd=goIdPwFind" class="mg_left5"><img src="<%=imageUrl%>/btn/btn_sch.jpg" alt="아이디/비밀번호 찾기" /></a></p>
    </fieldset>
</form>
- login ajax result
<%@ include file="/mobile/common/include/config.jsp" %>
${result}
  • 내용 추가
페이지 하단으로 스크롤 이동했을 때 추가되는 자동으로 다음 페이지 데이터가 추가되는 UX를 구현할 때 사용하는 기법으로 jQuery 의 append() 함수를 사용할 수 있다.
- product list view script
<script>
function paging(){
    count++;
    
    $.ajax({
        type: 'post'
        , async: true
        , url: "/display.do?cmd=productListAppend&ordFlag="+'${ordFlag}'+"&categoryCd="+categoryCd+"&itemCode="+'${itemCode}'+"&count="+count
        , beforeSend: function() {
             $('#ajax_load_indicator').show().fadeIn('fast');
          }
        , success: function(data) {
            var response = data.trim();
            console.log("success forward : "+response);
            // 상품 리스트 할당
            $('#view_list').append(response);
            $('#product_count').html($('#view_list li.thumb').size());
          }
        , error: function(data, status, err) {
            console.log("error forward : "+data);
            alert('서버와의 통신이 실패했습니다.');
          }
        , complete: function() {
            $('#ajax_load_indicator').fadeOut();
          }
    });
}
</script>
- product list view html
<!-- 상품 목록 -->
<div id="view_list" class="product_list" style="display: none;">
<c:forEach var="list" items="${returnMap}">
  <a href="/display.do?cmd=productView&brandCd=${list.brandCd }&prodCd=${list.prodCd }&ordFlag=${ordFlag }&styleYY=${list.styleYY }&priceDpYn=${list.priceDpYn }&listPrice=${list.listPrice }&categoryCd=${categoryCd}&itemCode=${itemCode}&rNum=${list.rNum }&count=${count}">
    <ul>
      <li class="thumb"><img src="${list.listImg }" alt="상품이미지" /></li>
      <li class="b_title"><span class="brand">[${list.brandNm }]</span><span class="title">${list.prodNm }</span></li>
      <li class="price">
      <c:if test="${list.priceDpYn eq 'Y'}">
      ${list.listPrice }원
      </c:if>
      <c:if test="${list.priceDpYn eq 'N'}">
      <span><a href="#"><img src="<%=imageUrl%>/common/ic_login.png" alt="로그인" /></a></span>
      </c:if>
      </li>
      <li class="btn_go"><img src="<%=imageUrl%>/btn/btn_go.png" alt="" /></li>
    </ul>
  </a>
</c:forEach>
</div>
<div id="ajax_load_indicator" style="display:none">
    <p style="text-align:center; padding:14px 0 14px 0"><img src="/mobile/common/img/ajax-loader-line.gif" /></p>
</div>
    
<!-- 더보기 bar-->
<div class="more_bar">
<a href="javascript:paging()">
  <ul class="sec01">
    <li class="btn_arr"><img src="<%=imageUrl%>/common/arr_down.png" alt="" /></li>
    <li class="text_more">15개 더보기</li>
    <li class="text_num"><span id="product_count">${total}</span> / 999</li>
  </ul>
  </a>
  <p><a href="#"><img src="<%=imageUrl%>/btn/btn_top.jpg" alt="맨위로" /></a></p>
</div>  
- append view html
<%@ include file="/mobile/common/include/config.jsp"%>
<!-- 상품 목록 -->
<c:forEach var="list" items="${returnMap}">
    <a href="/display.do?cmd=productView&brandCd=${list.brandCd }&prodCd=${list.prodCd }&ordFlag=${ordFlag }&styleYY=${list.styleYY }&priceDpYn=${list.priceDpYn }&listPrice=${list.listPrice }&categoryCd=${categoryCd}&itemCode=${itemCode}&rNum=${list.rNum }&count=${count}">
        <ul>
            <li class="thumb"><img src="${list.listImg }" alt="상품이미지" /></li>
            <li class="b_title"><span class="brand">[HAZZYS]</span><span
                class="title">${list.prodNm }</span></li>
            <li class="price">
            <c:if test="${list.priceDpYn eq 'Y'}">
            ${list.listPrice }원
            </c:if>
            <c:if test="${list.priceDpYn eq 'N'}">
            <span><a href="#"><img src="<%=imageUrl%>/common/ic_login.png" alt="로그인" /></a></span>
            </c:if>
            </li>
            <li class="btn_go"><img src="<%=imageUrl%>/btn/btn_go.png" alt="" /></li>
        </ul>
    </a>
</c:forEach>
 

If anything about current interaction design can be called “glamorous,” it’s creating Web applications. After all, when was the last time you heard someone rave about the interaction design of a product that wasn’t on the Web? (Okay, besides the iPod.) All the cool, innovative new projects are online.

Despite this, Web interaction designers can’t help but feel a little envious of our colleagues who create desktop software. Desktop applications have a richness and responsiveness that has seemed out of reach on the Web. The same simplicity that enabled the Web’s rapid proliferation also creates a gap between the experiences we can provide and the experiences users can get from a desktop application.

That gap is closing. Take a look at Google Suggest. Watch the way the suggested terms update as you type, almost instantly. Now look at Google Maps. Zoom in. Use your cursor to grab the map and scroll around a bit. Again, everything happens almost instantly, with no waiting for pages to reload.

Google Suggest and Google Maps are two examples of a new approach to web applications that we at Adaptive Path have been calling Ajax. The name is shorthand for Asynchronous JavaScript + XML, and it represents a fundamental shift in what’s possible on the Web.

Defining Ajax

Ajax isn’t a technology. It’s really several technologies, each flourishing in its own right, coming together in powerful new ways. Ajax incorporates:

The classic web application model works like this: Most user actions in the interface trigger an HTTP request back to a web server. The server does some processing—retrieving data, crunching numbers, talking to various legacy systems—and then returns an HTML page to the client. It’s a model adapted from the Web’s original use as a hypertext medium, but as fans of The Elements of User Experience know, what makes the Web good for hypertext doesn’t necessarily make it good for software applications.

사용자 삽입 이미지

Figure 1: The traditional model for web applications (left) compared to the Ajax model (right).

This approach makes a lot of technical sense, but it doesn’t make for a great user experience. While the server is doing its thing, what’s the user doing? That’s right, waiting. And at every step in a task, the user waits some more.

Obviously, if we were designing the Web from scratch for applications, we wouldn’t make users wait around. Once an interface is loaded, why should the user interaction come to a halt every time the application needs something from the server? In fact, why should the user see the application go to the server at all?

How Ajax is Different

An Ajax application eliminates the start-stop-start-stop nature of interaction on the Web by introducing an intermediary—an Ajax engine—between the user and the server. It seems like adding a layer to the application would make it less responsive, but the opposite is true.

Instead of loading a webpage, at the start of the session, the browser loads an Ajax engine—written in JavaScript and usually tucked away in a hidden frame. This engine is responsible for both rendering the interface the user sees and communicating with the server on the user’s behalf. The Ajax engine allows the user’s interaction with the application to happen asynchronously—independent of communication with the server. So the user is never staring at a blank browser window and an hourglass icon, waiting around for the server to do something.

사용자 삽입 이미지

Figure 2: The synchronous interaction pattern of a traditional web application (top) compared with the asynchronous pattern of an Ajax application (bottom).

Every user action that normally would generate an HTTP request takes the form of a JavaScript call to the Ajax engine instead. Any response to a user action that doesn’t require a trip back to the server—such as simple data validation, editing data in memory, and even some navigation—the engine handles on its own. If the engine needs something from the server in order to respond—if it’s submitting data for processing, loading additional interface code, or retrieving new data—the engine makes those requests asynchronously, usually using XML, without stalling a user’s interaction with the application.

Who’s Using Ajax

Google is making a huge investment in developing the Ajax approach. All of the major products Google has introduced over the last year—Orkut, Gmail, the latest beta version of Google Groups, Google Suggest, and Google Maps—are Ajax applications. (For more on the technical nuts and bolts of these Ajax implementations, check out these excellent analyses of Gmail, Google Suggest, and Google Maps.) Others are following suit: many of the features that people love in Flickr depend on Ajax, and Amazon’s A9.com search engine applies similar techniques.

These projects demonstrate that Ajax is not only technically sound, but also practical for real-world applications. This isn’t another technology that only works in a laboratory. And Ajax applications can be any size, from the very simple, single-function Google Suggest to the very complex and sophisticated Google Maps.

At Adaptive Path, we’ve been doing our own work with Ajax over the last several months, and we’re realizing we’ve only scratched the surface of the rich interaction and responsiveness that Ajax applications can provide. Ajax is an important development for Web applications, and its importance is only going to grow. And because there are so many developers out there who already know how to use these technologies, we expect to see many more organizations following Google’s lead in reaping the competitive advantage Ajax provides.

Moving Forward

The biggest challenges in creating Ajax applications are not technical. The core Ajax technologies are mature, stable, and well understood. Instead, the challenges are for the designers of these applications: to forget what we think we know about the limitations of the Web, and begin to imagine a wider, richer range of possibilities.

It’s going to be fun.


Caps Lock키 일명 대문자키(?)가 켜저있는지 확인하는 자바 스크립트이다.

뭐 별나게 쓸 일을 없지만, 소문자만 영어만 사용하는 곳에서는 꼭 필요한듯한 자바스크립트이다.
 

function checkCapsLock( e ) {
 var myKeyCode=0;
 var myShiftKey=false;
 var myMsg='Caps Lock이 켜져있습니다. 확인하세요!';

 // Internet Explorer 4+
 if ( document.all ) {
  myKeyCode=e.keyCode;
  myShiftKey=e.shiftKey;

 // Netscape 4
 } else if ( document.layers ) {
  myKeyCode=e.which;
  myShiftKey=( myKeyCode == 16 ) ? true : false;

 // Netscape 6
 } else if ( document.getElementById ) {
  myKeyCode=e.which;
  myShiftKey=( myKeyCode == 16 ) ? true : false;

 }

 // Upper case letters are seen without depressing the Shift key, therefore Caps Lock is on
 if ( ( myKeyCode >= 65 && myKeyCode <= 90 ) && !myShiftKey ) {
  alert( myMsg );

 // Lower case letters are seen while depressing the Shift key, therefore Caps Lock is on
 } else if ( ( myKeyCode >= 97 && myKeyCode <= 122 ) && myShiftKey ) {
  alert( myMsg );

 }
}

가끔 자바스크립트에서 딜레이가 필요한 경우가 있다.

보통

setTimeout("hideMessage()", 1000);


이렇게 많이 사용한다.
하지만...

이건 함수를 딜레이 시켜 실행 하는 부분이고,
가끔 정상적으로 동작을 하지 않는 경우를 확인했다..ㅠ,.ㅍ

왜!! 저 setTimeout() 함수가 정상 적동을 하지 않는지 아직도 의문 이다...ㅡㅡ;;
그래서 결국 자바스크립트에서 딜레이 함수를 별도로 만들었다.

function delay(gap){ /* gap is in millisecs */
  var then,now;
  then=new Date().getTime();
  now=then;
  while((now-then)<gap){
    now=new Date().getTime();
  }
}

작동 잘~ 된다!! ㅋㅋ

1. explode(분리문자열, 문자열)

     => 분리문자(열)를 기준으로 문자열을 배열로 저장한다.

2. implode(결합문자열, 문자열)

     => 결합문자(열)를 이용하여 문자열을 합쳐준다.

3. substr(문자열, 자르는 위치, 자를 수)

     => 문자열을 일정 위치에서 크기수만큼 잘라 준다.

4.  str_split(문자열)

     => PHP5이상에서 사용이 가능하며 크기가 일정하거나 알 수 없는 경우 사용 가능

5. echo "문자열"

     => 기본 출력 함수

6. ereg(검사할 문자, 검사대상문자열)

     => 문자열내 검사할 문자가 포함되었는지 검사

         eregi는 대 소문자를 구별하지 않는다.

7. header("location:이동할페이지")

     => 화면의 어떤 출력문보다 먼저 나와야 함. 다르 페이지로 이동시 사용.

          유사한 명령으로 meta태크나 java script에서 location.href="이동할 페이지" 가 있다.

8. ltrim(문자열)

     => 시작 공백제거

         반대 함수가 chop이다.

9. mb_strlen(문자열, 코딩방식)

     => 문자열의 길이를 알아내는 방식. 'euc-kr'로 설정시 한글인식이 된다.

10. nl2br

     => 문자열의 모든 줄바꿈 앞에 HTML 줄바꿈 태그를 생성한다.

11. ord(문자)

     => ASCII 번호 출력

12. phpinfo

     => 기본 정보 출력

13. print_r($변수)

     => 변수값 출력

14. strrev

     => 문자열을 역순으로 출력

15. strtoupper

     => 대문자 변경

          strtolower는 소문자로 변경한다.

16. trm(문자열)

     => 시작과 끝 공백 제거

'Web(웹) Study > PHP' 카테고리의 다른 글

date함수의 포맷문자열  (0) 2010.11.24
클래스 사용하기  (0) 2010.11.24
월의 마지막 날짜 구하기  (0) 2010.11.24
날짜의 요일 구하기  (0) 2010.11.24
php에 mssql을 사용하기  (0) 2010.02.12

date 함수에서 사용할 수있는  포맷문자열 입니다.


a : "am" 또는 "pm"
A : "AM" 또는 "PM"
d : 두자리로 표현되는 날짜, 즉 "01"~"31"
D : 세글자로 표현되는 요일, 즉 "Fri"
F : 월을 긴 문장으로 나타냅니다. 즉 "January"
h : 시간을 12시간 단위로 나타냅니다. "01"~"12"
H : 시간을 24시간 단위로 나타냅니다.
g : 시간을 12시간 단위로 0 없이 나타냅니다. "1"~"12"
G : 시간을 24시간 단위로 0 없이 나타냅니다. "0"~"24"
i : 분을 나타냅니다. "00"~"59"
j : 날짜를 0 없이 나타냅니다. "1"~"31"
l : (L의 소문자)요일을 나타냅니다. "Friday"
L : 윤년인지의 여부를 나타냅니다. "0" 또는 "1"
m : 달을 나타냅니다. "01"~"12"
n : 0 없이 달을 나타냅니다. "1"~"12"
M : 3글자로 달을 나타냅니다. "Jan"
s : 초를 나타냅니다. "00"~"59"
S : 영어에서 순서를 나타내는 2글자로 된 접미사; "th", "nd"
t : 주어진 달의 날 수; 즉 "28"~"31"
U : 기준시점(GMT 1970년 1월1일 00:00:00)으로부터 지난 시간을 초로 표시
w : 요일을 숫자로 표시합니다. 즉 "0"(일요일) ~ "6"(토요일)
Y : 4글자로 연도표시, "1999"
y : 2글자로 연도표시, "99"
z : 날짜를 표시, "0"~"365"
Z : 지역간의 시간편차를 초단위로 표시, 즉 "-43200"~"43200"

'Web(웹) Study > PHP' 카테고리의 다른 글

PHP 문자열 처리 함수  (0) 2011.01.10
클래스 사용하기  (0) 2010.11.24
월의 마지막 날짜 구하기  (0) 2010.11.24
날짜의 요일 구하기  (0) 2010.11.24
php에 mssql을 사용하기  (0) 2010.02.12

1. 클래스 정의

// class 키워드를 이용해서 클래스를 정의한다.
class Car {
    // 멤버 변수를 정의한다.
    var $color;
    var $speed;
   
    // 생성자
    function Car($color = 'red') {
        // $this 를 사용해서 멤버에 접근한다.
        $this->color = $color;
    }
   
    // 메소드를 정의한다.
    // 메소드 오버로딩을 지원하지 않는다.
    function speedUp($amount=1) {
        $this->speed += $amount;
    }
   
    function getSpeed() {
        return $this->speed;
    }
}



2. 클래스 사용하기

$car = new Car('blue');
$car->speedUp();
echo($car->getSpeed());



3. 상속하기
class Super {
    var $s_member;
   
    function s_method() {
        echo("call s_method()...\n");
    }
}

 

// extends 키워드를 이용해서 상속한다.
// 다중상속은 지원하지 안는다.

class Child extends Super {
    var $c_member;
   
    function c_method() {
        echo("call c_method()...\n");
    }
}

 

$super = new Super();
$super->s_member = 10;
$super->s_method();

 

$child = new Child();
$child->c_member = 5;
$child->c_method();

 

// 상속받은 부모의 속성을 사용할 수 있다.
$child->s_member = 10;
$child->s_method();

 

// 부모객체는 자식의 속성을 사용할 수 없다.
$super->c_member = 3;
$super->c_method();

 

출력 결과)
call s_method()...
call c_method()...
call s_method()...

 

Fatal error: Call to undefined method Super::c_method() in D:\workspace\PHPTest\test.php on line 34



4. 오버라이딩
class Super {
    var $member = '부모의 기본값';
   
    function operation() {
        echo("부모의 메소드 호출.\n");
        echo("\$member의 값은 {$this->member}\n");
    }
}

 

class Child extends Super {
    var $member = '자식의 기본값';
   
    function operation() {
        echo("자식의 메소드 호출\n");
        echo("\$member의 값은 {$this->member}\n");
       
       
        echo("\n부모값 호출\n");
       
        // 부모의 속성을 호출하기 위해서 parent 키워드와 :: 연산자를 사용한다.
        parent::operation();
    }
}

 

$super = new Super();
$super->operation();
echo("\n");
$child = new Child();
$child->operation();

 

출력 결과)
부모의 메소드 호출.
$member의 값은 부모의 기본값

 

자식의 메소드 호출
$member의 값은 자식의 기본값

 

부모값 호출
부모의 메소드 호출.
$member의 값은 자식의 기본값


5. 객체 비교하기
// 객체의 비교는 == 연사자를 이용하고, 속성들의 값이 동일할 때만  true 이다.
$car1 = new Car();
$car2 = new Car();
if($car1 == $car2) {
    echo("TRUE...\n");
} else {
    echo("FALSE...\n");
}

 

$car2->speedUp();
if($car1 == $car2) {
    echo("TRUE...\n");
} else {
    echo("FALSE...\n");
}

 

$car3 = new Car('blue');
if($car1 == $car3) {
    echo("TRUE...\n");
} else {
    echo("FALSE...\n");
}

출력결과)
TRUE...
FALSE...
FALSE...

'Web(웹) Study > PHP' 카테고리의 다른 글

PHP 문자열 처리 함수  (0) 2011.01.10
date함수의 포맷문자열  (0) 2010.11.24
월의 마지막 날짜 구하기  (0) 2010.11.24
날짜의 요일 구하기  (0) 2010.11.24
php에 mssql을 사용하기  (0) 2010.02.12
특정월의 마지막 날짜를 구하는 방법입니다.

날 수를 구하는것과 같겠죠..^^

방법은 date함수의 포맷문자열 't'를 사용합니다.

$day_count = date('t', strtotime("2010-09-01"));

다음도 됩니다.

$day_count = date('t', mktime(0, 0, 1, 9, 1, 2010));

mktime함수의 인자는 순서대로 시간, 분, 초, 월, 일, 년도 입니다.

'Web(웹) Study > PHP' 카테고리의 다른 글

date함수의 포맷문자열  (0) 2010.11.24
클래스 사용하기  (0) 2010.11.24
날짜의 요일 구하기  (0) 2010.11.24
php에 mssql을 사용하기  (0) 2010.02.12
PHP에서 "HTTP / HTTPS" Request하기  (0) 2009.11.18

다음과 같은 날짜를 나타내는 문자열이 있을때 이 날짜의 요일을 구하는 방법 입니다.

$day = "2010-09-01";

날짜의 요일정보는 date 함수의 'w' 포맷 문자열을 사용해서 구할 수 있습니다.

반환되는 값은 0부터 6까지의 숫자값으로 일~토 까지를 나타냅니다.

그러면 다음과 같이 사용할 수 있습니다.

$yoil = array("일","월","화","수","목","금","토");

echo($yoil[date('w', strtotime($day))]);

'Web(웹) Study > PHP' 카테고리의 다른 글

클래스 사용하기  (0) 2010.11.24
월의 마지막 날짜 구하기  (0) 2010.11.24
php에 mssql을 사용하기  (0) 2010.02.12
PHP에서 "HTTP / HTTPS" Request하기  (0) 2009.11.18
빠른 PHP 속도를 유지 하기 위한 것.  (0) 2009.10.06

이메일 체크 정규식
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i;


핸드폰번호 정규식
/^\d{3}-\d{3,4}-\d{4}$/;


일반 전화번호 정규식
/^\d{2,3}-\d{3,4}-\d{4}$/;


아이디나 비밀번호 정규식
 /^[a-z0-9_]{4,20}$/;


var regExp = /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/;


if ( !regExp.test( document.frm.hp.value ) ) {
      alert("잘못된 휴대폰 번호입니다. 숫자, - 를 포함한 숫자만 입력하세요.");
      return false
}

php에 mssql을 사용하게 되었네요.

mysql_connet처럼 당연히  mssql_connect 함수가 있길래 똑같이 해봤습니다만,
당연히 아무런 셋팅이 없으면 mssql_connect를 사용할 수가 없습니다.

첫번째 직면하는 에러문제는 undefined function이라는 겁니다..
이문제는 mssql 라이브러리를 링크하면 해결됩니다.
extension에 php_mssql.dll을 추가해주세요..

두번째 문제는 unable to connect server입니다..
연결이 안되지요.

이 문제는 두가지로 해석할 수 있습니다.

해당 사용자의 외부접속을 mssql서버에서 막았거나, php에서 해당 서버로 접속을 연결할 수 없다는거죠.

전자는 sql서버에 권한을 넣음으로써 해결할 수 있습니다.

후자 문제는 php서버와 sql서버가 같으면 발생하지 않을 수 있지만, 제가 테스트 하는 환경에서는 나타나더군요.

문제 해결은 다음과 같습니다.

sql이 설치된 서버의 windows/system32 폴더의 ntwdblib.dll 파일을
php가 설치된 서버의 windows/system32 폴더로 복사하고 서버를 재시작 하는 것입니다.

이러니 문제가 해결되더군요. 오늘도 밥값을 한거 같아 기쁩니다.

ps. 당연히 삽질 많이 했습니다.
한달전에 연결안되는 문제를 확인하고 바빠서 덮어두었는데..
이제서야 찾아서 해결책을 올리네요-0-

ps2. 두개의 파일이 다른점은 사이즈로 비교하시기 바랍니다.
sql이 설치된 서버의 ntwdblib.dll파일 사이즈는 284kb이고..
php가 설치된 서버의 ntwdblib.dll파일 사이즈는 273kb입니다.
파일을 첨부합니다~ ㅋ

(MSSQL)-, (PHP)- 확장자는 지우고 사용하세요~

'Web(웹) Study > PHP' 카테고리의 다른 글

월의 마지막 날짜 구하기  (0) 2010.11.24
날짜의 요일 구하기  (0) 2010.11.24
PHP에서 "HTTP / HTTPS" Request하기  (0) 2009.11.18
빠른 PHP 속도를 유지 하기 위한 것.  (0) 2009.10.06
PHP로 소켓 서버 작성하기  (1) 2009.10.06
Script.aculo.Us에서는 드래그앤드롭(Drag N Drop)을 쉽게 구현할 수 있는 클래스가 있는데 Draggable(Droppables)과 Sortable 2개의 클래스이다. 둘다 드래그앤드롭을 위한 클래스인데 Draggable는 객체를 드래그 가능하게 만드는 클래스이고 Sortable은 드래그앤드롭이 되면서 정렬이 가능하도록 하는 클래스이다. 정렬을 하고자 한다면 Sortable을 사용하는 것이 편하고 여기서 정리하려는 것은 Sortable이다.

Sortable.create('id_of_container',[options]);

위 코드이 Sortable 을 사용하는 기본 문법이다. id_of_container에 드래그앤드롭을 가능하게 할 엘리먼트의 id를 주고 options에 드래그앤드롭에 대한 옵션을 JSON형태로 던져주면 바로 정렬가능한 드래그앤드롭을 사용가능하다.  id_of_container이라고 쓴 것처럼 드래그할 객체가 아니라 드래그할 객체들을 담고 있는 container의 id를 주면 되고 options는 안주면 디폴트옵션으로 동작하게 된다.

예를 들어

  1. <ul id="contailner"> 
  2.     <li id="dnd_1">Test 1</li> 
  3.     <li id="dnd_2">Test 2</li> 
  4. <ul> 
  5. <script type="text/javascript"> 
  6.     Sortable.create("contailner");  
  7. </script> 

위와같이 작성하면 dnd_1, dnd_2객체가 바로 드래그앤드롭이 가능하다. (이 얼마나 간단하단 말인가. ㅎㅎㅎ)

이제 옵션을 보자. 자유롭게 사용하려면 옵션을 주어서 원하는 형태로 사용하여야 한다. 옵션은 Draggable과 공통적인 것도 있고 아닌것들도 있다.(아직 Script.aculo.us의 API리스트는 솔직히 좀 아쉽다.) API와 내가 테스트해본걸 바탕으로 적었지만 빠진 부분이 있을수도 있다.

tag : 여기에 HTML태그명을 주면 해당 태그에 대해서 Sortable이 동작하게 된다. 디폴트는 li태그이고 container아래 한단계 밑까지만 동작한다. 쉽게 말해 li안에 li가 또 들어있다고 하더라도 안에 있는 li에는 드래그앤드롭이 동작하지 않는다. Block엘리먼트에만 가능하고 table같은걸 블가능하다.

only : 이 옵션을 주고 여기서 class명을 지정하면 tag에 설정한 태그명이라고 할지라도 only에서 준 class명과 맞지 않으면 드래그앤드롭이 동작하지 않는다.

overlap : 가로 리스트는 horizontal, 세로 리스트는 vertical로 설정하라는데 정확한 동작은 잘 모르겠다.

constraint : horizontal, vertical, false 3가지가 있고 드래그앤드롭의 방향을 설정한다. horizontal/vertical로 설정할 경우에는 가로/세로로만 이동하며 false나 옵션을 주지 않았을 경우에는 어떤 방향이든지 이동이 가능하다.

containment : 이곳에 container 리스트를 지정하고 이곳에 지정한 container간에는 드래그앤드롭이 가능하다.

handle : 드래그앤드롭을 할 엘리먼트에서 전체가 아닌 특정부분만을 이용해서 드래그앤드롭이 가능하도록 하고 싶을때 handle이용한다. 이곳에 id 혹은 class명을 지정하면 핸들러로 사용할 수 있다.

delay : 드래그앤드롭으로 반응할 시간을 미리세컨단위로 설정할 수 있고 기본은 0이다. 너무 민감하게 반응하지 않기를 바랄때는 delay의 숫자를 크게 지정할 수 있다.

dropOnEmpty : true로 설정하면 container가 비어있을때도 drop이 가능하다. false일 경우에는 container에 다른 드래그앤드롭객체가 있을때만 드롭이 가능하다. 기본은 false

scroll : 기본으로는 지정되어 있지 않으며 window로 설정할 경우에는 드롭할 container가 화면밖에 있을경우에 드래그객체가 화면밖으로 나가면 자동으로 스크롤한다.

scrollSensitivity : 기본은 20이고 스크롤이 되게 하기 위해서 넘어가야하는 크기를 지정한다.

scrollSpeed : 스크롤 속도이고 픽셀로 지정하면 기본은 15이다.

onChange : 콜백함수로 드래그앤드롭을 시작하는 등 객체의 위치가 변경되면 계속 발생한다.

onUpdate : 콜백함수로 드래그앤드롭을 하여 실제 순서의 변화가 생겼을때만 발생한다.

 





아주 간단한 예제를 만들었다. 동작과 소스코드를 보면 쉽게 이해할 수 있을꺼라고 생각한다. 최근 작업을 하면서 몇가지 주의점(?)을 발견한 거라면...

  • container의 id에 언더바(_)가 들어가면 동작하지 않는다.
  • Sortable.serialize를 사용하려면 드래그앤드롭 엘리먼트의 아이디가 언더바(_)로 이어져야 한다. 언더바 뒤쪽에 있는 문자만 표시된다.
  • IE에서는 왼쪽 콘테이너에서 오른쪽 콘테이너로 갈때 드래그엘리먼트가 컨테이너 뒤쪽으로 가는 문제가 생긴다. 드롭하기 위해서 반이상 넘어갈 경우에는 위로 올라오는데 이건 IE의 z-index버그때문에 생기는 문제로 예상되는데 정확한 해결책은 아직 찾지 못했다.
Sortable.serialize는 해당 컨테이너에 있는 드래그앤드롭객체를 순서대로 보여준다. 이것은 위치정렬을 한 후에 Ajax등을 통해서 새로 정렬한 위치를 서버에 저장할 수 있도록 하는 역할을 한다.

그리고 예제의 소스를 보면 알겠지만 기본적으로는 드래그앤드롭을 할 때 해당위치의 공간은 표시하지만 따로 표시되지는 않는다. 이 문제를 해결하기 위해 더미 엘리먼트를 만들었다. OnChage가 발생할 때 해당 엘리먼트의 바로 앞쪽에 더미엘리먼트를 만들어서 insert한다. 이렇게 함으로써 드롭했을때 떨어질 위치가 명시적으로 보일수 있도록 하고 OnChange는 계속 발생하기 때문에 처음에 더미엘리먼트를 지우고 다시 넣어주기 때문에 다른 컨테이너로 넘어가는 순간 더미엘리먼트도 적절하게 이동된다. 깔끔한 해결책은 아닌듯 하지만 일단 동작은 한다.
항상 뭘하다보면 자기 중심적으로 생각하게 되는것 같습니다. 상대방의 입장에서 생각해야 되는데 그게 쉽지 않습니다. 더군다나 웹에서는 상대방(?)의 대한 정보가 보통은 전무한 편이라서 더 자기중심적으로 생각하게 되는 경우가 많죠.

초창기에 개발에 대해 전혀 모를때 인터넷에 있는 많은 정보들을 볼 때 가장 답답한 부분중 하나가 설명하는 사람이 당연히 내가 알꺼라고 생각하고 그냥 넘어가는 부분을 정작 나는 몰라서 그사람의 설명이나 소스까지 도달하기도 어려웠다는 것이지요. 머 그렇다고 항상 모든 것을 다 설명한다는 것도 어렵겠지만 블로그에서는 최대한 자세하게 쓰려고 하고 있기는 하지만 좀 초심을 잃어버린 생각이 들었습니다. 그리고 새로 알게된걸 항상 포스팅으로 하게되지는 않고 그러다 보면 포스팅타이밍을 놓쳐버린 것들도 많죠.



쿡이님의 질문을 받으면서 생각난 김에 JS로 엘리먼트를 다룰때 가장 많이 사용할 추가, 삭제에서 prototype.js가 지원하는 부분에 대해서 다시 한번 정리합니다.

prototype.js에는 Element 클래스가 있습니다. HTML의 DIV, INPUT, LI같은 엘리먼트에 관련된 클래스입니다. Element의 API문서 를 보면Element클래스가 지원하는 많은 메서드를 볼 수 있습니다. 엘리먼트와 관련된 속성에 대한 것이라든지, 추가, 삭제, 생성등등의 기능을 지원하고 있습니다.




일반적인 방법
  1. <div id="testDivision" name="testDivision"> 
  2.     <a href="#">Link 1</a> 
  3. </div> 

간단한 HTML을 가지고 보겠습니다. 엘리먼트를 핸들링할때 JS에서 제공하는 2가지방법이 있습니다. innerHTML을 이용하는 방법과 DOM을 이용하는 방법입니다.

일반적으로는 innerHTML을 이용하는 것이 간단하면서도 편하기 때문에 많이 사용합니다.

  1. var htmlStr = "<a href='#'>Link 2</a>";  
  2. var obj = document.getElementById("testDivision");  
  3. obj.innerHTML = obj.innerHTML + htmlStr;  

사실 설명할 내용도 없긴 하지만 innerHTML은 이름 그대로 해당 엘리먼트의 안에 있는 HTML을 의미하고 있습니다. 내부 HTML을 새로지정하면 새로 지정하는 내용으로 replace가 됩니다. 기본의 innerHTML값과 새로추가할 HTML스트링을 문자열로 이어붙혀서 다시 innerHTML으로 할당해서 HTML의 구조를 동적으로 바꾸는 것입니다. js를 실행하면 HTML이 아래와 같은 모습이 됩니다.
  1. <div id="testDivision" name="testDivision"> 
  2.     <a href="#">Link 1</a> 
  3.     <a href="#">Link 2</a> 
  4. </div> 


두번째 방법은 DOM입니다. DOM은 Document Object Model의 약자로 표준이 정해져 있고 대부분의 브라우저가 지원하고 있습니다. 엘리먼트를 추가/삭제같은 DOM Level 2 에 정의가 되어 있습니다.(DOM Level 1에서 추가확장되어 현재는 대부분 Level 2를 지원하고 있는 것으로 알고 있습니다.) 이름대로 DOM을 다루기 위해서 만들어진 것이기 때문에 다양한 메서드를 제공하고 있고 좀 더 세련된 느낌의 사용법을 가지고 있습니다.

  1. var elem = document.createElement("a")  
  2. elem.setAttribute("href", "#");  
  3. elem.appendChild(document.createTextNode("Link 2"));  
  4. document.getElementById("testDivision").appendChild(elem);  

같은 기능을 DOM으로 구현한 것입니다. 엘리먼트 만들고 속성추가하고 TextNode만들어서 A엘리먼트 안에 넣은 다음에 추가한 것입니다. 메서드로 다양하게 다룰 수 있기는 하지만 저 간단한 소스도 소스로는 꽤 복잡하게 작성되고 있고 한눈에 어떻게 동작할 것인지를 파악하기가 쉽지 않고 복잡한 HTML의 경우에는 훨씬 복잡하게 됩니다. innerHTML에 비해서 특정엘리먼트만 지우는 remove관련 메서드도 지원하고 있기는 하지만 브라우져의 따라 DOM Level 1/2의 지원차이가 있습니다.

DOMDom Test Pages 에서 지원여부를 테스트해 볼 수 있고 PPK의 W3C DOM Compatibility 에서 브라우져별 차이를 파악할 수 있습니다.




prototype.js 이용하기
당연히 prototype.js를 로드해야하고 그 후에 다음과 같이 사용하면 됩니다.
  1. $("testDivision").insert("<a href='#'>Link 2</a>");  
  2. $("testDivision").update("<a href='#'>Link 2</a>");  
  3. $("testDivision").remove();  

너무 간단한 코드라서 그냥 한 코드블럭에 다 썼습니다. 첫줄 insert만으로 위에서 설명했던 기능과 동일한 기능을 합니다. update는 replace의 기능을 합니다. 2번째 줄을 실행하면 Div안에 link2만 존재하게 되겠고 remove를 실행하면 testDivision DIV자체가 삭제되어버립니다. 간단한 기능만 소개했지만 그외에도 Element관련 다양한 기능 을 제공하고 있습니다. prototype.js내부적으로 크로스 브라우징을 지원하기 때문에 브라우저호환에 대해서 큰 걱정없이 사용할 수 있습니다.

추가적으로 좀 더 세밀하게 컨트롤 할 수 있는 기능을 제공하고 있습니다.
  1. $("testDivision").insert({top:"<a href='#'>Link 2</a>"});  
  2. // 결과  
  3. // <div id="testDivision" name="testDivision">  
  4. //       <a href="#">Link 2</a><a href="#">Link 1</a>  
  5. // </div>  
  6.  
  7. $("testDivision").insert({bottom:"<a href='#'>Link 2</a>"});  
  8. // 결과  
  9. // <div id="testDivision" name="testDivision">  
  10. //       <a href="#">Link 1</a><a href="#">Link 2</a>  
  11. // </div>  
  12.  
  13.  
  14. $("testDivision").insert({bottom:"<a href='#'>Link 2</a>"});  
  15. // 결과  
  16. // <a href="#">Link 2</a>  
  17. // <div id="testDivision" name="testDivision">  
  18. //       <a href="#">Link 1</a>  
  19. // </div>  
  20.  
  21. $("testDivision").insert({after:"<a href='#'>Link 2</a>"});  
  22. // 결과  
  23. // <div id="testDivision" name="testDivision">  
  24. //       <a href="#">Link 1</a>  
  25. // </div>  
  26. // <a href="#">Link 2</a>  

위 코드처럼 JSON형태로 사용해서 insert되는 위치를 지정해 줄 수 있습니다. 사용할 수 있는 position값은 top, bottom, before, after입니다.  이걸 이용하면 쉽게 원하는 위치에 엘리먼트의 삽입/삭제가 가능합니다.

좀 복잡한 HTML의 경우에는 script.aculo.us의 Builder을 사용하는 것도 괜찮은 방법 같습니다.

<?php

/* ----------------------------------------------
 GET HTTP PAGE...
 2006.02.17 copied by Leah. from php.net
---------------------------------------------- */

class HTTPRequest
{
   var $_fp;        // HTTP socket
   var $_url;        // full URL
   var $_host;        // HTTP host
   var $_protocol;    // protocol (HTTP/HTTPS)
   var $_uri;        // request URI
   var $_port;        // port
  
   // scan url
   function _scan_url()
   {
       $req = $this->_url;
      
       $pos = strpos($req, '://');
       $this->_protocol = strtolower(substr($req, 0, $pos));
      
       $req = substr($req, $pos+3);
       $pos = strpos($req, '/');
       if($pos === false)
           $pos = strlen($req);
       $host = substr($req, 0, $pos);
      
       if(strpos($host, ':') !== false)
       {
           list($this->_host, $this->_port) = explode(':', $host);
       }
       else
       {
           $this->_host = $host;
           $this->_port = ($this->_protocol == 'https') ? 443 : 80;
       }
      
       $this->_uri = substr($req, $pos);
       if($this->_uri == '')
           $this->_uri = '/';
   }
  
   // constructor
   function HTTPRequest($url)
   {
       $this->_url = $url;
       $this->_scan_url();
   }
  
   // download URL to string
   function DownloadToString()
   {
       $crlf = "\r\n";
      
       // generate request
       $req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
           .    'Host: ' . $this->_host . $crlf
           .    $crlf;
      
       // fetch
       $this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
       fwrite($this->_fp, $req);
       while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
           $response .= fread($this->_fp, 1024);
       fclose($this->_fp);
      
       // split header and body
       $pos = strpos($response, $crlf . $crlf);
       if($pos === false)
           return($response);
       $header = substr($response, 0, $pos);
       $body = substr($response, $pos + 2 * strlen($crlf));
      
       // parse headers
       $headers = array();
       $lines = explode($crlf, $header);
       foreach($lines as $line)
           if(($pos = strpos($line, ':')) !== false)
               $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
      
       // redirection?
       if(isset($headers['location']))
       {
           $http = new HTTPRequest($headers['location']);
           return($http->DownloadToString($http));
       }
       else
       {
           return($body);
       }
   }
}

// Example
//$r = new HTTPRequest('가져올 사이트 주소');
//echo $r->DownloadToString();

?>

'Web(웹) Study > PHP' 카테고리의 다른 글

날짜의 요일 구하기  (0) 2010.11.24
php에 mssql을 사용하기  (0) 2010.02.12
빠른 PHP 속도를 유지 하기 위한 것.  (0) 2009.10.06
PHP로 소켓 서버 작성하기  (1) 2009.10.06
PHP 함수정리  (0) 2009.10.06

<!--

// 최상위 체크 로직(chars로 넘긴 값이 있다면 true)

    function containsCharsOnly(input,chars) {

        for (var inx = 0; inx < input.value.length; inx++) {

            if (chars.indexOf(input.value.charAt(inx)) == -1)

                return false;

        }

        return true;

    }

 

 

// 최상위 체크 로직(chars로 넘긴 값이 있다면 false)

 function containsChars(input,chars) {

     for (var inx = 0; inx < input.value.length; inx++) {

        if (chars.indexOf(input.value.charAt(inx)) != -1)

            return true;

     }

     return false;

 }

 

 

 

// 숫자 체크

    function isNum(input) {

        var chars = "0123456789";

        return containsCharsOnly(input,chars);

    }

 

 

 

// 이름체크

 function nameCheck(input){

  var chars = '0123456789~!@#$%^&*()_-+=|{}[]<>,./?';

        return containsChars(input,chars);

 }

 

 

 

// 전화 번호 Check

    function isPhoneCheck(input) {

     var chars = "0123456789( ).-,<>{}[]_~";

        return containsCharsOnly(input,chars);

    }

 

 

 

// 영문 판별

    function isPhoneCheck(input) {

     var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

        return containsCharsOnly(input,chars);

    }

 

 

 

// 영숫자 판별

    function isPhoneCheck(input) {

     var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        return containsCharsOnly(input,chars);

    }

 

 

 

 // 입력값이 숫자,대시(-)로 되어있는지 체크

 function isNumDash(input) {

     var chars = "-0123456789";

     return containsCharsOnly(input,chars);

 }

 

 

 

 // 입력값이 숫자,콤마(,)로 되어있는지 체크

 function isNumComma(input) {

     var chars = ",0123456789";

     return containsCharsOnly(input,chars);

 }

 

 

 

 // 입력값이 사용자가 정의한 포맷 형식인지 체크

 // 자세한 format 형식은 자바스크립트의 ''regular expression''을 참조

 function isValidFormat(input,format) {

     if (input.value.search(format) != -1) {

         return true; file://올바른 포맷 형식

     }

     return false;

 }

 

 

 

 /**

  * 입력값이 이메일 형식인지 체크

  * ex) if (!isValidEmail(form.email)) {

  *         alert("올바른 이메일 주소가 아닙니다.");

  *     }

  */

 function isValidEmail(input) {

 //    var format = /^(\S+)@(\S+)\.([A-Za-z]+)$/;

     var format = /^((\w|[\-\.])+)@((\w|[\-\.])+)\.([A-Za-z]+)$/;

     return isValidFormat(input,format);

 }

 

 

 

 /**

  * 입력값이 전화번호 형식(숫자-숫자-숫자)인지 체크

  */

 function isValidPhone(input) {

     var format = /^(\d+)-(\d+)-(\d+)$/;

     return isValidFormat(input,format);

 }

 

 

 

 // 콤마 없애기

 function removeComma(input) {

     return input.value.replace(/,/gi,"");

 }

 

 

 

 // 문자 변환 함수

    function alterString(str,before,after) {

     var returnStr = "";

     for(i = 0; i < str.length; i++) {

      value = str.charAt(i);

      index = before.indexOf(value);

      if(index >= 0) value = after.charAt(index);

      returnStr += value;

     }

     return returnStr;

    }

 

 

 

// --> 대문자 변환 함수

    function ToUpper(arg) {

     var str1 = "abcdefghijklmnopqrstuvwxyz";

     var str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

     return alterString(arg,str1,str2);

    }

 

 

 

// --> 소문자 변환 함수

    function ToLower(arg){

     var str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

     var str2 = "abcdefghijklmnopqrstuvwxyz";

     return alterString(arg,str1,str2);

    }

 

 

 

// 반각 문자를 전각문자로

    function convert2ByteChar(x_char) {

        var x_2byteChar = ""; //컨버트된 문자

        var c = x_char.charCodeAt(0);

        if(32 <= c && c <= 126) { //전각으로 변환될수 있는 문자의 범위

            if(c == 32) { //스페이스인경우 ascii 코드 32

                x_2byteChar = unescape("%uFFFC");

            } else {

                x_2byteChar = unescape("%u"+gf_DecToHex(c+65248));

            }

        }

        return  x_2byteChar;

    }

 

 

 

// 10진수를 16진수로

    function gf_DecToHex(x_dec) {

        var x_Hex = new Array();

        var x_serial = 0;

        var x_over16 = x_dec;

        var x_tempNum = 0;

        while(x_dec > 15) {

            var x_h = x_dec % 16;          //나머지

            x_dec = parseInt(x_dec/16); //

            x_Hex[x_serial++] = (x_h > 9 ? String.fromCharCode(x_h + 55) : x_h); //16진수코드변환

        }

 

 

 

    //마지막은 몫의 값을 가짐

        x_Hex[x_serial++] = (x_dec > 9 ? String.fromCharCode(x_dec + 55) : x_dec); //16진수코드변환

  

    //,나머지,나머지,.....

        var retValue = "";

        for(var i=x_Hex.length ; i>0 ;i--) {

            retValue += x_Hex[i-1];

        }

        return retValue;

    }

 

 

 

// input box space, &nbsp;등 만으로 넣고 장난 칠때 이들 문자 뺀 길이를 통해 유효성 체크한다...

    function CheckStr(strOriginal, strFind, strChange){

        var position, strOri_Length;

        position = strOriginal.indexOf(strFind); 

        while (position != -1){

            strOriginal = strOriginal.replace(strFind, strChange);

            position = strOriginal.indexOf(strFind);

        }

        strOri_Length = strOriginal.length;

        return strOri_Length;

    }

 

 

 

// 체크 박스에 체크가 되어 있으면 true

 function checkValidator(str) {

  if(str.checked) return true;

  else return false;

 }

 

 

 

 // 비밀번호는 4자 등 최대 최소 길이를 파람으로 주고 처리...

    function checkLength(str,minLng,maxLng){

        var ckstr = str.value.length;

        if (parseInt(ckstr) < parseInt(minLng) || parseInt(ckstr) > parseInt(maxLng)) return false;

        return true;

    }

 

 

 

// 숫자만 받아서 아니면 메세지 보여 주는

    function onlyNumber(objEv) {

        if(!isNum(objEv)){

            alert("숫자만 입력가능합니다.");

            objEv.value = "";

            objEv.focus();

            return;

        }

    }

 

 

 

// 숫자를 체크하다가 6자 등 원하는 만큼 이동후 다음 input 박스로 이동 시키는...

    function goJump(fname, len, goname){

        onlyNumber(fname);

        if (document.all[fname].value.length == len) document.all[goname].focus();

    }

 

 

 

// 주민등록번호 체크 로직

    function check_ResidentNO(str_f_num,str_l_num){ 

        var i3=0

        for (var i=0;i<str_f_num.length;i++){

         var ch1 = str_f_num.substring(i,i+1);

            if (ch1<'0' || ch1>'9') i3=i3+1;

        }

        if ((str_f_num == '') || ( i3 != 0 )) return false;

        var i4=0;

        for (var i=0;i<str_l_num.length;i++){

            var ch1 = str_l_num.substring(i,i+1);

            if (ch1<'0' || ch1>'9') i4=i4+1;

        }

        if ((str_l_num == '') || ( i4 != 0 )) return false;

        if(str_f_num.substring(0,1) < 4) return false;

        if(str_l_num.substring(0,1) > 2) return false;

        if((str_f_num.length > 7) || (str_l_num.length > 8)) return false;

        if ((str_f_num == '72') || ( str_l_num == '18'))  return false;

               

        var f1=str_f_num.substring(0,1)

        var f2=str_f_num.substring(1,2)

        var f3=str_f_num.substring(2,3)

        var f4=str_f_num.substring(3,4)

        var f5=str_f_num.substring(4,5)

        var f6=str_f_num.substring(5,6)

        var hap=f1*2+f2*3+f3*4+f4*5+f5*6+f6*7

        var l1=str_l_num.substring(0,1)

        var l2=str_l_num.substring(1,2)

        var l3=str_l_num.substring(2,3)

        var l4=str_l_num.substring(3,4)

        var l5=str_l_num.substring(4,5)

        var l6=str_l_num.substring(5,6)

        var l7=str_l_num.substring(6,7)

        hap=hap+l1*8+l2*9+l3*2+l4*3+l5*4+l6*5

        hap=hap%11

        hap=11-hap

        hap=hap%10

        if (hap != l7) return false;

        return true;

    }

 

 

 

// 바이트 구하기

    function getByteLen(str){

        return(str.length+(escape(str)+"%u").match(/%u/g).length-1);

    }

 

 

 

 // url 가져오기

    function getUrlAddress(){

        var pageUrl = document.location;

     pageUrl  = new String(pageUrl);

      return pageUrl.substring(0,pageUrl.lastIndexOf("/"));

    }

 

 

 

// 오른마우스 금지, 나중에 해당 주석 풀고 사용

    function rightbutton(e){

        if (navigator.appName == 'Netscape' &&  (e.which == 3 || e.which == 2))

            return false;

        else if (navigator.appName == 'Microsoft Internet Explorer' && (event.button == 2 || event.button == 3))

        {

            alert("죄송합니다!! 정보무단복제를 막기 위하여 오른쪽 마우스 사용을 허용하지 않습니다.");

            return false;

        }

        return true;

    }

 

 

 

//document.onmousedown=rightbutton;

 

// 컨트롤 키 금지, 나중에 해당 주석 풀고 사용

    function checkCtl(){

        if (document.all){

            if(event.keyCode==17) {

                alert("죄송합니다!! 컨트롤키 사용을 허용하지 않습니다.");

                return false;

            }

        }

    }

 

 

 

//document.onkeydown = checkCtl;

 

 function setCookie(name,value) {

     document.cookie = name+"="+escape(value)+";path=/;domain=.kkaok.pe.kr;";

 }

 

 function setCookie(name,value, expires) {

     document.cookie = name + "=" + escape(value) +

     "; path=/; expires=" + expires.toGMTString();

 }

 

 function getCookie(Name) {

     var search = Name + "="

     if (document.cookie.length > 0) { // 쿠키가 설정되어 있다면

         offset = document.cookie.indexOf(search)

         if (offset != -1) { // 쿠키가 존재하면

             offset += search.length

         // set index of beginning of value

             end = document.cookie.indexOf(";", offset)

         // 쿠키 값의 마지막 위치 인덱스 번호 설정

             if (end == -1)

                 end = document.cookie.length

             return unescape(document.cookie.substring(offset, end));

         }

     }

 }

 

 

 

    String.prototype.trim = function(){

        return this.replace(/(^\s*)|(\s*$)/gi, "");

    }

 

//문자 바꾸기, 사용법 var str = 문자열.replaceAll("a", "1"); 

    String.prototype.replaceAll = function(str1, str2) {

        var temp_str = "";

        if (this.trim() != "" && str1 != str2) {

            temp_str = this.trim();

            while (temp_str.indexOf(str1) > -1){

                temp_str = temp_str.replace(str1, str2);

            }

        }

        return temp_str;

    }

 

//-->

이 속도 테스트 보다 더 중요한 것이 PHP보안 입니다. 보안이 가장 중요함당 !!!

PHP로 코딩 함에 있어서 알아야 할 속도 테스트 입니다.
조금더 빠른 PHP 속도를 유지 하기 위한 것이죠 ^^

작은 것이 모여서, 대따 오랜 시간이 걸릴 수 가 있는 것 입니다. !!
되도록이면 속도가 빠른 것을 사용하시는 것이 좋습니다.

물론 함수 마다 기능 마다 장단이 있지만요....^^

다른 비교가 있으면 알려주셍 ^^ 답변 달아 주세용 ^^
계속 적으로 업글 됩니다.

★ mysql 총 게시물 수 세기
<?php     $numresults=mysql_query("select code from $board");     $numrows=mysql_num_rows($numresults);     //2초 이상 ...게시물 10만개 ?> VS <?php     $numresults=mysql_query("select count(code) as code from $board");     $row_num=mysql_fetch_array($numresults);     $numrows=$row_num[code]; // 0.2  ...게시물 10만개 ?> 아래것이 훠얼씬 빠름다.. 도대체 mysql_num_row() 는 왜 만들어 놓은 것일까용???  


★ mysql_fetch_row  > mysql_fetch_array >>> mysql_result 입니다.

row 가 array 보다 약간 빠르고, result 보다는 훠얼씬 빠름당 ^^ row 는 불편한게 숫자로 칼럼을 불러와서 불편합니다. array 가 약간 느리지만, 문자 칼럼을 불러 올 수 있으니 array 쓰는 것도 양호 ^^ 아직도 mysql_result() 를 사용하시나요?  

★print , echo ,printf 함수 속도 비교
HTML 출력 >> echo > print >> printf print 와 printf 함수는 복잡한곳에 적격이고, 약간 느리다. echo 는 단순한곳에 적격이고...빠르다. printf 는 형식화된 출력을 해주므로 그래도 좋죠 ^^  

★  인라인

a.php <?php     $aa="sdsdsdsd";     echo ("       <table>       <td> $aa </td>       </table>       "); ?> 위 랑.. b.php <?php $aa="sdsdsdsd"; ?> <table> <td><?=$aa;?></td> </table> 랑 도대체 어케 코딩 하느냐죠 ? 솔직히 코딩은 a.php 가 편합니다. <?php ?> 를 한번 만 쓰니까 효율적일 수 있습니당.. 그러나 아무리 아무리 PHP가 빠르다고 해도 HTML 이 더 빠릅니당.. !!! 쿠쿠쿠 b.php 처럼 코딩 하는 습관을 가지세용 ^^ 변수가 많아 질 경우 b.php 파일이 느립니다. 그러나 소스 코드 분리 측면에서는 b.php 파일 형태가 좋습니다. 이 부분은 여러분들이나 저나 각종소스를 가지고 연구해 봐야만 할검당 ^^  


★ zend cache , APC ,Bware 캐쉬 비교
Zend cache > APC > Bware zend cache 는 캐쉬 입니다. 울나라에서 포탈에서도 몇군데 사용하죠. PHP 프로그램 변환 없이 속도를 빠르게 해 줍니다. ^^ zend cache 를 살 돈이 없으시다구용? 그러면 APC 나 zend optimizer 를 반드쉬 설치 하세용 !! ■ 그런디 Zend Cache 만한 무료 캐쉬가 나왔다고 합니당...^^ http://www.php-accelerator.co.uk/index.php 도대체 캐쉬의 작동 원리는 어케 되는가? 캐쉬는 여러가지로 작동 할 수 있습니다. 가장 많이 아는 것이 메모리에 페이지를 띄워 놓고 읽어 오는 것입니다. 하드에서 읽는 것 보다 빠르기 때문이죠. 그리고 HTML 로 만드는 것도 캐쉬 입니다.조금 더 빠르다면 캐쉬 라고 할 수 있습니다. 게시판 목록 보기 페이지는 디비 연결이 많습니다. 쓰기 보다 , 읽기가 20배 정도 많습니다. 게시판을 마니 운영해 봤다면 아시겟죠 ^^? 그래서 게시판 목록을 HTML 로 저장 시키고, 쓰기, 삭제 가 있을때 마다 HTML 로 만들어 주는 것 입니다. 그러면 디비 부하는 상당히 줄어 듭니다. 또는 코딩을 할때 enter 이나 tab 키를 많이 사용해서 합니다. 저번에 본 캐쉬는 enter 이나 tab 키를 없에 주는 캐쉬 였습니다. enter 이나 tab 를 없엘 경우 최대 1-2k 정도 절약이 되죵 ^^  


★ ereg_replace <<<  preg_replace 정규표현식
ereg_replace () 가 장난 아니게 느림다. 40개 정도 변환 하는데 1초나 걸려요.preg_replace 는 0.3초 정도요. 되도록이면 preg_replace() 를 사용하세요 !!! www.php.net/preg_replace tood.net preg_replace 강좌 http://www.tood.net/tood/toodboard/toodread.php?board=tootech&tcode=907  


★ foreach , list 함수 속도 차이 35%
foreach($string as $a);  >>>  while(list(,$a) = each($string)); foreach() 를 사용하는 것이 35% 정도 빠릅니다...!!  

★ explode() Vs split() Vs preg_split
explode() 와  split() 와 preg_split 는 문자열을 자르는 함수 입니다. 테스뚜 해보시면 아시겟지만 explode() 가 훨 빠릅니당..!!! 70% 정도 빠릅니다.  



★mysql_connect Vs mysql_pconnect
서로 장단이 있다 합니다. mysql_pconnect 가 더 빠르다고 합니다. persistant 메뉴얼에 영구적인 이렇게 되어 있으니까요.. 일정시간 동안 mysql 을 열어 놓기 때문에, 다시 열 필요가 없어서 빠르다고 합니다. 단점은 계속 열기 때문에 메모리를 많이 잡아 먹슴당...^^ mysql_pconnect 경우는 최소 메모리가 1G 이상 되어야 사용하시는 것이 좋습니다.  


★ 큰따옴표(") , 작은 따옴표(')
큰따옴표는 PHP가 파싱을 합니다. 그러나 작은 따옴표는 파싱을 하지 않습니다. 작은 따옴표를 사용하시는 것이 빠릅니다. 코딩시 echo ' test '.$aaa.' tood '; 요런식으로 하시는 게 가장 빠름당 !!  


★ mysql 데이터 저장 공간 크기 ?
id int(11) unsigned NOT NULL auto_increment,    bbs smallint(5) unsigned NOT NULL,    lens mediumint(8) unsigned NOT NULL,    int 도 무자게 많슴당.. 각각의 크기에 맞게 하는 것이 속도가 빨라 집니당 ^^ not null 를 주는 것도 속도가 빨라 집니당.. 작은 사이트 조회수 경우 1만을 넘기도 힘듭니다. 그럴 경우 smallint 를 사용하시면 됩니다.  


★ where 절에 모든 것은 인덱스를 걸어라 !!!
mysql 에서 쿼리시에 where 절에 사용되는 비교의 칼럼은 반드쉬 인덱스를 거세용 !!! mysql 인덱스 가 여러 분들의 게시판 속도를 업 시켜 줍니당 !!  


★메인페이지에서 속도를 빠르게 하려면, .htm 으로 만드는 것이 좋습니다.
그러니까..제 사이트 페이지 오른쪽 에는 모두 최신 게시물로 디비를 불러오는 부분 입니다. 디비 연결은 부하를 줄 수 있습니다. 그러니까..이예는 사이트가 상당히 활성화된 사이트일 경우 입니다. 하루에 2번 정도 .htm 으로 만들어 페이지를 업시키는 것이 좋습니다. 아무리 PHP가 빨라도 HTML 보다는 빠르지 않습니다.. !!! HTML 로 만드는 것은 생각 할것이 게시판 목록수 만큼 파일이 생성이 됩니다. 1만개 게시물이면 1만개 HTML 이 생기죠. 그런데 조회수가 보통 1000-3000 을 넘는 게시판 경우는 효율성이 중대 됩니다. 그러나 조회수가 100 비스므리 하다면...생각해봐야 합니다. 그러기 위해서는 ★cron 를 알아야 합니다 PHP강좌 게시판에서 cron 으로 검색하세용 !! 윈도우 사용자는 멀 쓰는지 잘 모르겠슴당...아시면 답글 부탁  ^^  


★ 초보자 Vs 전문가
www.zend.com 에서 제가 2000년 5월에 퍼온건데용 ^^   함 주석을 붙일까 해서용^^ Beginner vs Experienced    Author:  Boaz Yahav    Date  23/05/2000    Beginner : echo "$var";   Experienced : echo $var;   Beginner:echo "<a href=\"http://www.php.net\">PHP</a>";  ;; Experienced : ?><a href="http://www.php.net">PHP</a>; color="#0000CC"><?  ... ?>   ◆ "(따옴표) 가 굉장히 중요한것이라는 한 대목이죵 ^^ 전 보통의 경우 php 변수 값이 들어갈 경우는 초보자 처럼 쓰구요 ^^ 안들어 갈 경우 는 전문가 처럼 씀다. Beginner : $a[0]=1; $a[1]=2; $a[2]=3;   Experienced : $a = array(1,2,3, 1);   둘다 사용하는 데요. 전문가 쪽이 편함다. ^^ Beginner : if($a>1) { $b=2; } else { $b=3; }   Experienced : $b = ($a>1) ? 2:3;   요건 완존히 소스 어렵게 짜는 넘이 최고 라는 소리 같네용 ^^ 전문가 쪽것은 C 언어 에서 배웠는데도 역시 전 if 씀다. ^^ Beginner : $result=mysql_query(...);   Experienced: $result=mysql_query(...) OR die            (mysql_error());   요즘 들어 새삼 전문가 쪽으로 씀다.^^ 보통의 경우 <?php $result=mysql_query(...)   if (!$result) {      echo error()."<P>";      echo errno(); } ?> 이렇게 사용함다. ^^ or 이 설명이고 no 가 에러 번호 일 검다. ^^  


★MySQL,ADODB,PHPLib,PEAR 벤치마킹  
ADODB > PHPlib > PEAR MySQL     1.14      - ADODB     1.45     27% PHPLib    1.60     40% PEAR     2.87     152% (fetchInto) MySQL,ADODB,PHPLib,PEAR  는 모두 데이터베이스 인가요? 당근 아닙니다. MySQL만 데이터베이스 구요. ADODB,PHPLib,PEAR 는 PHP 프로그램 입니다. 3개 다 MySQL연결을 편하게 하는 클래스 프로그램 입니다. 그런디 벤치 마킹 결과 MySQL 에서 직접 쿼리하는 것 다음으로 ADODB 가 뽑혔슴당 ^^ PEAR 가 굉장히 늦군요. PEAR DB 나 ADODB 를 사용해 보았는데, 움..역시나 ADODB 가 좋군요. 오라클, mysql , ms sql 연결시 1개의 API 만 사용할 수 있는 프로그램 들 이 PEAR 과 ADODB 입니당 ^^  

★ 페이지 네비게이션- 페이지 분활
페이지 분활도 속도 차이가 납니다. 각각의 페이지 분활을 테스트 해보시면 아시겟지만, 10만개,20만개의 데이터를 넣어 보세요. 빠른것은 0.03초 정도, 느린것은 3초나 걸립니다. 인덱스를 걸어서 빨리 뜨는데, 머가 늦는 걸까 했는데, 페이지 네비게이션 알고리즘이 문제더군요. ^^  

★ 속도 테스트는 어케 하는가 ? microtime() 사용하면 됩니다.
<?php function pageTime($page) {  $mstart = explode(" ", $m);  $mend = explode(" ", microtime());  $mtime = ($mend[1] - $mstart[1]) + ($mend[0] - $mstart[0]);  echo " $m[1]  $mend[1]<P>";  echo " $m[0]  $mend[0]<P>";  print("tood.net 페이지 로딩 시간 : " . $mtime . " microseconds"); } pageTime(basename($PHP_SELF)); ?>    

조금 더 빠른 쿼리
$sql = "SELECT table.column FROM table WHERE criteria LIKE $myrow[variable]"; 아래 처럼 하면 파싱 되지 않기 때문에 아주 아주 쪼금 빨라 짐다..0.0000x 초; $sql = "SELECT table.column FROM table WHERE criteria LIKE " . $myrow['variable'];  

최적화 컴파일 옵션 사용 !
PHP counfigure 시에 최적화 방법 입니다. http://www.tood.net/tood/toodboard/toodread.php?board=tootech&tcode=1070   

'Web(웹) Study > PHP' 카테고리의 다른 글

php에 mssql을 사용하기  (0) 2010.02.12
PHP에서 "HTTP / HTTPS" Request하기  (0) 2009.11.18
PHP로 소켓 서버 작성하기  (1) 2009.10.06
PHP 함수정리  (0) 2009.10.06
무조건 알아야 할 PHP 속도 테스트 14 가지  (0) 2009.10.06
PHP로 소켓 서버 작성하기


대상 독자
요구사항
1 개요 - 소켓 서버란 무엇인가?
1.1 소켓의 형태
2 PHP 소켓 함수
2.1 PHP에서 소켓 만들기
2.2 실용 서버 만들기
2.3 실용적인 예
2.4 보안
가능한 기능 추가와 확장
저자에 관해

알아두기

이 자료는 http://www.zend.com/zend/tut/tutorial-staub3.php/에 있는
Writing Socket Servers in PHP를 제가 허접번역 및 내용을 추가 및 생략한 것입니다.
이미 다 아시는 내용 이시겠지만, 이해해 주시면 감사하겠습니다.
질문이나 번역을 바라는 주제가 있으시면,
이메일 또는 코멘트를 이용해 주세요. 참고로 전 영어, PHP 둘다 왕초보^^;.

대상 독자
인터넷 소켓 서버를 만들기 위해 PHP 소켓 함수 사용에 관심있는 분들..

미리 준비할 것
       
        * PHP 소켓 라이브러리. 이것은 컴파일 할 때 -enable-sockets 설정 옵션을 주시면 됩니다.
        * PHP의 CLI (Command Line Interface) 버전. 이것은 소켓서버가 커멘드 라인에서 실행하기 때문입니다.
        * 리눅스 운영체제
비록 리눅스를 사용한 따라하기이지만, 윈도우나 유닉스환경에서도 됩니다.
윈도우에서, PHP 소켓은 php.ini에서 externsion=php_sockets.dll부분의 주석을 제거해야
사용할 수 있습니다.

1 개요 - 소켓 서버란 무엇인가?

소켓 서버는 소켓 서버에 들어오는 요청과 응답을 대기하고있는 특정 포트에 할당하는 서비스입니다.
이메일 서비스(POP3, SMTP)와 웹서버는 소켓 서버의 좋은 예입니다.
HTTP(Web)서버는 들어오는 요청에 대해 포트 80에서 대기하고,
서버 안에 있는 HTML과 다른 파일(이미지, 동영상,문서)을 클라이언트 사용자에게 서비스 합니다.

소켓 서버는 주로 서비스나 데몬으로 끊임없이 실행됩니다.

쉽게 설명하자면, 우리가 네트워크 프로그래밍을 한다는 의미는 소켓이 제공하는 함수를 이용하여 프로그래밍을 한다는 의미입니다.
일상적으로, 소켓 프로그래밍과 네트워크 프로그래밍은 거의 같은 의미로 사용되고 있습니다.

1.1 소켓의 종류

정보가 인터넷으로 보내질 때, 그것은 주로 패킷으로 나누어집니다.  
왜냐하면 큰 용량을 패킷이라는 작은 단위로 쪼갠후에 보내야 하기 때문입니다.

패킷으로 정보를 쪼갤 때 두가지 다른 프로토콜이 있는데, 정보 형태에 대해 전송 필요조건에 의존하기 때문입니다.        
        * TCP(Transmmission Control Protocol) - 전송 패킷은 다른 끝에서 번호가 붙여지고 끝에가서 조립된다. 그들은전체 메시지를 형성하기 위해 조립된다 .
        TCP는 데이터의 손실이 없습니다.(만약 패킷을 잃어버리면, 재전송합니다.), 이메일처럼 완전한 받아야 하는 파일을 보낼때 적합합니다.
         * UDP(User Datagram Protocol) - 이것은 비연결 프로토콜입니다.
        TCP처럼 IP 프로토콜 위에서 실행됩니다.
그 차이는 UDP는 약간의 에러 복구 서비스를 제공하고 신뢰성이 없습니다.
UDP는 특별히 음악, 동영상 스트리밍처럼 스트리밍 데이타에 적합합니다.

2. PHP 소켓  함수

PHP 는 저 수준에서 소켓을 처리할 수 있습니다.
PHP3에서, PHP는 fsockopen()과 관련 함수로 처리하는 소켓을 도입하였습니다.
(네트워크 부분은 PHP공식 매뉴얼 http://php.net/network를 보세요).
PHP4에서는, PHP의 소켓은  BSD 스타일 소켓에 저수준 연결의 도입으로 멋지게 확장되었습니다.

참고: PHP에서 소켓 함수는 여전히 실험적이지만, 다음 버전에서 더욱 강화될 것입니다.
PHP 소켓함수는 잘만 작성하면 쓸만하다는 것을 테스트는 보여줍니다.

2.1. PHP로 소켓 만들기

PHP에서 저수준 소켓을 만드는 것은 C와 유닉스 소켓 프로그래밍에서 소켓 함수를 사용한것과 매우 비슷합니다.

간단한 예제로 시작해봅시다. 9000 포트에서 연결을 대기하는 소켓 서버는 입력으로 문자열을 받아들이고, 모든 공백 문자는 제거하고, 반환한다.


#!/usr/local/bin/php -q

<?
// 무한정 실행하기 위해 시간한계를 0으로 설정한다.
set_time_limit (0);

// 대기할 IP 주소와 포트번호를 설정한다
$address = '192.168.0.100';
$port = 9000;

// TCP 소켓을 만든다.
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// IP 주소와 포트번호를 소켓에 결합
socket_bind($sock, $address, $port) or die('Could not bind to address');
// 접속을 위해 대기를 시작한다
socket_listen($sock);

/* 들어오는 요청을 받아들이고 자식 프로세스로 그들을 처리한다 */
$client = socket_accept($sock);

// 클라이언트가 입력한 1024 바이트를 읽는다.
$input = socket_read($client, 1024);

// 입력받은 문자열에서 공백을 제거한다.
$output = ereg_replace("[ \t\n\r]","",$input).chr(0);

// 클라이언드에 출력을 보낸다.
socket_write($client, $output);

// 자식 프로세스를 닫는다
socket_close($client);

// 주 소켓을 닫는다
socket_close($sock);
?>

이 프로그램을 실행하려면, 첫 줄 #!/usr/local/bin/php -q 가 PHP CLI(or CGI) binary의 위치에 있어야 합니다.
여러분은 소스파일의 실행모드를 바꾸는 것이 필요합니다.
(chmod 755 socket_server.php)
실행하려면,  커멘드 라인에서 ./socket_server.php치고 엔터.
외관상 이 프로그램은 아무일도 않합니다.

그럼 각각의 라인을 자세히 살펴봅시다.

        * #!/usr/local/bin/php -q
        PHP CLI 실행파일을 실행합니다. -q 옵션을 쓰면 HTTP 헤더를 출력하지 않습니다.

        * $sock =sock_create(AF_INET, SOCK_STREAM, 0)
        '주인' 소켓을 만듭니다. 이 소켓은  들어오는 요청을 위해 대기할 것이고, 클라이언트를 위해 새로운 소켓을 생성할것입니다.

PHP manual에 보면 (http://www.php.net/socket_create): AF_INET는 IPV4 프로토콜의 도메인 타입입니다.
참고: 만약 UDP 소켓을 열기위해서는, SOCK_STREAM을 지우고 SOCK_DGRAM을 쓰십시오.

        * socket_bind($sock, $address, $port) or die('Could not bind to address')
        소켓을 입력된 주소와 포트에 결합합니다.

        * socket_listen($sock)
        저장된 포트번호에서, 들어오는 연결을 대기합니다. 만약 연결되면, 자식 소켓을 생성할 것이다.

        * $cliend = socket_accept($sock)
        마스터 소켓에서 접속을 받아들인다.

        * $input = socket_read($client, 1024)
        받아들인 소켓에서 1024 바이트를 읽는다,
       
        * $output = ereg_replace("[\t\n\r]","",$input).chr(0)
        정규식을 사용하여 모든 공백 문자를 제거한다.
       
        *socket_write($client, $output)
        스트림 소켓으로 테이터를 전송한다.
       

2.2 실제 서버 제작하기

지금 여러분은 소켓을 설정하고 대기하기 위해 필요한 기본 절차를 배웠습니다.
여러분은 쓸모있는 서버를 만들 준비가 되어있습니다.

위에 있는 소스코드를 보면, 이 프로그램은 단 한번 실행되고 종료됩니다.
그것은 소켓서버를 생성하기위해 요구되는 단계를 설명하기에는 좋습니다.
그러나 그것은 현실 상황에서는 적합하지 않다.
여러분의 프로그램이 실행 되고, 들어오는 요청에 응답하자마다. 프로그램이 종료되기를 원치않을 것입니다.
다시말하면, 계속 실행되야만 한다.

우리는 그러므로 프로그램은 계속 실행하기 위한 방법이 필요합니다.

우리가 명확히 exit 문을 명령할때까지, 우리는 while(true) { /* 놀지말고 일 좀 해라 */ } 이렇게 반복문을 계속적으로 사용할수 있습니다.
우리는 위의 예를 다음과 같은 기능을 추가하여 확장할 것입니다.

        *  끝없이 프로그램을 실행하게한다.
        * 종료 기능을 만든다.
        * 여러명이 접속해도 처리할수 있도록 한다.

#!/usr/local/bin/php -q
<?

// 끝없이 실행하기 위해 시간 한계를 0으로 설정한다
set_time_limit (0);

// 서버가 대기할 ip 주소와 port 번호를 설정한다.
$address = '192.168.0.100';
$port = 9000;
// 동시에 접속할 수 있는 사용자를 10명으로 한정한다.
$max_clients = 10;

// 클라이언드 정보를 얻을 배열
// 다시 말하자면, 사용자가 10명을 동시에 받아들이겠다면,
// 배열 크기를 10개로 잡아야 합니다.
$clients = Array();

// TCP 스트림 소켓 생성
$sock = socket_create(AF_INET, SOCK_STREAM, 0);

// 소켓을 아이피주소/포트에 결합
socket_bind($sock, $address, $port) or die('주소 지정에 실패했습니다.');

// 연결을 대기를 시작한다.
socket_listen($sock);

// 무한 루프 실행
while (true) {
    // 읽기위해 클라이언트 대기 소켓을 설정한다
    $read[0] = $sock;
    for ($i = 0; $i < $max_clients; $i++)
    {
        if ($client[$i]['sock']  != null)
            $read[$i + 1] = $client[$i]['sock'] ;
    }
    // socket_select()에 블럭킹 호출을 설정한다.
    $ready = socket_select($read,null,null,null);

    /* 만약 새로운 접속이 되면, 그것을 클라이언트 배열에 추가한다 */
    if (in_array($sock, $read)) {
        for ($i = 0; $i < $max_clients; $i++)
        {
            if ($client[$i]['sock'] == null) {
                $client[$i]['sock'] = socket_accept($sock);
                break;
            }
            elseif ($i == $max_clients - 1)
                print ("너무 많은 사용자")
        }
        if (--$ready <= 0)
            continue;
    } // 조건문 if in_array의 끝
    
    // 만약 클라이언트가 쓰기를 시도하면, 바로 그것을 처리한다
    for ($i = 0; $i < $max_clients; $i++) // for each client
    {
        if (in_array($client[$i]['sock'] , $read))
        { // 사용자로부터 입력을 받아서..
            $input = socket_read($client[$i]['sock'] , 1024);
        // 만약 입력이 없으면...
            if ($input == null) {
                // Zero length string meaning disconnected
                unset($client[$i]);
            }
            $n = trim($input);
        // 만약 클라이언트가 'exit'를 입력하면,
            if ($input == 'exit') {
             // 요청에 따라 연결을 종료한다
                socket_close($client[$i]['sock']);
                                // 만약 아니면...
            } elseif ($input) {
             // 공백문자를 제거하고,
                $output = ereg_replace("[ \t\n\r]","",$input).chr(0);
                // 사용에게 소켓 스트림을 통하여 문자열을 보낸다.
                socket_write($client[$i]['sock'],$output);
            }
        } else {
            // 소켓 종료
            socket_close($client[$i]['sock']);
            unset($client[$i]);
        }
    }
} // while문 끝
// 주인 소켓 종료
socket_close($sock);
?>

기본 기능은 처음 예제와 같다. 다만 추가된 특징은 사용자가 문자열 'exit'를 프로그램에 보내면,
프로그램은 연결을 끝낼것이다.

이 프로그램은 반복문을 제외하고, 처음 프로그램과 매우 비슷하다.
소스는 4개의  기본 블럭이 있다.

        1 읽기위해 소켓 설정
        2 새로운 클라이언트를 대기하고 $client 배열로 그것을 설정한다.
         3 클라이언트 대기하고 입력을 기록한다.
        4 클라이언트 입력을 처리한다.

이 예에서, 새 함수는 socket_select($read, null, null, null)입니다.
이 함수는 소켓 배열에서 select() 시스템 호출을 실행하고 상태가 바뀔때까지 기다립니다.
이것은 그 상태가 바뀔때까지 막고 있다가, 누군가 접속하여 그 상태가 바뀌면 그것을 처리합니다.

마지막 요점으로, 여러분은 연결된 다른 클라이언드에 정보를 뿌리고 싶을때(예를 들면 다-대-다 채팅 환경을 말한다)를 알아낼 수있습니다.
이것은 다음과 같은 코드로 저장될수 있다.
<PRE>
$output = '이것은 제가 여러명에게 보내고 싶은 메시지입니다'.chr(0);
for ($j = 0; $j < MAX_CLIENTS; $j++) // 각각의 클라이언트
{
    if ($client[$j]['sock']) {
        socket_write($client[$j]['sock'], $output);
    }
}

원문에서 broadcast라는 말이 나오는데 우리 말로는 '방송'으로 번역하고, &nbsp;
여기서는 한번에 여러명에게 정보를 보내는 것을 애기합니다. 다르게 애기하면 '대량 살포' 이런 의미입니다.

socket_select()함수 역시 중요한데. 부가 설명을 하자면,
select라는 말처럼 기다리고 있다가, 튀는 놈, 예를 들면 사용자가 접속하면, 그 놈을 선택(select)하여
넘겨주면 그걸 처리해주는 것입니다.

2.3 실용적인 사용

지금 우리는 소켓 서버 생성의 기초를 배웠다. 만약 한계가 있다면, 우리의 상상력입니다.

        *  채팅 서버(텍스트 또는 그래픽 기반). 이것은 재미있으면서 진짜 어플리케이션이 될 수 있습니다.
        *  실시간 정보 스트리밍 (뉴스, 주식..기타등등)
        *  스트리밍 멀티미디어 (이미지, 동영상과 사운드)
        *  인증 서버
        *  간단한 웹, POP3, SMTP 그리고 FTP 서버.

좀더 자세하게 말하자면, 소켓 라이브러리는 서버와 마찬가지로 클라이언트 프로그램을 만들 수 있다.

2.4 보안

보안은 접근 가능한 온라인 프로그램 생성할때 고려되어야 한다.
이것은  계속 실행되는 서버 소켓과같이 일반적인 PHP 스크립트에도 해당됩니다.

여러분이 보안 정책을 계획할때, 고려하는 많은 사실이 있다. 여기 몇가지 나열하겠다.


        * 파일 접근 - 여러분은 파일 접근을 제한해야한다. 만약 웹서버같은 것이 파일 접근을 허락하면
        , 여러분은 특정 폴더에서 파일에 접근하게 해야한다. 다른 좋은 개념은
       
        * 인증 - 보안에 약한 서버를 위해, 여러분은 인증을 사용하기를 추천한다. 여러분이
        플래시나, 비주얼 베이직으로 사용자 프론트-엔드를 만들더라도, 그것은 신뢰성이 없습니다.
        누군가 네트워크 접속과 "sniff"할수 없을 것이다.

인증을 하기 위한 한가지 좋은 방법으로, 사용자가 성공적으로 스스로 인증하기 전까지 어떤 시도도 허락하지 않는 것이다.
(위에서 예를 들면 인증 하자마자, $client[$i]['authenticated'] = true )
       
        * 암호화 - 암호화는 중요한 정보를 막기위한 대단히 좋은 방법입니다. 암호화는 특히 위에 애기한 인증과 함께 사용하면
대단히  유용합니다. 운이 좋게도 PHP는 뛰어난 암호화 라이브러리를 제공합니다.
자세한 내용은 (http://www.php.net/mcrypt)

3. 가능한 기능 추가와 확장
        * PCNTL을 사용하여 프로세스 제어와 쓰레드를 추가한다.
         * 프론트-앤드 인터페이스(다시 말해 GUI 화면)는 C++, VB, Flash (XMLSockets를 사용), 자바 또는 TCP/IP 또는 UDP 소켓을 지원하는 모든 소프트 웨어를 사용하려 작성할 수 있다.
        * 만약 서버가  시험삼아 돌아가게되면, 당신은 모니터에 에러 메시지에 출력하는 대신 텍스트 화일이나 데이터 베이스 기록되는 사용자 에러 핸들링 함수를 생성을 원할것이다.

글쓴 이에 대해
집에서 놀고 있는 백수.
PHP 함수정리

1. 날짜 및 시간 관련함수

*time()
-용도: 현재 시각을 timestamp값으로 구한다.
-방법: time()

*date()
-용도: 사용자가 지정한 형태로 시간을 표시. 특정시간의 날짜와 요일등을 배열로 리턴한다.
-방법: date("표시할 시간의 포맷형태","특정한 timestamp값")

*mktime()
-용도: 지정된 날짜를 timestamp값으로 변환한다.
-방법: mktime(시,분,초,월,일,년)

*checkdate()
-용도: 날짜와 시간이 올바른 범위 안에 있는지 검사한다.
-방법: checkdate(월,일,년)

*getdate()
-용도: 특정timestamp값으로 시간,요일,날짜정보를 배열로 반환한다.
-방법: getdate(timestamp값) 또는 getdate()

*gettimeofday()
-용도: 현재 시스템의 현재 시간 정보를 배열로 리턴한다.
-방법: gettimeofday()

*gmmktime()
-용도: 그리니치표준 시간으로 지정한 날짜의 timestamp값을 리턴한다.
-방법: gmmktime(시,분,초,월,일,년)

*strftime()
-용도: 특정한 포맷으로 날짜 정보를 출력하는데 언어를 지정할수 있다.
-방법: strftime("표시할 시간의 포맷형태","특정시간의 timestamp값")

*microtime()
-용도: 현재시간의 마이크로타임 값과 timestamp값을 표시한다.
-방법: microtime()

*localtime()
-용도: 현재 서버의 로컬 타임을 표시
-방법: localtime() 또는 localtime("timestamp값")

2. 문자열 처리함수

*addslashes()
-용도: 작은따옴표 큰따옴표와 같은 특정문자 앞에 역슬래시 문자를 붙인다.
-방법: addslashes()

*stripslashes()
-용도: allslashes로 역슬래시 처리된 문자를 원상태로 되돌린다.
-방법: stripslashes()

*htmlspecialchars()
-용도: HTML코드를 소스 그대로 출력해준다.
-방법: htmlspecialchars()

*nl2br()
-용도: 문자열에 포함된 개행 문자를 <br>태그로 모두 바꿔준다.
-방법: nl2br()

*echo()
-용도: 문자열 출력
-방법: echo("변수명" 또는 "문자열")

*sprintf()
-용도: 포맷 문자열을 통해 지정해 준 포맷으로 문자열을 표시한다.
-방법: sprintf("포맷","변수명")

*printf()
-용도: 지정할 수 있는 포맷에 따라 문자열을 출력한다.
-방법: printf("포맷","변수명")

*explode()
-용도: 문자열을 지정해준 구분자로 분리하여 배열에 저장한다.
-방법: explode("구분자","문자열인수")

*implode()
-용도: 구분자로 나누어 배열에 담은 문자열을 다시 지정해준 구분자로 연결하여 전체 문자열을 반환한다.
-방법: implode("구분자",배열변수명)

*join()
-용도: implode()와 동일한 기능을 수행한다.
-방법: join("/", "배열변수명")

*split()
-용도: 주어진 문자열을 정규표현식의 패턴에 따라 분리하여 배열에 저장한다.
-방법: implode("정규표현식","문자열")

*strcmp()
-용도: 두개의 문자열을 비교하여 참이면1, 거짓이면 0을 반환한다.
-방법: strcmp("문자열","문자열") 또는 strcmp("문자열","변수명") 또는 strcmp(변수명, 변수명)

*substr()
-용도: 문자열에서 특정시작 문자부터 길이만큼의 문자열을 추출하여 반환한다.
-방법: substr("문자열", 시작문자번호, 문자열의 길이)

*strchr()
-용도: 문자열이 처음으로 나타나는 위치부터 끝까지 반환
-방법: strchr("문자열","찾을 문자열")

*strstr()
-용도:strchr()함수와 동일한 수행을 한다.
-방법: strstr("문자열","찾을 문자열")

*strrchr()
-용도: 문자열이 마지막으로 나타나는 위치부터 끝까지 반환한다.
-방법: strrchr("문자열","찾을문자열")

*strpos()
-용도: 문자열 대신 처음으로 나타나는 위치를 숫자로 반환, 이때 숫자는 0부터 시작.
-방법: strpos("문자열","찾을 문자열")

*strrpos()
-용도: 찾고자 하는 문자열에서 마지막으로 나타나는 위치를 반환한다.
-방법: strrpos("문자열", "찾을 문자열")

*strlen()
-용도: 문자열의 길이를 반환한다.
-방법: strlen($변수명) 또는 strlen("문자열")

*strtolower()
-용도: 알파벳 대문자를 모두 소문자로 바꾸어 반환한다.
-방법: strtolower("문자열")

*strtoupper()
-용도: 알파벳 대문자를 소문자로 바꾸어 반환한다.
-방법: strtoupper("문자열")

*ucfirst()
-용도: 알파벳 문자열의 첫 글자를 대문자로 반환한다.
-방법: unfirst("문자열")

*ucwords()
-용도: 알파벳 문자열의 첫 글자를 대문자로 반환한다.
-방법: ucwords("문자열")

*strrev()
-용도: 인자로 전달한 문자열의 순서를 역전시킨다.
-방법: strrev("문자열")

*strtr()
-용도: 문자열에서 변경하고자 하는 문자열을 변경할문자열로 1:1 변경해준다.
-방법: strtr("문자열","변경하고자하는 문자열","변경할 문자열")

*str_replace
-용도: 문자열 중에 변경하고자 하는 문자열을 찾아 변환한다.
-방법: str_replace("찾을 문자열","변경할 문자열","문자열 원본")

*chop()
-용도: 문자열의 뒷부분의 공백 문자를 제거한 후 반환한다.
-방법: chop("문자열")

*trim()
-용도: 문자열의 앞과 뒤에 있는 공백을 제거한 후 문자열을 반환한다.
-방법: trim("문자열")

*quotemeta()
-용도: 메타문자 앞에 역슬래시를 붙인다.
-방법: quotemeta()

*ord/chr()
-용도: ord()함수는 문자열에서 첫번째 문자에 아스키코드값을 반환하고 chr()함수는 아스키함수에 해당하는 문자를 반환한다.
-방법: ord("문자열"), chr("아스키값")

*parse_str()
-용도: get방식과 같은 형태의 변수형을 변수와 값으로 받을 수 있게 해준다.
-방법: parse_str(변수명)

3.파일관련함수

*fopen()
-용도: 로컬경로의 파일이나 url경로의 파일을 읽기 모드나 쓰기 모드로 열어준다.
-방법: fopen("절대경로명/파일", "모드")또는 fopen("url주소", "모드")

*fclose()
-용도: fopen으로 열린 파일을 닫는다.
-방법: fclose($fp)

*fread()
-용도: 파일포인터가 가리키는 파일의 내용을 지정한 크기만큼 읽어 들인다.
-방법:fread($fp,"읽어들일 바이트")

*feof()
-용도: 현재 파일 포인터가 파일의 끝인지를 알려주는 함수
-방법: feof($fp)

*fgets()
-용도: 파일을 읽어올때 한줄씩 읽어온다.
-방법: fgets($fp,"읽어들일 바이트")

*fputs()
-용도: 파일을 a 또는 w 모드로 열어 문자열을 파일에 기록한다.
-방법: fputs($fp, "문자열")

*fwirte()
-용도: 파일을 기록한다.
-방법: fwrite($fp, "문자열")

*fpassthru()
-용도: 파일포인터의 현재 위치에서 파일의 끝까지 읽어 들이도록 한다.
-방법: fpassthru($fp)

*readfile()
-용도: fpassthru와 비슷하지만 fopen()없이 직접 바로 파일을 읽어들일 수 있다. 읽어들인 파일의 절대경로를 포함한다.
-방법: readfile("파일의 절대경로 또는 상대경로/파일명")

*fgetc()
-용도: 파일로부터 한문자를 읽어들인다.
-방법: fgetc($fp)

*filesize()
-용도: 파일의 크기를 바이트수로 반환한다.
-방법: filesize("파일경로/파일명")

*file_exists()
-용도: 파일이름으로 지정한 파일이 존재하는지 검사한다.
-방법: file_exists("파일경로/파일명")

*is_file()
-용도: 파일이름으로 지정한 이름이 파일면 true를 반환한다.
-방법: is_file("파일경로/파일명")

*is_dir()
-용도: 파일이름으로 지정한 이름이 디렉토리일경우 true를 반환한다.
-방법: is_dir("파일경로/파일명")

*is_link()
-용도: 파일이름으로 지정한 이름이 심볼릭 링크일경우 true를 반환한다.
-방법: is_link("파일경로/파일명")

*is_escutable()
-용도: 파일이름으로 지정한 파일이 실행 가능한 파일이면 true를 반환한다.
-방법: is_excutable("파일경로/파일명")

*is_readable()
-용도: 파일이름으로 지정한 파일이나 디렉토리가 읽기 가능한경우 true를 반환한다
-방법: is_readable("파일경로/파일명 또는 디렉토리명")

*is_writeable()
-용도: 파일이름으로 지정한 파일이나 디렉토리가 쓰기 가능한 경우 true를 반환한다
-방법: is_writeable("파일경로/파일명 또는 디렉토리명")

*copy()
-용도: 파일을 복사하고 제대로 수행이 되면 true를 반환한다.
-방법: copy("파일경로/복사할 파일명", "파일경로/복사된 파일명")

*rename()
-용도: 파일을 이름을 바꾼다. 제대로 수행이 되면 true를 반환한다.
-방법: rename("파일경로/변경할 파일명", "파일경로/변경후 파일명")

*unlink()
-용도: 파일을 삭제한다. 제대로 수행될 경우 true를 반환한다.
-방법: unlink("파일경로/삭제할 파일명")

*mkdir()
-용도: 디렉토리를 생상하고 동시에 권한도 함께 지정할 수 있다.
-방법: mkdir("경로/디렉토리명")

*rmdir()
-용도: 디렉토리 삭제
-방법: rmdir("경로/디렉토리명")

*basename()
-용도: 경로명과 파일명을 받아 파일명만을 반환한다.
-방법: basename("파일경로/파일명")

*dirname()
-용도: 경로명과 파일명을 받아 경로명만을 반환한다.
-방법: dirname("파일경로/파일명")

*file()
-용도: 줄단위로 읽어서 각 줄으 문자열을 배열로 하여 반환한다.
-방법: dirname("파일경로/파일명")

4.디렉토리 관련함수

*opendir()
-용도: 지정한 디렉토리에 대한 핸들을 얻는다.
-방법: opendir("디렉토리 경로")

*closedir()
-용도: opendir()함수 호출로 열어둔 디렉토리에 대한 핸들을 닫는다.
-방법: closedir($od)

*readdir()
-용도: 디렉토리에 있는 모든 디렉토리 및 파일들의 이름을 읽어 배열의 형태로 반환
-방법: readdir($od)

*rewinddir()
-용도: 디렉토리 핸들의 포인터 위치를 제일 처음으로 되돌린다.
-방법: rewinddir($od)

*chdir()
-용도: 지저한 디렉토리로 바꾼다.
-방법: chdir("경로명/디렉토리명")

*dir()
-용도: 디렉토리 관련 함수를 사용할 수 있는 클래스
-방법: dir("경로/디렉토리명")

5. URL관련함수

*parse_url()
-용도: url을 입력하면 해당 url에 대한 정보를 연관 배열로 저장하여 반환
-방법: parse_url("URL주소")

*urlencode()
-용도: 데이터를 url인코딩해준다.
-방법: urlencode("문자열")

*urldecode()
-용도: url을 통해 넘어온 값 중 인코딩된 문자열을 디코딩한다.
-방법: urldecode("문자열")

6.변수 및 수학 관련함수

*gettype()
-용도: 변수형을 반환한다.
-방법: gettype("변수명")

*settype()
-용도: 변수형을 변환한다.
-방법: settype("변수명", "변수타입")

*intval()
-용도: 변수값을 정수형 값으로 변환
-방법: intval("변수값")

*doubleval()
-용도: 변수값을 실수형 값으로 변환한다.
-방법: doubleval("변수값")

*strval()
-용도: 변수를 문자형 값으로 변환한다.
-방법: strval("변수값")

*isset()
-용도: 변수가 존재하는지 확인한다.
-방법: isset("변수명")

*unset()
-용도: 변수를 삭제한다.
-방법: unset("변수명")

*empty()
-용도: 변수에 값이 존재하는지 확인하여 없으면 true를 있으면 false를 반환한다.
-방법: empty("변수명")

*is_array()
-용도: 변수의 형이 배열인지 확인한다.
-방법: is_array("변수명")

*is_double
-용도: 변수의 형이 더블형인지 확인한다.
-방법: is_double("변수명")

*abs()
-용도: 변수의 절대값을 반환
-방법: abs("변수명")

*round()
-용도: 변수의 반올림한 값을 구한다.
-방법: round("변수명")

*ceil()
-용도: 변수 값의 무조건 올림 값을 구한다.
-방법: ceil("변수명")

*floor()
-용도: 변수값의 무조건 내림 값을 구한다.
-방법: floor("변수명")

*pow()
-용도: 인자 값만큼 제곱승 한 값을 구한다.
-방법: pow("변수명", "제곱할 횟수")

*max & min()
-용도: 최대값과 최소값을 구한다.
-방법: max("숫자값", "숫자값",...) min("숫자값", "숫자값",...)

7.기타 알아두어야 할 함수

*count()/sizeof()
-용도: 배열의 크기를 구한다.
-방법: count("변수명") sizeof("변수명")

*each()/list()
-용도: 배열의 내용을 출력할때 사용한다.
-방법: each("배열변수명"), list("배열의 인자를 받을 변수명", "배열의 인자를 받을 변수명"...)

*end()/next()/reset()
-용도: 현재 배열의 포인터를 끝이나 다음으로 이동시킨다. reset은 배열포인터를 다시 처음으로 되돌린다.
-방법: end("배열변수명") next("배열변수명")

*exec()
-용도: 리눅스 서버의 내부 명령어를 사용하게 한다.
-방법: exec("리눅스명령어", "결과를 저장할 변수명" ,"에러발생시 저장할 변수명")

*number_format()
-용도: 천단위마다 ","를 붙여준다.
-방법: number_format("변수명", "소수점자리수", "소수점 표시마크변경", "천단위 표시 마크변경")

*show_source() / highlight_string()
-용도: php파일의 소스를 보여준다.
-방법: show_source("경로명/파일명") highlight_string("변수명")

*uniqid()
-용도: 유일한 아이디 값을 만들어준다
-방법: uniqid()
★ 무조건 알아야 할 PHP 속도 테스트 14 가지 ◆◇◆◇◆◇      


PHP로 코딩 함에 있어서 알아야 할 속도 테스트 입니다.
조금더 빠른 PHP 속도를 유지 하기 위한 것이죠 ^^

작은 것이 모여서, 대따 오랜 시간이 걸릴 수 가 있는 것 입니다. !!
되도록이면 속도가 빠른 것을 사용하시는 것이 좋습니다.

물론 함수 마다 기능 마다 장단이 있지만요....^^


다른 비교가 있으면 알려주셍 ^^ 답변 달아 주세용 ^^

계속 적으로 업글 됩니다. 현재 14가지 !!!!


==========================================================================
★ mysql 총 게시물 수 세기

$numresults=mysql_query("select code from $board");
$numrows=mysql_num_rows($numresults);
2초 이상 ...게시물 10만개

VS

$numresults=mysql_query("select count(code) as code from $board");
$row_num=mysql_fetch_array($numresults);
$numrows=$row_num[code];
0.2  ...게시물 10만개

아래것이 훠얼씬 빠름다..
도대체 mysql_num_row() 는 왜 만들어 놓은 것일까용???


==========================================================================
★ mysql_fetch_row  > mysql_fetch_array >>> mysql_result


입니다.

row 가 array 보다 약간 빠르고, result 보다는 훠얼씬 빠름당 ^^

row 는 불편한게 숫자로 칼럼을 불러와서 불편합니다.
array 가 약간 느리지만, 문자 칼럼을 불러 올 수 있으니 array 쓰는 것도 양호 ^^

아직도 mysql_result() 를 사용하시나요?

==========================================================================
★print , echo ,printf 함수 속도 비교
HTML 출력 >> echo > print >> printf


print 와 printf 함수는 복잡한곳에 적격이고, 약간 느리다.

echo 는 단순한곳에 적격이고...빠르다.
printf 는 형식화된 출력을 해주므로 그래도 좋죠 ^^

==========================================================================
★  인라인

 a.php
<?
$aa="sdsdsdsd";
echo ("<table>
 <td> $aa </td>
</table>");
?>

 위 랑..

 b.php
<? $aa="sdsdsdsd"; ?>
<table>
<td><? echo $aa; ?></td>
</table>

 랑 도대체 어케 코딩 하느냐죠 ?

솔직히 코딩은 a.php 가 편합니다.
<? ?> 를 한번 만 쓰니까 효율적일 수 있습니당..

그러나 아무리 아무리 PHP가 빠르다고 해도 HTML 이 더 빠릅니당.. !!!

쿠쿠쿠

b.php 처럼 코딩 하는 습관을 가지세용 ^^

==========================================================================
★ zend cache , APC ,Bware 캐쉬 비교
Zend cache > APC > Bware

zend cache 는 캐쉬 입니다. 울나라에서 포탈에서도 몇군데 사용하죠.
PHP 프로그램 변환 없이 속도를 빠르게 해 줍니다. ^^

zend cache 를 살 돈이 없으시다구용?
그러면 APC 나 zend optimizer 를 반드쉬 설치 하세용 !!

■ 그런디 Zend Cache 만한 무료 캐쉬가 나왔다고 합니당...^^
http://www.php -accelerator.co.uk/index.php ;


==========================================================================
★ ereg_replace , preg_replace 정규표현식
ereg_replace () 가 장난 아니게 느림다.
40개 정도 변환 하는데 1초나 걸려요.preg_replace 는 0.3초 정도요.

되도록이면 preg_replace() 를 사용하세요 !!!

www.php.net/preg_replace


==========================================================================
★ foreach , list 함수 속도 차이 35%

foreach($string as $a);  >>>  while(list(,$a) = each($string));

foreach() 를 사용하는 것이 35% 정도 빠릅니다...!!


==========================================================================
★mysql_connect Vs mysql_pconnect

서로 장단이 있다 합니다.

mysql_pconnect 가 더 빠르다고 합니다.
persistant

메뉴얼에 영구적인 이렇게 되어 있으니까요..
일정시간 동안 mysql 을 열어 놓기 때문에, 다시 열 필요가 없어서 빠르다고 합니다.

단점은 계속 열기 때문에 메모리를 많이 잡아 먹슴당...^^
mysql_pconnect 경우는 최소 메모리가 1G 이상 되어야 사용하시는 것이 좋습니다.

==========================================================================
★ 큰따옴표(") , 작은 따옴표(')

큰따옴표는 PHP가 파싱을 합니다. 그러나 작은 따옴표는 파싱을 하지 않습니다.
작은 따옴표를 사용하시는 것이 빠릅니다.

코딩시 echo ' test '.$aaa.' tood ';
요런식으로 하시는 게 가장 빠름당 !!

==========================================================================
★ mysql 데이터 저장 공간 크기 ?


id int(11) unsigned NOT NULL auto_increment,
   bbs smallint(5) unsigned NOT NULL,
   lens mediumint(8) unsigned NOT NULL,
 

int 도 무자게 많슴당..
각각의 크기에 맞게 하는 것이 속도가 빨라 집니당 ^^

not null 를 주는 것도 속도가 빨라 집니당..

작은 사이트 조회수 경우 1만을 넘기도 힘듭니다. 그럴 경우 smallint 를 사용하시면 됩니다.

==========================================================================
★ where 절에 모든 것은 인덱스를 걸어라 !!!
mysql 에서 쿼리시에 where 절에 사용되는 비교의 칼럼은 반드쉬 인덱스를 거세용 !!!

mysql 인덱스 가 여러 분들의 게시판 속도를 업 시켜 줍니당 !!


==========================================================================
★메인페이지에서 속도를 빠르게 하려면, .htm 으로 만드는 것이 좋습니다.

그러니까..제 사이트 페이지 오른쪽 에는 모두 최신 게시물로 디비를 불러오는 부분
입니다.

디비 연결은 부하를 줄 수 있습니다.

그러니까..이예는 사이트가 상당히 활성화된 사이트일 경우 입니다.

하루에 2번 정도 .htm 으로 만들어 페이지를 업시키는 것이 좋습니다.
아무리 PHP가 빨라도 HTML 보다는 빠르지 않습니다.. !!!

그러기 위해서는 ★cron 를 알아야 합니다 PHP강좌 게시판에서 cron 으로 검색하세용 !!
윈도우 사용자는 멀 쓰는지 잘 모르겠슴당...아시면 답글 부탁  ^^


==========================================================================
★ 초보자 Vs 전문가

www.zend.com 에서 제가 2000년 5월에 퍼온건데용 ^^  
함 주석을 붙일까 해서용^^


Beginner vs Experienced  
Author:  Boaz Yahav  
Date  23/05/2000  

Beginner : echo "$var";  
Experienced : echo $var;  


Beginner:echo "<a href=\" http://www.php.net\">PHP</a>";  ;
Experienced : ?><a href=" http://www.php.net">PHP</a><?  ... ?>  ;

◆ "(따옴표) 가 굉장히 중요한것이라는 한 대목이죵 ^^
전 보통의 경우 php 변수 값이 들어갈 경우는 초보자 처럼 쓰구요 ^^ 안들어 갈 경우 는 전문가 처럼 씀다.

Beginner : $a[0]=1; $a[1]=2; $a[2]=3;  
Experienced : $a = array(1,2,3, 1);  
둘다 사용하는 데요. 전문가 쪽이 편함다. ^^

Beginner : if($a>1) { $b=2; } else { $b=3; } 
Experienced : $b = ($a>1) ? 2:3;  
요건 완존히 소스 어렵게 짜는 넘이 최고 라는 소리 같네용 ^^
전문가 쪽것은 C 언어 에서 배웠는데도 역시 전 if 씀다. ^^

Beginner : $result=mysql_query(...);  
Experienced: $result=mysql_query(...) OR die  
        (mysql_error());  

요즘 들어 새삼 전문가 쪽으로 씀다.^^
보통의 경우

$result=mysql_query(...)  
if (!$result)
{
 echo error()."<P>";
 echo errno();
}
이렇게 사용함다. ^^

or 이 설명이고 no 가 에러 번호 일 검다. ^^

==========================================================================
★MySQL,ADODB,PHPLib,PEAR 벤치마킹  

ADODB > PHPlib > PEAR
 
MySQL     1.14      -
ADODB     1.45     27%
PHPLib    1.60     40%
PEAR     2.87     152% (fetchInto)

MySQL,ADODB,PHPLib,PEAR  는 모두 데이터베이스 인가요? 당근 아닙니다.
MySQL만 데이터베이스 구요.
ADODB,PHPLib,PEAR 는 PHP 프로그램 입니다.

3개 다 MySQL연결을 편하게 하는 클래스 프로그램 입니다.
그런디 벤치 마킹 결과 MySQL 에서 직접 쿼리하는 것 다음으로 ADODB 가 뽑혔슴당 ^^

PEAR 가 굉장히 늦군요. PEAR DB 나 ADODB 를 사용해 보았는데, 움..역시나 ADODB 가 좋군요.
오라클, mysql , ms sql 연결시 1개의 API 만 사용할 수 있는 프로그램 들 이 PEAR 과 ADODB 입니당 ^^
==========================================================================
★ 속도 테스트는 어케 하는가 ? microtime() 사용하면 됩니다.


<?

function pageTime($page) {
 $mstart = explode(" ", $m);
 $mend = explode(" ", microtime());
 $mtime = ($mend[1] - $mstart[1]) + ($mend[0] - $mstart[0]);

 echo " $m[1]  $mend[1]<P>";
 echo " $m[0]  $mend[0]<P>";

 print("tood.net 페이지 로딩 시간 : " . $mtime . " microseconds");
}
pageTime(basename($PHP_SELF));
?>
 


==========================================================================


==========================================================================

참고 사이트
http://www.tood.net
http://www.zend.com
http://www.php.net
http://www.php.lt/benchmark/phpbench.php
http://www.phpbuilder.com
http://www.phpbuilder.com/columns/piergiorgio20010321.php3?print_mode=1
<?
  /*
    ** 추상 클래스 **

    상위 클래스에서 메소드(껍데기)만 구현하고, 하위 클래스에서 그 메소드를
    구현해야 한다.

    CSpeak 클래스에서 speak()라는 추상 메소드를 구현 했으며, 하위 클래스의
    CKor, CEng에서 각각 실제 기능이 있는 speak() 메소드를 구현 하였다.
  */
  abstract class CSpeak
  {
    abstract public function speak();
   
    public function write()
    {
      $this->speak();
    }
    public function __set($name, $value) { $this->{$name}=$value; }
    public function __get($name) { return $this->{$name}; }
  }

  class CKor extends CSpeak
  {
    public function speak()
    {
      echo "한국어를 하다.<br>";
    }
  }

  class CEng extends CSpeak
  {
    public function speak()
    {
      echo "영어를 하다.<br>";
    }
  }
  /*
  class CJpn extends CSpeak
  {
    // 추상 메소드를 구현하지 않았기 때문에 에러가 난다.
  }
  */


  $kor = new CKor();
  $eng = new CEng();

  $kor->write();
  $eng->write();
?>

결과 :
한국어를 하다.
영어를 하다.

HTML에서 벗어나기

PHP 파일을 해석할때 PHP코드로 해석하라고 하는 특별한 코드와 만나지 않는다면 단순히 파일의 텍스트를 넘겨줄 뿐이다. 해석기(parser) PHP 닫기 태그가 있는곳까지 발견된 코드 모두를 수행한다. PHP 닫기 태그 만나면 다시 텍스트를 그냥 넘겨주기 시작하는것이다. 이런 메카니즘은 HTML안에 PHP코드를 내장시킬수 있게 해준다: PHP 태그 밖의 모든것은 완전히 단독으로 존재하는것이고, 반면에 PHP 태그 안쪽은 코드로서 해석이 된다.

PHP 코드 블록은 네가지의 태그형태로 표시할수 있다. 중에서 두가지 (<?php. . .?> <script language="php">. . .</script>) 항상 유효한 형태이다. 반면에 다른 형태는 php.ini 설정 파일에서 켜거나 있다. 짧은형(short-form)태그와 ASP스타일(ASP-style) 태그는 편하겠지만, 형태 태그만큼 이식성이 뛰어나진 못하다. XML이나 XHTML안에 PHP코드를 내장시키려면 XML 호환될수 있도록 <?php. . .?>형을 써야한다.


PHP 에서 MSSQL 접속하는 방법 (셋팅방법, 윈도우 XP)
기본적으로 윈도우에 APM 설치및 사용이 가능하다는 전제로 설명하겠습니다.

참고로 제 컴퓨터 사양은 아래와 같습니다.

윈도우 XP 프로페셔널 SP3
아파치, MySQL, PHP (Ver 5.x)

PHP 에서만 셋팅을 해주면 MSSQL 접속이 가능합니다.
php.ini 파일에서 'mssql' 이라고 검색해보시면 아래와 같은 부분이 나옵니다.

;extension=php_msql.dll
;extension=php_mssql.dll
extension=php_mysql.dll

위에서 mssql 부분의 ; 표시를 지워버립니다. 아래처럼요

;extension=php_msql.dll
extension=php_mssql.dll
extension=php_mysql.dll

그리고 PHP 설치한 폴더 안에 보시면 ntwdblib.dll 파일이 있는데 이 파일을 윈도우 하위 폴더인 system32 에 넣습니다.
c:\windows\system32
여기가 되겠죠..

그럼 셋팅은 끝났습니다.
이제 아파치를 다시 재시동 하고 테스트에 들어갑니다.

<?
$myServer = "MSSQL 서버주소";
$myUser = "유저아이디";
$myPass = "유저비번";
$myDB = "DB이름";

$db = mssql_connect($myServer, $myUser, $myPass) or die ("서버 연결 실패");
mssql_select_db($myDB,$db) or die ("DB 연결 실패");
?>

위의 테스트에서 에러가 발생하지 않았다면 성공한겁니다.

참고로 MSSQL 서버 포트가 별도로 지정된 경우 쉽게 생각하는건 서버주소:포트번호 라고 생각하지만 MSSQL 서버는 다릅니다.

서버주소:포트번호 X
서버주소,포트번호 O

쉼표로 해줘야 되요.. ^^

사용자 삽입 이미지

<?

 /***************************************************
   그림에 텍스트 입력하기
 ***************************************************/

 $fontname = "MALGUN.TTF"; // php 파일과 같은 디렉토리거나, 경로까지 설정해야함
    $width = "500";
    $height = "500";

 function euckr2utf8($text) {
  return stripslashes(iconv("EUC-KR","UTF-8",$text));
 }

    $im1 = imagecreatefromjpeg("jj.jpg");
    $im2 = imagecreatefromjpeg("kim.jpg"); // GIF 파일 로드 : imagecreatefromgif()

    $white = ImageColorAllocate ($im1, 255, 255, 255);// 사용할 색상 설정 
    $black = ImageColorAllocate($im1,0,0,0);  // 사용할 색상 설정

 // 2개의 그림을 합친다.
 ImageCopyMerge ($im1, $im2, 0, 0, 0, 0, imageSX($im2), imageSY($im2), 70);

    ImageTTFText($im1, 20, 0, 5, 128, $black, $fontname, chr((rand() % 26)+65));

 header ("Content-type: image/png");  // 브라우저로 출력할 파일 타입 지정
    ImagePNG($im1); // 브라우저로 출력시킴

  //  ImagePNG($im1, "c:/1.png"); // jpg파일로 출력시킴
    ImageJpeg ($im1,"c:/1.jpg");  // png 파일로 출력시킴

    ImageDestroy($im1); // 이미지에 사용한 메모리 제거
    ImageDestroy($im2);

?>

출처 : http://sugame.tistory.com/234

사용자 삽입 이미지

원래는 max-width를 써서

img {
     max-width: 600px;
}

이나

img {
     max-width: 80%;
}

이렇게 해주면 되지만 익스플로러를 위해 한줄 더 추가하면

img {
     max-width: 600px;
     width:expression(this.width > 600 ? "600px" : this.width);
}

파이어폭스, 익스플로러 모두 제대로 적용됨.

사용자 삽입 이미지

웹표준 강의시에도 항상 나오는 이야기이다.

또한 네이버UI가이드(http://html.nhndesign.com/)가 공개됨으로써 많은 분들이 이곳을 참고하고 있기도하다.

네이버 UI가이드 역시 100% 완벽하지 않다.

갑론을 박해야 할 요소도 있긴 하지만 이정도 분량의 꼼꼼한 가이드을 공개 한 것 역시 네이버가 한 일중에서는 정말 칭찬 할 만한 일이라고 생각한다.

1. 하위선택자 사용에 따른 들여쓰기

필자의 견해 :
하위선택자를 사용했을때 이에 맞춰 들여쓰기를 하면 훨씬 코드 보기가 수월해진다.
이미 대다수의 홈페이지에서 이렇게 사용하고 있는 것같다.



2. 그룹화와 CSS의 주석

필자의 견해 :
의미있는 CSS끼리 그룹화 시키고 보기 쉽게 주석처리
물론 모든 네이밍작업이 그렇지만 CSS 네이밍도 사람들마다 조금씩 다르다
어떤이는 영어를 그냥 발음나는대로 영어로 옮기는 사람이 있는 반면에
영단어를찾아서 쓰는 사람이 있고
아니면 영어동사까지 포함해서 쓰는 사람도 있고
영문네이밍은 정말 사람마다 다양하다 이때 주석으로 이 부분이 어디에 해당하는 부분임을 명시하면
좀더 보기 수월한 코드가 된다.


3. 스타일 선언은 한줄에

필자의 견해 :
물론 CSS 코드가 길어지면
한줄에 하나의 속성만 지정하는 방식은 괜한 공백을 많이 잡아먹어서
용량이 커지기 때문에 불필요하지만
확실히 한줄에 하나의 속성만 적어놓는것이 가독성이 좋을때가 많다
때에 따라 둘을 적절히 사용하는 센스가 필요하겠다.

4. css 파일의 분리

필자의 견해 :
이곳의 예제에서는 layout.css, typography.css 등으로 css 파일을 분류하였는데
물론 이런식으로 분류도 있겠지만
나는 메뉴섹션별로(우리나라의 웹사이트는 대게 섹션별로 공통되는 디자인이 많다)
CSS파일을 구분하여 사용한다


5. 엘리먼트 초기화

필자의 견해 :
브라우저마다 엘리먼트의 default style일 틀리므로 반드시 초기화 할것.

6. 사용되는 색상코드를 한곳에 모아 적어 둔다

필자의 견해 :
확실히 도움되는 정보다
해당 웹사이트에서 주로 사용되는 폰트명과 폰트사이즈 컬러셋을 모아놓고 이를 미리 정의해두면
색상 가이드라인이 확실해질수 있겠다

실제로 프로젝트 경험에 의해 특정 콘텐츠마다 각각의 색상과 폰트와 line-height, 마진을 가진 경우를 보았다.
예를 들면 A에 관한 콘텐츠는 어떤 폰트와 어떤 색상을 사용하며 하단에 마진값 얼마를 반드시 가져야 한다. 이런종류.
이럴때 해당 프로젝트에 처음 투입되는 사람은 그러한 규칙이 이미 있는지 인수인계를 못받았을 확률도 많다.
이때 이러한 규칙에 대해서 짤막하게(길게 주석으로 남긴다는 것은 절대 하지 말아야할것. 길게 주석을 적어 넣을바에야 차라리 ppt또는 문서 파일로 UI 가이드라인을 만드는게 낫다.) 적어 놓으면 갑작스럽게 관계자가 아닌사람이 UI를 수정한다거나 할때 좋은점도 있는 것 같다.





7. 의미있는 네이밍

필자의 견해 :
가장 중요하다
네이밍기법에 항상 언급되는 내용이지만
green 이라던지 left, right 등의 네이밍보다는
header, menu, nav, footer등의 의미있는 네이밍이 좋다.



8. 알파벳순서의 프로퍼티정의

필자의 견해 :
사실 나는 이부분은 찬성하지 않는다
자주쓰이는 속성 순서대로, 레이아웃에 영향을 많이 주는 순서대로 나열하는 것이
경험상 코드가독성에 아주 좋다.
알파벳순으로 나열하게 되면 정작 중요한 width같은 속성은 거의 맨뒤에 위치하게 되는데
이것보다는 중요한 순서대로 프로퍼티를 나열하는게 경험상 좋은것 같다.
필자는 display,position,float,width,height,padding,margin,border,background 순으로 사용한다
물론 이부분 역시 네이버UI가이드에서 사용빈도에 따른 프로퍼티 나열이 언급되어있다.



9. 유용한 css 클래스 유지

필자의 견해 :
유용한 css 클래스를 미리 정의하는 것은 아주 좋은 행위지만
이곳 예제에서는 width100이라던지 alignRight라던지
7번에서 언급한 의미있는 네이밍이 되어 있지 않다

필자는 clear라는 css클래스를 global css에 선언하는데
IE에서 clear:both시에 상단에 마진이 생기는 현상을 제거하기 위해

.clear {clear:both;height:0;line-height:0;font-size:0;}

이렇게 사용하고 있다.

현석님의 트랙백을 보고나니 내가 이 9번 문항에 대해서 잘못 코멘트한것 같다.
원본에서의 유용한 CSS의 클래스의 의미가 단순히 표현을 위한 width100, width75 이런 클래스가 유용한 클래스라고 말한것이라면 정말 절대 삼가해야할 것이다. 현석님 말대로 .mt10 {margin-top:10px;} 이런 클래스는 정말 삼가해야할 일이다. 이걸 클래스로 지정해서 사용하느니 인라인 스타일시트로 적용하는게 훨씬 나은 방법이다.
저는 유용한 클래스의 의미를 좀더 넓은 범위의 유용한 클래스(의미있는 네이밍이 되어있는 특정 콘텐츠 형식에 대한 클래스화)라고 잘못 해석하고 이해한것 같아서 추가 코멘트 남깁니다.





모두 아주 좋은 내용이다.

계속해서 HTML과 CSS를 사용하여 표현과 문서를 분리하는 곳이 많아졌다.

이런 중요한 개발방법론은 계속해서 공유되어져

새로 웹퍼블리셔가 되고싶은 사람들에게 많은 도움이 되었으면 좋겠다.

CSS Baese Design을 할 때...
이전의 <TABLE>이 하던 것을 <DIV>로 대체해야 하기에...
아마도 height속성과 더불어 가장 많이 쓰이는 CSS속성이 될 것이다.

지금까지 <TABLE>위주의 코딩을 하던 사람들에게는...
CSS의 width값의 적용범위가 <TABLE>에 익숙해있던 범위와는 달라서...곤혹을 치룰 것이다.


예를 들어 <TABLE>에 width=360을 입력해놓은 상태이면...
width=120인 <TD>를 3개 있다치더라도...cellpadding, cellspacing값과는 무관하게
width=120과는 오차범위가 1pixel이상 나는 일이 별로 없고,
width=360은 어느정도는 절대적으로 지켜졌기 때문이다.

사용자 삽입 이미지

그림 1


그리고, 이전의 익스플로러에서
margin, border, padding값을 자의적으로 적용함과 함께...
width값의 적용범위를 border가 그려지는 영역으로 되었기 때문에...


사용자 삽입 이미지

그림 2


대다수의 사람들이 위의 그림처럼 border의 안쪽영역을 width값의 범위인 줄 알고 있고,
padding값은 width값의 안쪽 부분의 여백을 정의하는 것으로 알고 있다.


나도 2004년 2월까진 저렇게 알고 있었다.


내가 그토록 신뢰했던 CSS refernce 서적과 국내 CSS에 대해 설명해놓은 사람들의 홈페이지나 글들을 봐도 저것이 잘못되었다고 말하는 이가 하나도 없다.


아니다.


width값은...실제 데이타가 들어가는 영역의 범위를 규정하는 것이다.
margin값과 padding값, 그리고 border의 width값에 영향을 받지 않는
텍스트나 이미지, 또다른 요소들이 차지하는 영역에만 width값을 적용시켜야한다.

사용자 삽입 이미지



그러나, 익스플로러는 그렇지 못하다.

익스플로러 장난 아니다.


<DIV>에 width값을 적용시켜놓으면 1px짜리 border정도까지 포함시키고
padding값이 width값의 안쪽에 적용되어 의도했던 것보다 <DIV>의 크기가 작게 나온다.

더욱 웃긴건...
padding값이 같은 익스플로러6.0에서조차도 차이가 난다.

익스플로러 5.0과 window2000에서의 익스플로러6.0은 그림2처럼 구현을 하고
windowXP에서는 그림3처럼 구현을 하는데...
같은 페이지에서조차 그림2처럼 구현하기도 한다.

(같은 페이지에서 저러면 돌아버린다.)

또한, border값은 width와 다른 범위이지만, Block의 width값에 일부를 포함시켜 의도했던 border의 두께가 나오지 않을 때도 있다. border-left:10px solid #FF0000을 적용시켜도 width값이 지정되어 있을 때 실제 border가 8pixel만 나올 때도 있다.


CSS Based Design을 하시려는 분이 있다면...
넷스케이프6.0이상 버젼을 꼭 깔기를 추천합니다.
CSS적용에 대해서는 넷스케이프의 CSS엔진이 훨씬 훌륭합니다.


추신:
<td style="padding-left:12px;"> 이거 쓰지마시라
만약 꼭! 써야한다면...<table>에 width값을 정의하지말지니라.
window2000에서 볼때와 windowXP에서 볼 때 적용된 것이 다르다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META NAME="Generator" CONTENT="EditPlus">
  <META NAME="Author" CONTENT="">
  <META NAME="Keywords" CONTENT="">
  <META NAME="Description" CONTENT="">

  <script language="JavaScript">
function test()
{
 var date = new Date();
 date.setFullYear('2008','11','16' -16);

 alert(date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate());
}
  </script>
 </HEAD>

 <BODY>
  <a href="javascript:test();">test</a>
 </BODY>
</HTML>

function getCon(){

 var len=0, j;
 var str = document.board.content.value;

 for (i=0, j=str.length;i<j;i++, len++) {

  if ( (str.charCodeAt(i)<0)||(str.charCodeAt(i)>127) ){
   len = len+1;
  }

  if (len >= 20000) {
   alert(''최대 2000 Bytes 까지만 보낼 수 있습니다.'');
   document.board.content.value=str.substring(0,i);
   document.board.content.focus();
   return;
  }

 }
}

<textarea name="content" cols="70" rows="15" onclick="getCon()" onkeyup="getCon()"></textarea>

사용자 삽입 이미지

open flash chart를 data file 없이 사용 하는 방법입니다.
서버 단에서 밑에 javascript 부분을 text로 생성한 다음 화면에 뿌려주면 될 것 같습니다.


<html>
<head>
<base href="http://teethgrinder.co.uk/open-flash-chart/"></base>
<meta http-equiv=content-type content="text/html; charset=UTF-8">
<title>Open Flash Chart - Tutorials - No Data File</title>
<link rel="stylesheet" type="text/css" title="standard Style" href="ofc.css">
</head>
<body style="font-family: verdana; font-size: 12px;">

    <div id="109299445549ac9c2e9c8b46.84997988"></div>
    <script type="text/javascript" src="js/swfobject.js"></script>
    <script type="text/javascript">
        var so = new SWFObject("open-flash-chart.swf", "ofc", "400", "250", "9", "#FFFFFF");
        so.addVariable("variables","true");
        so.addVariable("title","Paper+Mario%23comma%23+%25+complete,{font-size: 18px; color: #A0A0A0;}");
        so.addVariable("x_legend","Week+1,12,#A0A0A0");
        so.addVariable("x_label_style","10,#A0A0A0,0,1");
        so.addVariable("x_axis_steps","1");
        so.addVariable("y_label_style","10,#A0A0A0");
        so.addVariable("y_ticks","5,10,2");
        so.addVariable("x_labels","Mon,Tue,Wed,Thu,Fri,Sat,Sun");
        so.addVariable("y_min","0");
        so.addVariable("y_max","100");
        so.addVariable("x_axis_colour","#A0A0A0");
        so.addVariable("x_grid_colour","#FFFFFF");
        so.addVariable("y_axis_colour","#A0A0A0");
        so.addVariable("y_grid_colour","#FFFFFF");
        so.addVariable("tool_tip","Progress%23comma%23+%23val%23%25");
        so.addVariable("bar_sketch","50,6,#99FF00,#7030A0,%25+Complete,10");
        so.addVariable("values","50,65,70,75,80,89,100");
        so.write("109299445549ac9c2e9c8b46.84997988");
    </script>
</body>
</html>
 
function CkImageVal(value){
                            var oInput = event.srcElement;
                            var fname = oInput.value;

                            if((/(.jpg|.jpeg|.gif|.png)$/i).test(fname))
                                oInput.parentElement.children[0].src = fname;
                            else
                                alert('이미지는 gif, jpg, png 파일만 가능합니다.');

                            var imgInfo        = new Image();
                            imgInfo.onload    = img_Load;
                            imgInfo.src        = value;
                        }
                        function img_Load(){
                            var imgSrc, imgWidth, imgHeight, imgFileSize;
                            var maxFileSize;
                            maxFileSize    = 50000000;
                            imgSrc            = this.src;
                            imgWidth        = this.width;
                            imgHeight        = this.height;
                            imgFileSize    = this.fileSize;

                            if (imgSrc == "" || imgWidth > 100){
                                alert('가로 600 픽셀을 초과하는 이미지파일을 가져올 수 없습니다.');
                                return;
                            }

                            if (imgFileSize > maxFileSize){
                                alert('선택하신 그림 파일은 허용 최대크기인 ' + maxFileSize/1024 + ' KB 를 초과하였습니다.');
                                return;
                            }
                        }

+ Recent posts