phpsource/템플릿2000. 8. 6. 13:30
FastTemplate는 템플릿툴!!!
아래에는 "FastTemplate"로 작성된 템플릿을 보여주고 있습니다. 이 템플릿에는 {TITLE}라는 변수가 포함되어 있으며 이 변수는 출력하기 전에 실제 값으로 치환됩니다. 하나의 페이지를 완성하기 위한 단계는 아래와 같습니다.
  1. 템플릿 이름을 파일 이름으로 맵핑하기 : 메소드 define()
  2. 값을 템플릿 변수에 지정하기 : 메소드 assign()
  3. 템플릿 분석하기 : 메소드 parse()
  4. HTML 출력하기 : 메소드 FastPrint()
[code html;gutter:false] <!-- NAME: main.tpl --> <html> <head><title> {TITLE} </title> </head> <body> </body> </html> <!-- END: main.tpl --> [/code]
[code php;gutter:false] <? // Example FastTemplate Demo #1 - The example from the man page Header("Content-type: text/plain"); include("class.FastTemplate.php3"); $tpl = new FastTemplate("./templates"); $tpl->define( array( main => "main.tpl", ) ); $tpl->assign( array( TITLE => "FastTemplate Test") ); $tpl->parse(MAIN, array("main")); $tpl->FastPrint(); ?> [/code]
평가
PHP4가 동작되는 서버 상에서의 스크립트 수행속도가 VH layout이나 UnitTable보다 2배정도 빠릅니다. 그러나 레이아웃이 복잡하여 TABLE 태그가 다층으로 중첩되어 있는 페이지에 대한 템플릿을 보면 템플릿 내에 TABLE 태그가 그대로 나타나 있어 템플릿 자체가 복잡합니다. 즉 TABLE 태그 내에 들어가는 데이터가 치환되는 것이지 레이아웃에 사용된 TABLE 태그를 해석하여 생성해주는 기능은 빠져 있습니다. VH layout이나 UnitTable은 모두 레이아웃을 표현하고 생성해주는 부분이 포함되어 있으며, 이것 때문에 FastTemplate보다 다소 수행속도가 느리다고 볼 수 있습니다. 따라서 레이아웃은 빼고 데이터만 템플릿에 표현하고 싶으신 분은 FastTemplate를 사용하시는 것이 바람직합니다.
FastTemplate에 대한 더 자세한 사용법이나 특징은 이곳(www.thewebmasters.net) 을 방문하시거나 아니면 컴퓨터 서적 "professional PHP Programming"의 제22장 템플릿을 참조하세요......

'phpsource > 템플릿' 카테고리의 다른 글

{유닛테이블}06.구성  (0) 2000.08.06
{유닛테이블}05.개요  (0) 2000.08.06
{유닛테이블}04.VH layout의 소개  (0) 2000.08.06
{유닛테이블}02.페이지툴의 필요성  (0) 2000.08.06
{유닛테이블}01.페이지툴  (0) 2000.08.06
Posted by 방글24
phpsource/템플릿2000. 8. 6. 13:27
PHP 코드와 HTML 태그를 분리하면???
서버사이드 스크립트로 작성된 소스코드를 보면 스크립트 문장하고 HTML 태그가 혼재되어 있어 매우 혼란스럽기도 하며, 또한 도무지 전체 흐름이 파악하기가 쉽지 않습니다. 그 외에도 웹사이트가 복잡해 지다보면 이러한 방식으로는 관리하기도 어렵고, 향후 홈페이지를 수정하는 작업도 보통문제가 아니라고 생각하였습니다. 그래서 서버사이드 스크립트에서 작업한 PHP 코드와 방문자 인터페이스를 담당하게 될 HTML 태그를 분리하면 이러한 문제를 다소나마 해결할 수 있을 것으로 판단되어 "PHP코드와 HTML태그의 분리" 방법으로 템플릿과 레이아웃 기술을 제 홈페이지에 적용하기 시작했고, 적용하기 전에 템플릿과 레이아웃 기술을 구현할 수 있는 툴을 개발하게 되었죠. 개발하기 전에 "FastTemplate"와 같은 좋은(?) 툴이 있다는 것을 알았다면 개발을 좀 더 쉽게 할 수도 있었을 텐데, 그러지 못해 좀 투박한 상태로 사용해 오다가 보름 전부터 "FastTemplate"와 "VH layout"을 참조하여 유닛테이블의 인터페이스 부분을 대폭 수정하였고, 이제 여러분과 정보를 공유하고자 유닛테이블의 소스코드를 공개합니다.
템플릿툴 또는 레이아웃툴을 사용하여 얻게 되는 이점을 보면 우선 개발속도를 높일 수 있고, 소스 코드의 가독성을 높일 수 있으며, 웹사이트 전체에 걸쳐 반복되는 부분을 재 사용할 수 있어 툴에 따라서는 사용자가 직접 작성해야 할 코드의 양을 상당히 줄일 수 있고, 아울러 관리 및 향후 수정을 용이하게 해줍니다.
장점이 있으면 단점도 있겠지요. 새로운 기술을 적용하다보니 처음 보는 사람은 오히려 복잡해 보입니다. 이해하기도 어렵고요. 또한 스크립트 수행속도가 느려집니다. 그러나 뒤에서 언급될 각 페이지툴에 대한 예제를 실행해보면 알겠지만 인터넷상에서는 페이지툴을 사용할 때나 안 할 때나 속도차이를 별로 느낄 수 없습니다. 이는 서버의 수행속도보다 네트워크의 전송속도가 훨씬 느리기 때문이죠. 페이지툴을 사용한다고 해서 전송되는 데이터 양이 늘어나는 것은 아니며, 단지 서버에서 처리해야 할 데이터 양이 많아지는 것입니다.
어쨌든 페이지툴을 적용하면 단점도 따르기 때문에 모든 페이지에 페이지툴을 적용하기보다는 간단한 개인 홈페이지는 기존에 하던 대로 "HTML 태그 내에 PHP 코드를 삽입하는 방식"을 사용하는 것이 효율적일 수도 있을 겁니다. 반면에 대부분의 상용 홈페이지와 같이 레이아웃 또는 디자인 구조가 다소 복잡한 코드에서는 가능한 한 페이지툴을 적용할 필요가 있을 것 같습니다.
즉, 좀더 정돈된 페이지를 구성하기 위해서는 레이아웃을 위해 TABLE 태그를 여러 층으로 중첩하여 사용하게 되는데, 이렇게 다층으로 구성된 페이지에서 시작 태그와 종료태그 짝을 실수하지 않고 맞추기가 쉽지 않고 전체의 구조를 한 눈에 파악하기도 쉽지 않죠. 또한 웹사이트 내에 있는 여러 페이지의 일부분을 동일한 형태(레이아웃 또는 데이터)로 반복되는 부분이 많을 경우 매 페이지마다 동일한 부분을 매번 별도로 작성한다는 것은 문서를 작성하기도 불편하고 관리하기도 쉽지 않습니다.

'phpsource > 템플릿' 카테고리의 다른 글

{유닛테이블}06.구성  (0) 2000.08.06
{유닛테이블}05.개요  (0) 2000.08.06
{유닛테이블}04.VH layout의 소개  (0) 2000.08.06
{유닛테이블}03.FastTemplate의 소개  (0) 2000.08.06
{유닛테이블}01.페이지툴  (0) 2000.08.06
Posted by 방글24
phpsource/템플릿2000. 8. 6. 13:10
페이지툴이란?
하나 이상의 페이지에서 데이터를 공유하거나, PHP 코드와 HTML 태그를 분리하여 페이지를 작성하기 위해서는 보통 템플릿 기술이 적용된 템플릿툴을 이용하여 페이지를 작성하며, 또한 대부분의 페이지에서 레이아웃을 위해 사용되는 TABLE 태그를 좀더 쉽게 표현하기 위해서는 레이아웃 기술이 적용된 레이아웃툴을 사용하여 페이지를 작성하게 됩니다. 이와 같이 페이지를 작성하는데 도움을 주는 툴을 통칭하여 페이지툴이라고 칭하겠습니다.
  • 당신의 웹사이트의 구성이 일정한 틀을 가지고 반복 사용되고 있습니까?
  • PHP 소스 코드와 HTML 태그가 혼재되어 있어 홈페이지 개발에 어려움을 느끼고 있습니까?
  • 페이지의 레이아웃 구조가 점점 복잡해져서 개발과 관리에 어려움을 느끼고 있습니까?
개발자라면 한번쯤 생각해 보았을 문제들입니다. 페이지툴을 사용하여 이러한 문제를 조금이나마 해결해보세요. 아마 템플릿툴이나 레이아웃툴과 같은 페이지툴을 사용하지 않는다면 여러분의 문제를 해결하기가 쉽지 않을 것입니다.
현재 PHP를 위해 구현된 템플릿툴을 보면 컴퓨터서적 "professional PHP Programming"에서도 소개된 "FastTemplate"가 있고 레이아웃툴로는 VH Consultants에서 개발하여 공개하고 있는 "VH layout"이 있습니다. 혹시 여러분이 또 다른 템플릿툴이나 레이아웃툴을 알고 계시면 게시판을 통해 다른 분들에게도 소개해 주세요.
"FastTemplate"와 "VH layout"에 대한 자세한 내용은 아래에 있는 관련 웹사이트를 참조해주시고 여기서는 2장, 3장에서 간단하게 소개만 하겠습니다. 4장부터는 제가 직접 제작한 유닛테이블을 소개하겠습니다.
페이지툴 개발 웹사이트......
(수정:2010.1.11) FastTemplate-1.1.0 클래스 파일 소스는 복사본을 참조하세요.
  • VH layout(www.vhconsultants.com)
(수정:2010.1.11) 오래된 문서라서 현재는 링크가 깨진 상태입니다. 복사본을 참조하세요.
버그 발견, 개선 요구, 기능 추가......
유닛테이블에 버그가 있거나 새로이 개선되기를 바라는 점, 추가되기를 바라는 기능, 각 툴을 사용해보신 소감 등이 있으면 후키라이브러리 Q/A 게시판을 이용해 의견을 주세요:-)

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:07
__sleep, __wakeup과 같이 "__"로 시작하는 매직함수(magic function)는 PHP 클래스 내에서 특수한 목적으로 사용됩니다. 따라서 이 함수들이 가지고 있는 문서화된 매직 기능을 사용할 필요가 없다면 클래스 내에 이 함수들을 정의해서는 안됩니다.
__sleep
serialize 함수를 통해 객체를 직렬화할 때 해당 클래스에 매직 함수 __sleep가 정의되어 있는지 확인합니다. 만약 정의되어 있다면 객체를 직렬화하기 전에 __sleep 함수를 수행합니다. 이 함수는 직렬화하기 전에 객체 멤버에 대하여 조작해야 하는 작업, 또는 직렬화하기 전에 미리 수행해야 하는 작업(예를 들어 데이터베이스 연결 종료 등)을 수행할 수 있습니다. __sleep 함수는 직렬화할 객체의 모든 멤버변수의 이름을 변수에 담아 반환합니다.
[code php;gutter:false] class Scott {
var $error;
var $svar = array();

function Scott() {
$this->svar['Hello'] = "World";
}

function __sleep() {
$this->svar['Hello'] = "Yawn";
// return list of instance-variables to be serialized
return array('error', 'svar');
}
}

$x = new Scott();
print_r($x);
$y = serialize($x);
$z = unserialize($y);
print_r($z); [/code]
__wakeup
unserialize 함수를 통해 문자열을 객체화할 때 해당 클래스에 매직 함수 __wakeup가 정의되어 있는지 확인합니다. 만약 정의되어 있다면 객체화하기 전에 __wakeup 함수를 수행합니다. 이 함수를 수행할 때 객체화하기 전에 객체를 상대로 수행해야하는 작업, 또는 객체화하기 전에 미리 수행해야 하는 작업(예를 들어 데이터베이스 연결 등)을 수행할 수 있습니다.
[code php;gutter:false] class Scott {
var $error;
var $svar = array();

function Scott() {
$this->svar['Hello'] = "World";
}

function __sleep() {
$this->svar['Hello'] = "Yawn";
// return list of instance-variables to be serialized
return array('error', 'svar');
}

function __wakeup() {
$this->svar['test'] = "I'm here!";
}
}

$x = new Scott();
print_r($x);
$y = serialize($x);
$z = unserialize($y);
print_r($z); [/code]

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:05
부모클래스의 메소드 호출
보통 부모클래스에서 선언된 메소드를 자식클래스에서 재정의하는 이유는 크게 두가지가 있습니다.
1. 부모클래스 메소드를 완전히 새롭게 정의하기 위하여
2. 부모클래스 메소드의 기능에 새로운 기능을 추가하기 위하여
첫 번째 기능은 부모클래스의 메소드를 무시하고 메소드에 새로운 정의를 함으로써 부모클래스의 메소드 정의를 숨기는 것입니다. 그러나 때로는 부모클래스의 메소드를 모두 지우는 것보다는 추가적인 기능이 필요한 경우가 있습니다. 이같은 경우에는 부모클래스의 메소드와 자식클래스에서 재정의된 메소드를 모두 수행하게 될 것입니다. 즉, 재정의된 메소드 구문 내에서 부모클래스의 메소드를 호출할 수 있어야 하며 필요한 기능만 추가적으로 작성하면 될 것입니다. 이럴 때 부모클래스의 메소드를 호출하기 위해서 사용하는 키워드가 parent입니다. 자바에서의 키워드 super와 같은 역할을 하며 이것은 그 메소드 호출을 상위클래스로 전달합니다.
부모키워드 parent는 $this 키워드와 비슷하게 이 클래스의 부모클래스를 나타내는 위치 지정자입니다. 현재 클래스의 부모클래스를 참조해야 되는 경우에는 부모키워드 parent를 사용할 수 있습니다.
[code php;gutter:false] class A {
function example() {
echo "클래스 A에 정의된 메소드 example. \n";
}
}

class B extends A {
function example() {
echo "클래스 B에서 재정의된 메소드 example. \n";
parent::example();
}
}

$b = new B;

$b->example(); [/code]
이 예의 출력결과를 보면 아래와 같이 나타날 것입니다.
클래스 B에서 재정의된 메소드 example.
클래스 A에 정의된 메소드 example.
앞장 범위연산자에서 설명한 대로 키워드 parent 대신에 extends 다음에 기술된 부모클래스명을 직접 사용해도 됩니다.
parent::example();  ------>  A::example();
키워드 parent를 써야 될 이유
위의 예에서 부모클래스를 A가 아닌 A1으로부터 상속받도록 수정하여야 한다면 아래와 같이 extends 다음에 있는 부모클래스명을 변경하는 것으로 모든 작업은 끝나게 됩니다. 만약 parent::example()가 아닌 A::example()라고 작성하였었다면 이 부분도 A1::example()라고 수정하여야 할 것입니다. 결국 수정할 때 손이 더 많이 가야 하는 것이지요. 그러니 부모클래스에 있는 메소드에 접근하는 경우라면 키워드 parent를 이용하는 것이 소스 코드를 관리하는데 훨씬 유리할 것입니다.
[code php;gutter:false] class B extends A1 {
function example() {
echo "클래스 B에서 재정의된 메소드 example. \n";
parent::example();
}
}

$b = new B;

$b->example(); [/code]

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:04
범위연산자란?
PHP4에서만 지원되며 클래스와 메소드 또는 클래스와 멤버변수를 연결시켜 주는 일로 범위연산자(scope resolver) 뒤에 나오는 메소드와 멤버변수의 스코프(사용범위)를 지정하는 일을 하는 것입니다.
클래스명::메소드명
클래스명::멤버변수명
범위연산자 사용목적
1. 인스턴스되지 않은 클래스의 메소드에 접근할 때
2. 부모클래스의 메소드와 멤버변수에 접근할 때
인스턴스되지 않은 클래스에 있는 메소드에 접근할 때
[code php;gutter:false] class A {
function example() {
echo "클래스 A에 정의된 메소드 example. \n";
}
}

A::example(); [/code]
아직 클래스 A에 대한 객체가 생성되기 전이지만 범위연산자를 이용하면 일반 함수처럼 실행시킬 수 있습니다. 그러나 클래스 A에 대한 객체가 전혀 생성되어 있지 않으므로 클래스 외부에서 이 함수에 접근할 때는 이 함수 내에 $this 객체를 사용해서는 안됩니다. 물론 일반 함수와 마찬가지로 지역 변수 및 전역 변수를 사용할 수는 있습니다.
[code php;gutter:false] class A {
var $var = "초기값";

function example() {
echo "클래스 A에 속한 메소드 example. \n";
echo $this->var . "\n";
}
}

A::example(); [/code]
위의 예제를 보면 아직 클래스 A에 대한 객체가 생성되지 않았으므로 멤버변수 $var에 대한 기억장소가 할당되지도 않았고 더구나 초기값을 설정할 수도 없습니다. 그러니 아무리 범위연산자를 이용하여 메소드 example()에 접근한다해도 멤버변수 $var의 초기값을 나타낼 수는 없을 것입니다. 실험해 본 바로는 이 경우 $this->var의 값이 NULL로 처리되는 것 같습니다.
부모클래스의 메소드에 접근할 때
[code php;gutter:false] class A {
function example() {
echo "클래스 A에 정의된 메소드 example. \n";
}
}

class B extends A {
function example() {
echo "클래스 B에서 재정의된 메소드 example. \n";
A::example();
}
}

$b = new B;

$b->example(); [/code]
이 예의 출력결과를 보면 아래와 같이 나타날 것입니다.
클래스 B에서 재정의된 메소드 example.
클래스 A에 정의된 메소드 example.
범위연산자는 클래스가 상속되었을 때 재정의되기 전의 부모클래스에 있는 메소드에 접근할 때 유용하게 사용될 수 있습니다.
부모클래스의 멤버변수에 접근할 때
php.net의 문서 설명과는 달리 아직 공개되지 않는 어떤 방법이 있는 지는 모르겠으나 부모클래스의 멤버변수로 접근하는 방법에 대하여는 문서화되지 않은 것 같습니다.

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:03
생성자(constructor)는 클래스의 새로운 인스턴스가 생성될 때 자동적으로 호출되는 클래스 내의 함수이며, 클래스명과 동일한 이름를 갖는 특수한 메소드입니다.
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// Add $num articles of $artnr to the cart

function add_item ($artnr, $num) {
$this->items[$artnr] += $num;
}

// Take $num articles of $artnr out of the cart

function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
}

class Auto_Cart extends Cart {
function Auto_Cart () {
$this->add_item ("10", 1);
}
} [/code]
위의 예제는 클래스 Auto_Cart가 new 연산자로 만들어질 때마다 품목번호 "10"의 수량이 1을 갖도록 장바구니를 초기화시키는 생성자를 새로이 포함하여 정의하였습니다.
생성자에 전달되는 인자
생성자는 필요하면 선택적으로 인자(argument)를 전달할 수도 있기 때문에 매우 유용하게 사용됩니다.
[code php;gutter:false] class Constructor_Cart extends Cart {
function Constructor_Cart ($item = "10", $num = 1) {
$this->add_item ($item, $num);
}
}

// Shop the same old boring stuff.

$default_cart = new Constructor_Cart;

// Shop for real...

$different_cart = new Constructor_Cart ("20", 17); [/code]
PHP3와 PHP4 생성자 사이에 발생하는 미묘한 차이
PHP3에서는 클래스와 동일한 이름을 가진 함수를 생성자로 처리하고 있습니다. 따라서 아래와 같은 경우에 클래스 B의 이름과 동일한 이름의 함수 B()가 없으므로 객체를 생성할 때 실행할 생성자가 없습니다.
[code php;gutter:false] class A {
function A() {
echo "I am the constructor of A.\n";
}
}

class B extends A {
function C() {
echo "I am a regular function.\n";
}
}

// no constructor is being called in PHP3.
$b = new B; [/code]
그러나 만약 아래와 같이 클래스 A에 함수 B()가 정의되어 있다면 설사 클래스 B를 가지고 객체를 생성하더라도 클래스 A에 있는 일반함수 B()를 클래스 B의 생성자로 인식합니다. 즉, PHP3에서는 함수 B()가 클래스 B에 속해 있는지 아니면 부모 클래스로부터 상속된 함수인지를 인식하지 못합니다. 따라서 객체 $b를 생성할 때 클래스 A에 있는 일반함수 B()를 생성자로써 실행하게 되는 것이지요.
[code php;gutter:false] class A {
function A() {
echo "I am the constructor of A.\n";
}

function B() {
echo "I am a regular function named B in class A.\n";
echo "I am not a constructor in A.\n";
}
}

class B extends A {
function C() {
echo "I am a regular function.\n";
}
}

// no constructor is being called in PHP3.
$b = new B; [/code]
클래스 B에 속하지도 않은, 부모클래스로부터 상속된 일반 함수 B()를 클래스 B의 생성자로 인식한다는 것은 대부분 우리가 전혀 의도하지 않는 일로 잘못하다가는 원치않는 결과를 초래할 수도 있습니다. 객체지향언어에서 말하는 생성자의 구분이 모호해 진다는 것이지요. 이러한 문제를 PHP4에서는 바로 잡았습니다. 단지 이름만 같다고 생성자로 처리하는 것이 아니라 반드시 해당 클래스 내에 포함되어 있는 것만 생성자로 처리하도록 수정하였습니다. 따라서 위의 예를 PHP4에서 수행한다면 클래스 A에 속한 일반함수 B()를 생성자로써 실행하지는 않습니다.
대신에 PHP4에서는 생성자와 관련하여 새로운 기능이 추가되었습니다. 파생클래스에서 생성자가 정의되어 있지 않으면 그 부모 클래스에 정의된 생성자가 실행하도록 수정되었습니다. 즉, 위의 예에서보면 객체 $b를 생성할 때 클래스 B에 해당하는 생성자 B() 함수가 정의되어 있지 않으므로 그 부모 클래스의 생성자인 A()가 생성자로 수행됩니다.
이러한 PHP3와 PHP4 사이의 미묘한 차이를 명확히 구분하지 못한 상태에서 생성자를 다루게 되면 프로그램이 매우 심각한 오류에 빠질 수 있다는 것을 참고하시기 바랍니다.

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:02
클래스를 상속하려면?
기존에 이미 작성된 클래스를 상속(class inheritance)받으면 이미 작성된 메소드와 멤버변수를 그대로 이어받게 됩니다. 상속받은 특성에 덧붙여 새로운 특성을 추가하는 방법으로 새로운 클래스를 정의하게 됩니다. 이와 같이 기존의 클래스로부터 특성을 이어받는 것을 상속이라고 합니다. 이 때 확장된 클래스를 정의하기 위해 "extends"라는 키워드를 사용합니다.
부모클래스 & 자식클래스에 관련된 용어
기존의 클래스와 확장된 클래스를 나타내는 용어는 객체지향언어마다 다양하게 사용되고 있습니다. 그러나 어떤 용어를 사용하더라도 같은 의미로 사용되고 있다고 이해하시면 됩니다.
기존의 클래스 확장된 클래스
용어 영문 용어 영문
기반클래스 base class 파생클래스 derived class
수퍼클래스 super class 서브클래스 sub class
부모클래스 parent class 자식클래스 child class
클래스 상속 예제
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// Add $num articles of $artnr to the cart

function add_item ($artnr, $num) {
$this->items[$artnr] += $num;
}

// Take $num articles of $artnr out of the cart

function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
}

class Named_Cart extends Cart {
var $owner;

function set_owner ($name) {
$this->owner = $name;
}
} [/code]
클래스 Named_Cart는 클래스 Cart의 모든 변수와 함수를 그대로 상속받게 되며, 새로운 멤버인 변수 $owner과 함수 set_owner()를 추가하여 정의합니다. 앞서 배운 new 연산자를 이용하여 클래스 Named_Cart의 객체를 생성한 후 장바구니 주인을 지정하거나 주인이 누구인지 확인할 수 있습니다. 아울러 부모클래스 Cart에 있는 장바구니 관련 함수를 그대로 사용할 수 있습니다.
[code php;gutter:false] $ncart = new Named_Cart; // Create a named cart
$ncart->set_owner ("kris"); // Name that cart
print $ncart->owner; // print the cart owners name
$ncart->add_item ("10", 1); // (inherited functionality from cart) [/code]
단일 상속
PHP는 다중 상속(multiple inheritance)를 지원하지 않으며, 오로지 단일 상속만 지원합니다.

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 14:00
객체 생성=객체 초기화(object initialization)=인스턴스화(instantiation)
클래스는 붕어빵을 만드는 틀(= type, =template)과 같은 것으로, 클래스 내에 정의된 메소드와 멤버변수를 사용하기 위해서는 틀을 가지고 붕어빵을 만드는 것같이 객체를 생성하여야 합니다. 객체(object)를 초기화하는 방법은 new 연산자를 사용하여 객체를 변수에 인스턴스 시키는 것입니다.
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// Add $num articles of $artnr to the cart

function add_item ($artnr, $num) {
$this->items[$artnr] += $num;
}

// Take $num articles of $artnr out of the cart

function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
}

$cart = new Cart;
$cart->add_item("10", 1); [/code]
위와 같이 하면 클래스 Cart에 대한 객체 $cart가 생성됩니다. 객체 함수 add_item()은 장바구니에 품목번호 "10"의 수량을 1개 추가하기 위해 호출됩니다.
지정연산자 "->"의 의미
"->" 는 객체의 멤버변수 또는 메소드를 지정하는데 사용되는 지정연산자입니다. C++ 언어를 접해 본 분은 쉽게 이해하시겠지만, new 연산자로 생성되는 객체를 나타내는 객체명에는 실제로 객체의 멤버(변수 또는 함수)가 존재하는 것이 아니라 객체의 멤버가 존재하는 메모리상에 위치를 나타내는 주소(adress)가 담겨져 있습니다. 이와 같이 객체지향언어에서는 주소를 가지고 멤버를 참조하려면 아래와 같이 지정연산자 "->"를 이용하게 됩니다.
멤버변수를 참조할 때 : 객체명->변수;
메소드를 참조할 때 : 객체명->함수;
C++ 언어에서는 "->"를 화살표 멤버 연산자라고 말하며, "->"의 앞쪽에 있는 식별자(여기서는 객체명)가 포인터(pointer; 주소를 의미함)일 때 그 멤버를 참조하기 위한 연산자입니다.
지역 변수에 초기화된 객체
객체를 지역변수에 인스턴스할 수 있기 때문에, 클래스를 정의하고 객체를 생성하는 것을 하나의 모듈로 개발할 수 있습니다.
[code php;gutter:false] <?php

function class_in_function() {
class test {
var $a = 10;
function test() {
echo "함수 내에 정의된 클래스의 생성자 실행\n";
}
function echo_test() {
echo "함수 내에 정의된 클래스의 멤버변수 \$a의 값 = ".$this->a."\n";
}
}

$obj = new test;
$obj->echo_test();
}

class_in_function();
?> [/code]
< 예제 코드 >
함수 내에 정의된 클래스의 생성자 실행
함수 내에 정의된 클래스의 멤버변수 $a의 값 = 10
< 실행 결과 >
객체 생성할 때 생성자명을 가변함수로 지정하기
[code php;gutter:false] $classname = "MiniDB";
$obj = new $classname(); [/code]
이 코드는 PHP3와 PHP4 모두에서 정상적으로 동작합니다.
메소드명을 변경하기(가변함수)
PHP의 매뉴얼을 보면 가변함수(variable function)를 지원하는데 이것은 변수명 뒤에 괄호가 왔을 때, PHP는 그 이름을 가진 함수를 찾아 실행하는 것입니다. 이것은 클래스의 메소드에서도 그대로 사용할 수 있습니다.
[code php;gutter:false] class test {
function A() {
echo "나 A 함수\n";
}
}

$obj = new test;

$method = "A";
$obj->$method(); [/code]
이것을 응용하여 같은 실행문으로 A0, A1, A2라는 메소드에 번갈아 가면서 접근하려면 역시 가변함수를 사용하면 됩니다.
[code php;gutter:false] class test {
function A0() {
echo "나 A0 함수\n";
}

function A1() {
echo "나 A1 함수\n";
}
function A2() {
echo "나 A2 함수\n";
}
}

$obj = new test;

for ($i=0;$i<3;$i++) {
$method = "A$i" ;
$obj->$method();
} [/code]
위에 것은 모두 PHP3와 PHP4에서 모두 동작되는 코드입니다. 만약, PHP4에서만 동작시켜도 무방하다면 아래와 같이 중괄호를 이용하면 소스를 간결하게 코딩할 수 있습니다.
[code php;gutter:false] for ($i=0;$i<3;$i++) {
$obj->{"a$i"}();
} [/code]
객체명을 변경하기(가변변수)
가변변수(Variable Variables)의 유용함은 모두 알고 있겠지만 PHP4에서는 별문제가 없지만 PHP3에서 객체변수를 가변변수로 사용하기는 그리 쉽지 않습니다.
[code php;gutter:false] class test {
var $hello = "hello world";
}

$obj = new test;
$a = "obj";
echo $$a->hello; // or echo ${$a}->hello; [/code]
PHP3에서 위와 같이 작성하여 실행한다면,
Object
Parse error: parse error, ...... test.php3 on line 9
위와 같은 에러를 만나게 됩니다. 그러나 PHP4에서는 객체변수에도 가변변수를 제대로 지원하기 시작했습니다. 따라서 위의 예제가 에러없이 잘 실행되지요. 그러면 PHP3에서는 객체변수의 이름을 변경할 수 없을까요? 아래와 같이 $GLOBALS 배열을 사용해 보세요. 아무 문제없이 잘 실행될 겁니다.
[code php;gutter:false] class test {
var $hello = "hello world";
}

$obj = new test;
$a = "obj";
echo $GLOBALS[$a]->world(); [/code]
따라서 PHP3와 PHP4 모두에서 동작되기를 바란다면 $GLOBALS 배열을 이용하여 작성하세요.
배열구조의 멤버변수를 가변변수로 다루는 방법
[code php;gutter:false] class test {
var $arr = array();

function test() {
$this->arr[0] = 0;
$this->arr[1] = 1;
}
}

$obj = new test; [/code]
위와 같이 클래스 test에 배열 구조의 멤버변수가 있을 때, 이러한 멤버변수의 배열 요소에 접근하려면 $obj->arr[0]; 와 같이 사용하면 됩니다. 여기서 멤버변수명 "arr"을 가변변수로 처리하려면,
[code php;gutter:false] $prop = "arr";
$obj->{"$prop"}[0]; [/code]
위와 같이 가변변수 $prop를 중괄호로 묶어주세요. 여기서 겹따옴표는 생략해도 됩니다. PHP3와 PHP4에서 모두 잘 동작할 것입니다.

Posted by 방글24
phpclass/클래스활용2000. 7. 13. 13:50
PHP에서 클래스를 사용하는 방법에 대하여 알아봅니다.
클래스란?
클래스는 객체의 변수와 함수를 정의하는 템플릿이며, 이에 따라 변수로 표현되는 데이터 영역과 이러한 데이터 영역에 접근할 수 있는 함수로 구성됩니다. 클래스 내에 정의된 변수를 멤버변수(member variable)라고 하고 함수를 메소드(method)라고 합니다. C++과 같은 객체지향언어에서는 멤버변수를 데이터멤버, 메소드를 멤버함수라고 호칭합니다. PHP에서 클래스를 사용하는 것은 C++ 또는 자바와 거의 비슷합니다.
클래스 정의
클래스를 정의(class definition)할 때는 키워드 "class"를 사용합니다. 클래스를 구성하는 멤버변수와 메소드를 정의할 때는 "var"과 "function"이라는 키워드를 사용합니다. "function"은 일반 함수를 정의할 때도 사용되지만 "var"은 클래스의 멤버변수를 정의할 때만 사용되는 키워드로, 멤버변수를 정의할 때는 반드시 명시하여야 합니다. 예를 들어 클래스는 아래와 같이 정의합니다. 이 예는 PHP 매뉴얼에 있는 것으로 수정하지 않고 가져왔습니다. 이 예에서는 $items라는 멤버변수와 add_item, remove_item라는 메소드가 정의되어 있습니다.
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

// Add $num articles of $artnr to the cart

function add_item ($artnr, $num) {
$this->items[$artnr] += $num;
}

// Take $num articles of $artnr out of the cart

function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
} [/code]
멤버변수의 초기화
PHP3에서는 멤버변수값을 아래와 같이 상수 또는 변수를 이용하여 초기화할 수 있습니다.
[code php;gutter:false] class Cart {
var $items = 0; // Items in our shopping cart
} [/code]
< 상수로 초기화할 때 >
[code php;gutter:false] class Cart {
var $items; // Items in our shopping cart

function Cart($items) {
$this->items = $items;
}
} [/code]
< 변수로 초기화할 때(1) >
[code php;gutter:false] $items = 0;

class Cart {
var $items = $GLOBALS["items"]; // Items in our shopping cart
} [/code]
< 변수로 초기화할 때(2) >
반면 PHP4에서는 var 변수에는 상수로만 초기화할 수 있고, 상수가 아닌 값을 가지고 초기화할 때는 생성자를 이용하여야 합니다. 즉, var $items = $GLOBALS["items"];와 같은 표현은 허용하지 않습니다.
따라서 아래와 같은 표현은 PHP4에서는 허용하지 않습니다.
[code php;gutter:false] class Cart {
var $todays_date = date("Y-m-d");
var $name = $firstname;
var $owner = 'Fred ' . 'Jones';
var $items = array("VCR", "TV");
} [/code]
PHP4에서 초기화할 때 동일한 결과를 얻으려면 아래와 같이 생성자를 이용합니다.
[code php;gutter:false] class Cart {
var $todays_date;
var $name;
var $owner;
var $items;

function Cart() {
$this->todays_date = date("Y-m-d");
$this->name = $GLOBALS['firstname'];
/* etc. . . */
}
} [/code]
PHP4 예약어
stdClass
stdClass 는 Zend에서 내부적으로 사용하고 있는 예약어입니다. 따라서 사용자는 클래스명으로 stdClass를 사용할 수 없습니다. get_declared_classes() 함수를 사용하면 현재 스크립트에 정의된 클래스명을 배열에 담아 되돌려 줍니다. 따라서 이 함수를 이용하면 stdClass의 존재를 확인할 수 있습니다.
[code php;gutter:false] <?php

class Vegetable {

}

class Spinach extends Vegetable {

}

$arr_class = get_declared_classes();

while (list($k,$v)=each($arr_class)) {
echo("\$arr_class[$k]=$v\n");
}

?> [/code]
이 문서를 실행하면 아래와 같은 결과를 얻을 수 있습니다.
[code php;gutter:false] $arr_class[0]=stdClass
$arr_class[1]=OverloadedTestClass
$arr_class[2]=Directory
$arr_class[3]=OCI-Lob
$arr_class[4]=vegetable
$arr_class[5]=spinach [/code]
위 예제의 실행결과를 보면, 사용자가 정의한 vegetable, spinach 외에도 stdClass, OverloadedTestClass, Directory, OCI-Lob가 있는 것을 볼 수 있습니다. 좀 더 자세한 것은 메뉴 "클래스&객체 함수 >> get_declared_classes()"를 살펴보시기 바랍니다.
매직함수(magic function)
__sleep, __wakeup과 같이 "__"로 시작하는 매직함수는 PHP 클래스 내에서 특수한 목적으로 사용됩니다. 따라서 이 함수들이 가지고 있는 문서화된 매직 기능을 사용할 필요가 없다면 클래스 내에 이 함수들을 정의해서는 안됩니다. 자세한 것은 메뉴에서 "매직함수"장을 살펴보기 바랍니다.
$this가 무엇에 쓰는 물건인고?
클래스 메소드 내에서만 사용되며, 클래스의 현재 인스턴스를 참조할 때 사용하는 변수이며, 예를 들어 현재 객체 내에 something라고 명명된 임의의 변수 또는 함수를 참조하기 위해서는 $this->something을 사용하여야 합니다. 즉, "$this"의 의미는 new 연산자에 의해 생성될 객체 자신을 의미합니다. 그러니 아직 생성되지 않은 객체 자신을 의미하는 의사(擬似)변수(pseudo variable)이며, "my own" 또는 "current object"라고 불리웁니다.
앞에서 클래스를 붕어빵 틀과 같다고 했습니다. 정의된 클래스에 의해 생성된 객체는 붕어빵 틀로 만들어낸 수많은 붕어빵이지요. 아래 예에서 본다면, $붕어빵1->make("특급밀가루")으로 make() 메소드에 접근한다면 이 때 make() 메소드 내의 $this는 $붕어빵1을 의미하고, $붕어빵2->make("중급밀가루")으로 접근한다면 이 때 $this는 $붕어빵2를 의미하고, $붕어빵3->make("저급밀가루")으로 접근한다면 이 때 $this는 $붕어빵3을 의미합니다.
[code php;gutter:false] class 붕어빵 {
var 재료;

function make($재료) {
$this->재료 = $재료;
......
}
}

$붕어빵1 = new 붕어빵; // 인스턴스 "붕어빵1"
$붕어빵2 = new 붕어빵; // 인스턴스 "붕어빵2"
$붕어빵3 = new 붕어빵; // 인스턴스 "붕어빵3"

$붕어빵1->make("특급밀가루");
$붕어빵2->make("중급밀가루");
$붕어빵3->make("저급밀가루"); [/code]

Posted by 방글24