cake php 사용법

2017.01.15 07:47

졸리운_곰 조회 수:2436

cake php 사용법

cakePHP.doc cakePHP.doc

 

0. 머리말(Preface)#

0.1. 대상#

이 매뉴얼은 웹 애플리케이션을 보다 빠르고, 좀더 즐겁게 만들고 싶어하는 사람들을 위해 쓰여졌다. CakePHP는 모든 수준의 PHP 유저가 쉽고 빠르게, 견고하고 유지보수하기 쉬운 애플리케이션을 만드는 것을 지원한다.

이 매뉴얼은 PHP와 HTML의 기본 지식이 필요하다. Model-View-Controller (MVC) 프로그래밍 패턴에 대해 알고 있으면 도움이 된다. 그러나 MVC 에 처음 접하는 이들도 이해할 수 있도록 도중에 설명을 더할 것이다. 웹 서버의 설정과 트러블슈팅을 위한 설명이 있지만, 모든 점을 다루는 것은 이 매뉴얼의 범위 밖이다.

응급치료(심페기능 소생법)의 기초지식, 기초적인 생존 기술, 데이트 & 대인관계의 기초 지식도 권장되지만 그것도 이 문서의 범위 밖이다.

 0.2. CakePHP 는 무료이다#

 CakePHP 는 뮤료이다. 돈을 지불할 필요도 없으며, 마음대로 사용할 수 있다. CakePHP 는 MIT 라이센스에 따라 개발되었다. CakePHP 는 오픈소스 프로젝트이다. 이것은 여러분이 소스코드에 대해 모두 접근할 수 있다는 뜻이다. 최신 버전은 CakePHP 웹사이트 (http://www.cakephp.org) 에서 구할 수 있다. 또한 이 웹사이트에서 최신의 가장 좋은 코드를 열람할 수 있다.

 0.3. 커뮤니티#

CakePHP 는 근면한 사람들의 커뮤니티에 의해 개발되었다. 전세계의 여러 나라에서 모였으며, 가능한 많은 사람에게 도움을 주는 CakePHP 프레임워크를 개발하기 위해 협력하고 있다. Cake 의 활동적인 개발자와 사용자 커뮤니티의 정보를 더 알고 싶다면 http://www.cakephp.org 를 방문하라.

CakePHP 의 IRC 채널은 항상 박식하며, 친절한 베이커(Baker)들로 가득 차 있다. 만일 여러분이 약간의 코드에

 

1. 소개 (Introduction to CakePHP)#

1.1. CakePHP 는 무엇인가?#

 CakePHP 는 PHP 용 무료 오픈 소스 초고속 개발 프레임워크이다.  웹 애플리케이션을 만드는 프로그래머를 위한 이것의 라이브러리 구조, 클래스와 런타임 인프라스트럭쳐는 원래 루비에 의해 영감을 받았다. 우리의 최우선 목표는 유연성을 잃지 않고, 구조화되고 신속한 방법으로 작업할 수 있게 하는 것이다.

 

1.2. 왜 CakePHP 인가?#

신속하고, 최소한의 혼란으로 애플리케이션을 개발하기 위한 프레임워크로서 CakePHP 가 탁월한 선택이 되는 몇가지 특징이 있다. 순서없이 몇가지를 열거하자면 다음과 같다 : 

  • 활동적이고, 친밀한 커뮤니티
  • 유연한 라이센스
  • PHP4, PHP5 와의 호환성
  • 데이터베이스 인터랙션과 간략화한 쿼리를 위한 CRUD 가 통합됨
  • 애플리케이션 스캐폴딩
  • 모델 뷰 컨트롤러 (MVC) 구조
  • 보기좋은 맞춤 URL 의 요청 디스패처
  • 자료 검사 기능 내장
  • 빠르고 유연한 템플릿 기능 (PHP 문법, 각종 헬퍼 포함 )
  • AJAX, 자바스크립트, HTML 폼을 위한 각종 뷰 헬퍼
  • 보안, 세션, 리퀘스트 등을 처리하는 컴포넌트
  • 유연한 접근 제한 목록
  • 불법 자료 삭제
  • 유연한 뷰 캐시
  • 웹사이트의 어떤 서브 디렉토리에서든 작동, 아파치는 전혀 손대지 않거나 약간의 설정

 

1.3. CakePHP 의 역사#

2005년,  Michal Tatarynowicz 는 PHP 내에서 초고속 애플리케이션 프레임워크의 최소버전을 짰다. 그는 매우 좋은 프레임워크의 시작이었다는 것을 알았다. Michal 은 Cake 라 부르기로 하며, MIT 라이센스로 개발자 커뮤니티에 공개했다. 현재 CakePHP 란 이름 아래 Cake 를 보수하고 있다.

2. 기본 개념 (Basic Concepts)#

 2.1. 머리말#

이 장에서는 Cake 에 내장되어 있는 MVC 개념에 대해 간략하게 소개한다. MVC (모델 뷰 컨트롤러) 패턴을 처음 대한다면, 여러분을 위한 장이 될 것이다. 우선, 일반적인 MVC 개념에 대해 검토한 뒤, CakePHP 의 MVC 의 구제척인 애플리케이션을 만든다. 그후 MVC 패턴을 사용한 CakePHP 의 간단한 예를 몇가지 소개하겠다.

 

 

2.2. MVC 패턴#

모델-뷰-컨트롤러는 코드를 논리적으로 분리하고, 재활용하기 용이하며, 관리하기 쉽고, 일반적으로 개선된 소프트웨어 디자인 패턴이다. 모델-뷰-컨트롤러는 집필그룹 Gang for Four 에 의해 처음 소개되었다. Dean Helman 은 다음과 같이 썼다 (Objective Toolkit Pro white paper 에서 인용) :

 " MVC 패러다임은 애플리케이션, 또는 애플리케이션의 일부분까지도 모델, 뷰, 컨트롤러라고 하는 3개의 부분으로 분할하는 방법이다. MVC 는 본래부터 입력, 처리, 출력이라고 하는 지금까지 이용되어 왔던 역할을 하고, GUI 의 영역에서 확실히 자리매김하기 위해 개발된 것이다."

입력 -> 처리 -> 출력

컨트롤러 -> 모델 -> 뷰

"유저의 입력, 외부 세계의 모델링, 그리고 유저의 눈으로 보이는 피드백으로 각각 분할되어,모델,뷰 포트,컨트롤러 오브젝트에 의하여 처리된다.컨트롤러는 유저로부터 마우스와 키보드의 입력을 포착하고,유저의 액션을 커맨드에 결부시킨다.그것은 모델과(또는) 뷰 포트에 보내고, 적절한 변화를 가져온다.모델은 하나 또는 여러개의 데이터 요소를 관리하고, 그 상태에 관한 질의에 반응한다. 그리고 상태를 변경하라는 지시에 반응한다. 뷰 포트는 사각형의 디스플레이를 관리하고, 그래픽와 텍스트의 조합으로 유저에게 데이터를 제공한 책임을 갖는다."

 Cake 의 용어에서, 모델은 특정한 데이터베이스의 테이블/레코드,  다른 테이블이나 레코드와의 관계를 나타낸다. 모델은 또한 데이터의 검증 규칙도 포함하고 있고, 모델 데이터가 삽입또는 갱신될 때 사용된다. view 는 Cake 의 출력 파일로, PHP 코드가 기록된 일반적인 HTML 파일이다. Cake 의 컨트롤러는 서버로부터의 리퀘스트를 처리한다. 컨트롤러는 유저의 입력(URL 과 POST 데이터)를 접수, 비즈니스 로직을 적용하여 모델을 사용하여 데이터베이스의 데이터를 읽고 쓰고, 마지막으로 출력 데이터를 적절한 출력 파일에 보낸다.

애플리케이션을 가능한 간단하게 조직화하기 위해 Cake 는 단지 오브젝트의 관계 관리만을 위해가 아니라 파일의 저장 방법까지 관리하기 위해 이 패턴을 이용한다. 자세한 것은 다음 부분에 설명한다.

 2.3. Cake 의 파일 배치 개요#

서버에 Cake 의 압축을 풀면, 3개의 주요 폴더가 나타난다. 

  1. app

< >cake vandors  

 

 

cake 폴더에는 Cake 의 핵심 라이브러리가 있으며, 일반적으로 건드릴 필요가 없다.

 app 폴더에는 애플리케이션의 구체적인 폴더나 파일이 들어갈 것이다.  cake 폴더와 app 폴더를 분리함으로써, 여러 app 폴더에 하나의 Cake 라이브러리를 공유할 수 있다. 이로써 CakePHP 의 업데이트도 간단하게 된다. 최신 버전의 CakePHP 를 다운로드하여 현재의 핵심 라이브러리를 덮어쓰기만 하면 된다. 자신의 app 를 위해 작성했던 코드가 덮어 씌워질 걱정이 없다.

 vendors 디렉토리는 써드 파티의 라이브러리를 저장하는 장소이다. vendors 에 관해 나중에 좀더 설명하겠지만, 기본적인 개념으로 vendors 디렉토리에 저장된 클래스에는 Cake 의 vendor() 함수를 사용해 접근할 수 있다.

 전체 파일 구조에 대해 보자 

< >/app
    /config          - 데이터베이스, ACL 등의 설정 파일

    /controllers     - 컨트롤러는 이 디렉토리에 둔다.
        /components  - 컴포넌트는 이 디렉토리에 둔다.

    /index.php       - /app 를 DocumentRoot 로 쓰이도록 한다.

    /models          - 모델은 이 디렉토리에 둔다.
 
    /plugins         - 플러그인은 이 디렉토리에 둔다.

    /tmp             - 캐시와 로그로 사용

    /vendors         - 이 애플리케이션에 이용하는 써드 파티 라이브러리

    /views           - 뷰 파일은 이 디렉토리에 둔다.
        /elements    - 엘러먼트, 소형 뷰들은 이 디렉토리에 둔다.
        /errors      - 커스텀 에러 페이지는 이 디렉토리에 둔다.
        /helpers     - 헬퍼는 이 디렉토리에 둔다.
        /layouts     - 애플리케이션 레이아웃 파일은 이 디렉토리에 둔다.
        /pages       - 동적으로 작성하지 않아도 좋은 파일은 이 디렉토리에 둔다.

    /webroot         - 애플리케이션의 DocumentRoot
        /css
        /files
        /img
        /js

/cake                - Cake 의 핵심 라이브러리. 이 디렉토리에내의 어떤 파일도 편집해서는 안 된다.

index.php          

/vendors             - 서버 전체가 사용하는 써드 파티의 라이브러리

VERSION.txt          - 현재 사용하고 있는 Cake 의 버젼을 알 수 있다.

3.1. 머리말#

그럼 이제, 여러분은 CakePHP 의 모든 라이브러리 구조와 목적에 관해 알고 있다, 또는 그런 것들에는 관심이 없고 바로 실행해보기 위해 여기로 건너 뛰었을 것이다. 어느 쪽이든, 팔을 걷어 붙히고 준비하라.

이 장에서는, 서버에 설치해야 할 것, 몇가지 서버설정의 방법, CakePHP 의 다운로드와 설치, CakePHP 의 기본 페이지의 표시, 원할히 진행되지 않는 경우의 몇가지 트러블 슈팅 팁에 대해 설명한다. 

3.2. 요구사항#

CakePHP 를 사용하려면, 먼저 CakePHP 를 실행시키기 위한 모든 라이브러리와 프로그램이 설치된 서버가 필요하다. 

3.2.1. 서버 요구사항#

 CakePHP 를 작동시키기 위한 서버의 셋업 조건은 아래와 같다. 

< >다음 사항이 가능한 HTTP 서버 (아파치등) : session, mod_write (필수는 아니지만 권장사항) PHP 4.3.2 이상. CakePHP 는 PHP4 와 PHP5 모두 잘 작동한다 데이터베이스 엔진 (현재 MySQL, ProsgreSQL, ADODB 지원) #

 

3.3.1. 최신 안정판 구하기#

CakePHP 를 입수하는 방법은 여러 가지가 있다 : CakeForge 에서 안정판 다운로드하기, 나이틀리 빌드 가져오기, 또는 SVN 으로 부터 프레시 버전 가져오기

안정판의 코드를 다운로드하려면,  http://cakeforge.org/projects/cakephp/ 에서 CakeForge 의 CakePHP 의 섹션에 있는 파일을 체크한다.

나이틀리는 http://cakephp.org/downloads/index/nightly 에서 다운로드 받을 수 있다.이 나이틀리 릴리즈는 안정판이며 다음 안정판까지의 버그 픽스가 가끔 포함되어 있다.

프레시 버전을 SVN 저장소에서 가져오려면, 자신이 사용하고 있는 SVN 클라이언트를 사용하여 https://svn.cakephp.org/repo/trunk/cake/ 에 접속한 뒤, 버전을 선택한다.

3.3.2. 언패킹#

최신 버전을 다운로드하면, 압축되어 있는 패키지를 웹서버에 올린다. CakePHP 패키지의 패키지를 푸는 두가지 방법이 있다. 하나의 도메인의 아래에 다수의 CakePHP 애플리케이션을 두는 개발용 셋업, 또는 한개의 도메인에 한개의 CakePHP 애플리케이션을 두는 공개용 셋업이다. 

3.4. CakePHP 셋업#

CakePHP 의 첫번째의 셋업 방법은 두번째 방법에 비해 안전하지 않기 때문에, 일반적으로 개발환경용으로 권장되는 방법이다. 두번째 방법은 보다 안전하며 공개환경으로 사용되어야 한다. 

주의 : /app/tmp 는 웹서버를 사용하는 유저에게 반드시 쓰기 권한을 줘야 한다. 

3.4.1. 개발용 셋업(Development Setup)#

개발시에는 특정 DocumentRoot 속에 Cake 의 인스톨 디렉토리를 아래와 같이 통채로 배치할 수 있다. 

< >/wwwroot
    /cake
        /app
        /cake
        /vendors
        .htaccess
        index.php www.example.com/cake/콘트롤러명/액션명/파라미터1/파라미터2   3.4.2. 공개용 셋업(Production Setup)#

 

공개용 셋업을 사용하려면, 서버의 DocumentRoot 에 대한 변경 권한을 갖고 있어야 한다. 이렇게 하면 도메인 전부를 하나의 CakePHP 애플리케이션으로서 움직이게 할 수 있다. 

공개용 셋업은 아래의 배치를 사용한다. : 

< >../path_to_cake_install
    /app
        /config
        /controllers
        /models
        /plugins
        /tmp
        /vendors
        /views
        /webroot <-- 이 디렉토리는 새로운 DocumentRoot 가 된다.
        .htaccess
        index.php
    /cake
    /vendors
    .htaccess
    index.php  DocumentRoot /path_to_cake/app/webroot  http://www.example.com/콘트롤러명/액션명/파라미터1/파라미터2  

 

3.4.3. 고급 셋업 : 다른 설치 방법#

Cake 의 디렉토리를 디스크의 다른 장소에 두고 싶은 경우가 있다. 공유 서버의 제한 때문이거나 여러개의 app 가 동일한 Cake 라이브러리를 공유하도록 하고 싶은 때 등이다. 

Cake 애플리케이션에는 3개의 주요 부분이 있다.

< >CakePHP 의 핵심 라이브러리 - /cake 애플리케이션 코드 (컨트롤러, 모델, 레이아웃, 뷰등) - /app 애플리케이션의 webroot 파일 (이미지, 자바스크립트, css) - /app/webroot  ROOT 는 여러분의 app 폴더를 포함하는 디렉토리의 경로를 설정한다. APP_DIR 는 여러분의 app 폴더의 경로명을 설정한다. CAKE_CORE_INCLUDE_PATH 는 Cake 라이브러리 폴더의 경로를 설정한다.  if (!defined('ROOT')){
    define('ROOT', dirname(dirname(dirname(__FILE__))));
}

if (!defined('APP_DIR')){
    define ('APP_DIR', basename(dirname(dirname(__FILE__))));
}

if (!defined('CAKE_CORE_INCLUDE_PATH')){
    define('CAKE_CORE_INCLUDE_PATH', ROOT);
} Cake 라이브러리를 다른 애플리케이션과 공유하고 싶다. 경로는 /usr/lib/cake. Cake webroot 디렉토리는 /var/www/mysite/ 가 되어야 한다. 애플리케이션 파일은 /home/me/mysite 에 넣는다.  파일 설정은 이와 같이 한다 :
/home
    /me
        /mysite                  <-- /cake_install/app 로 사용된다
            /config
            /controllers
            /models
            /plugins
            /tmp
            /vendors
            /views
            index.php
/var
    /www
        /mysite                  <-- /cake_install/app/webroot 로 사용된다
            /css
            /files
            /img
            /js
            .htaccess
            css.php
            favicon.ico
            index.php
/usr
    /lib
        /cake                    <-- /cake_install/cake 로 사용된다
            /cake
                /config
                /docs
                /libs
                /scripts
                app_controller.php
                app_model.php
                basics.php
                bootstrap.php
                dispatcher.php
            /vendors  if (!defined('ROOT')){
    define('ROOT', DS.'home'.DS.'me');
}

if (!defined('APP_DIR')){
    define ('APP_DIR', 'mysite');
}

if (!defined('CAKE_CORE_INCLUDE_PATH')){
    define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'lib'.DS.'cake');
}  #

CakePHP 는 mod_write 와 간단히 연동되도록 만들어져 있지만, 시스템이 잘 작동할 때 까지 고생하는 유저도 있을 수 있다. 바르게 작동하기 위해서 아래와 같이 시도해 볼 수 있다 :

< >/htaccess 의 override 가 허가되어 있는 것을 확인한다 : httpd.conf 내에 서버의 각 디렉토리를 정의하고 있는 부분이 필요하다. 해당 디렉토리에 AllowOverrideAll 로 설정되어 있는지 확인한다. 유저나 사이트 특유의 httpd.conf 가 아니라 시스템의 httpd.conf 를 수정하고 있는지 확인한다. 어떤 이유로, 필요한 .htaccess 파일이 없는 CakePHP 소스를 입수하는 경우도 있다.운영 체제 중에는 '.' 로 시작된 파일을 숨김 속성으로 취급,복사하지 않기 때문이다. 공식 사이트의 다운로드 섹션이나 CakePHP 의 SVN 저장소의 소스인지 확인한다. mod_write 가 올바르게 로딩되고 있는지 확인하라. httpd.conf 내에 LoadModule rewrite_module libexec/httpd/mod_rewrite.so 그리고 AddModule mod_rewrite.c 가 있을 것이다. 만일 Cake 를 유저 디렉토리 (http://example.com/~myusername/) 에 설치했다면, Cake 설치 디렉토리의 .htaccess 파일을 수정해야 한다. 딱 한 줄 "RewriteBase /~myusername/" 을 추가하면 된다. 만일 어떤 이유로, URL 뒤에 길고 알 수 없는 세션 아이디 (http://example.com/posts/?CAKEPHP=4kgj577sgabvnmhjgkdiuy1956if6ska) 가 붙는다면, 설치 루트 디렉토리의 .htaccess 파일에 "php_flag session.trans_id off" 를 추가하면 된다.  #

자, 작동이 되는지 확인하자. 어떤 설정을 사용하고 있는지에 따라, 브라우저에 http://www.example.com  또는 http://www.example.com/cake 를 쳐보자.이때에 CakePHP 의 기본 페이지가 표시되고, 현재의 데이터베이스 접속 상태에 관한 메시지가 나올 것이다. 

축하한다! 여러분은 Cake 기반의 애플리케이션을 구축할 준비가 되었다.

 

4. 설정 (Configuration)#

 

4.1. 데이터베이스의 설정#

app/config/database.php 파일에서 모든 데이터베이스 설정을 한다. 처음 설치를 하면, database.php 는 존재 하지 않기 때문에, database.php.default 를 복사하여 작성하고, 파일명을 변경한다. 다음과 같이 나타날 것이다 :

 

예 4.1. app/config/database.php

 

< >var $default = array('driver'   => 'mysql',
                     'connect'  => 'mysql_connect',
                     'host'     => 'localhost',
                     'login'    => 'user',
                     'password' => 'password',
                     'database' => 'project_name',
                     'prefix'   => '');  

 

기본값의 데이터베이스 접속 정보를 자신의 애플리케이션용으로 고친다.

 

'prefix' (접두사) 키에 대해 : 여기에 설정한 문자열이, 어떠한 SQL 호출의 테이블명 앞에 추가된다. 이 하나의 설정이 모든 곳에서 사용된다. 데이터베이스가 하나 밖에 없는 호스팅을 이용하는 경우에서도 이렇게 쓰는 것으로 Cake 의 테이블 규약을 따를 수 있다. 주의 : HABTM 조인 테이블은 한번만 접두사가 붙는다 : prefix_apples_bananas (O), prefix_apples_prefix_bananas (X).

 

CakePHP 는, 다음 데이터베이스 드라이버를 지원한다 :

 

< >mysqlpostgressqlitepear-드라이버명 (예를 들면, pear-mysql 등.)adodb-드라이버명 

 

$default 접속 중에 있는 'connect' 키로, 데이타베이스 접속을 지속적으로 할것인지 정할 수 있다. database.php.default 파일내에 있는 주석을 참고하여 데이타베이스의 셋업의 타입을 지정한다.

 

또한 데이터베이스 테이블은 다음 규약을 따를 필요가 있다 :

 

< >Cake 에서 사용하는 테이블명은, 영어의 복수형으로 한다. "users", "authors"  또는 "articles" 등이다. 주의 : 대응하는 모델의 이름은 단수형이다.테이블에는 'id' 라는 이름의 주요키 (primary key) 가 반드시 있어야 한다.테이블끼리 관련 지을 경우, 외부키 (foreign key) 는 'article_id' 와 같이 한다. 테이블명의 단수형으로 언더바를 붙이고, 맨마지막에 'id' 를 붙인다.테이블에 'created' (작성) 와/또는 'modified' (수정) 이라는 컬럼이 있으면, Cake 는 적절한 시기에 필드에 데이터를 자동으로 넣는다. 

 

database.php 파일내에는 $test 접속 설정도 포함된다. 여기에 설정을 입력(또는 같은 포맷에 설정을 추가)하고 애플리케이션의 model 중에 다음과 같이 설정해 이용한다.

 

< >var $useDbConfig = 'test';  

 

이 방법으로 임의의 접속 설정을 추가할 수 있다.

 

4.2. 전역 설정#

CakePHP 의 전역 설정은 app/config/core.php 에서 한다. 설정 파일이라는 것을 정말 좋아하지 않지만, 작성할 수 밖에 없었다. 여기에서 몇가지를 변경할 수 있다. core.php 의 주석중에 각각의 설정에 관한 주의사항이 기재되어 있다.

 

DEBUG : 애플리케이션을 만들 때의 디버그 설정을 지정한다. 0 이 아닌 값이면 Cake 는 pr()과 debug() 함수를 호출하여 결과를 출력하고, flash 메시지에 의한 페이지 전송을 자동으로 멈춘다. 값을 2 이상으로 설정하면 페이지의 맨 마지막 부분에 SQL 명령문의 결과가 표시된다.

 

또한 디버그 모드(DEBUG의 값이 1 이상)일 때, Cake 는 "Missing Controller" (컨트롤러가 존재하지 않습니다) "Missing Action" (액션이 존재하지 않습니다) 라고 하는 에러 페이지를 생성하게 된다. 그러나 공개모드 (DEBUG의 값이 0)일 때, Cake 는 app/views/errors/error404.thtml 에 있는 "페이지가 존재하지 않습니다" 라고 하는 페이지를 표시한다.

 

CAKE_SESSION_COOKIE : Cake 애플리케이션에 세션을 사용할 때, 쿠키의 이름을 지정한다.

 

CAKE_SECURITY : 세션 체크 레벨을 지정할 수 있다. 설정에 따라 세션의 타임 아웃, 새로운 세션 ID의 생성, 오래된 세션의 파일의 삭제등을 한다. 설정값은 다음과 같다.

 

< >high : 10초 동안 아무것도 하지 않으면 세션 타임 아웃. 세션 ID를 요청할 때마다 재생성한다. medium : 20분 동안 아무것도 하지 않으면 세션 타임 아웃. low : 30분 동안 아무것도 하지 않으면 세션 타임 아웃.  

 

CAKE_SESSION_SAVE : 세션 데이터의 저장 방법을 지정한다. 설정 가능한 값은 다음과 같다.

 

< >cake : 세션 데이터는 Cake 를 인스톨한 디렉토리내 tmp/ 에 저장된다. php : 세션 데이터는 php.ini 에 저장된 경로에 저장된다. database : 세션 데이터는 'default' 키로 정의된 데이터베이스에 접속해서 저장된다.  4.3. 라우트 설정#

 

"라우팅" 은 PHP 로 구현되는 mod_rewrite 의 축소판 비슷한 것이다. URL로부터 컨트롤러/액션/파라미터를 매핑하고 역으로도 실행한다. 보기좋은 URL(pretty URLs)을 좀 더 설정하기 쉽게 하고, mod_rewrite 가 없이 작동하기 위해 Cake 에 추가되었다. 그러나, mod_rewrite 를 사용하면 주소창은 훨씬 깔끔해진다. 

라우트에서는 적합한 URL을 특정한 컨트롤러와 액션에 결부시키는 개별적인 룰이다. 라우트는 app/config/routes.php 파일내에 설정되며, 아래와 같이 설정한다. 

예 4.2. 라우트 패턴 예제 

< ><?php $Route->connect (
    'URL',
    array('controller'=>'컨트롤러명',
    'action'=>'액션명', '최초의 파라미터')
); ?>  URL 은 매핑하는 Cake URL 의 정규표현식이다. 컨트롤러명은 호출되는 컨트롤러이다. 액션명은 호출되는 컨트롤러의 액션명이다. 그리고 최초의 파라미터는 임의의 액션 파라미터 값을 설정할 수 있다.  

 

최초의 파라미터 이후의 이은 파라미터도 컨트롤러의 액션에 파라미터로 넘겨 받는다. 

다음의 예에서는 /blog 의 모든 URL을 BlogController 에 접속한다. 기본 액션은 BlogController::index() 가 된다. 

예 4.3. 라우트 예제 

< ><?php $Route->connect ('/blog/:action/*', array('controller'=>'Blog', 'action'=>'index')); ?>  /blog/history/05/june 이라는 URL 은 다음과 같이 조작된다. 

 

예 4.4. 컨트롤러에서의 라우트 핸들링 

< ><?php
class BlogController extends AppController {
 function history ($year, $month=null) {
   // .. 적절한 내용 표시
 }
}
?>  URL 의 'history' 는 Blog 의 라우트의 :action 에 적합하다. * 에 적합한 URL 의 요소는 작동중인 컨트롤러가 다루고 있는 메소드에 파라미터로서 넘겨 받는다. 즉 $year 와 $month 가 된다. /blog/history/05 라는 URL이 호출된 경우 history() 에는 05 라는 하나의 파라미터만 넘겨 받는다. 

 

다음 예는 PagesController::display('home') 를 사용하기 위한 CakePHP 의 기본 라우트 설정이다. Home 은 /app/views/pages/home.thtml 이라는 파일을 작성하는 것으로 이것을 표현하는 뷰가 된다 

예 4.5. 라우트 초기 설정 

< ><?php connect ('/', array('controller'=>'Pages', 'action'=>'display', 'home')); ?>  

 

4.4 고급 라우팅 설정 : 어드민 라우팅과 웹서비스#

/app/config/core.php 의 설정중에는 애플리케이션을 체계화 하고 개발자와 유저에 있어서 알기 쉬운 URL을 만들기 위해 도움이 되는 것이 있다. 

먼저, 어드민 라우팅 (admin routing) 이 있다. 애플리케이션으로 ProductController 와 NewsController 가 있는 경우, 관리자 권한이 있는 사람만 접근 가능한 특별한 URL 을 준비하고, 컨트롤러가 특별한 액션으로 접근할 수 있도록 하고 싶은 경우가 있다. URL 을 이해하기 쉬운 좋은 상태로 하기 위해, 어떤 사람은 /admin/products/add 와 /admin/news/post 와 같은 것을 준비할 수 있겠지만, /product/adminAdd 와 /news/adminPost 와 같이 하고 싶은 사람도 있을 수 있다. 

이와 같이 구현하려면, 우선 /app/config/core.php 파일에 있는 CAKE_ADMIN 의 아래행의 주석을 삭제한다. CAKE_ADMIN 의 기본값은 'admin' 이지만 원하는 대로 변경할 수 있다. 컨트롤러내에서의 관리자 액션을 추가할 때 필요하기 때문에, 이 문자열을 기억해 두어야 한다. 이 경우의 관리 액션은 admin_actinoName() 이라는 이름이 된다. 바람직한 URL 과 가능한 CAKE_ADMIN 과 컨트롤 액션의 설정의 예는 다음과 같다. 

< >/admin/products/add            CAKE_ADMIN = 'admin'                               ProductsController 의 액션명은 = 'admin_add()' 

 

/superuser/news/post           CAKE_ADMIN = 'superuser'

                               NewsController 의 액션명은 = 'superuser_post()' 

/admin/posts/delete            CAKE_ADMIN = 'admin'
                               PostsController 의 액션명은 = 'admin_delete()' 

어드민 라우팅을 사용하면, 로직을 지저분하게 하는 일 없이 라우팅을 아주 간단히 구현할 수 있다. 가능할 경우, 어드민 라우팅을 다음과 같이 사용한다면 쉽게 컨트롤러를 정의할 수 있다 : 

< >$this->params[CAKE_ADMIN];  또는  $this->params['admin']; ('admin' 은 CAKE_ADMIN 의 값이라고 가정한다) 

 

어드민 라우팅을 유효하게 하거나 이것을 사용하는 것은 어떤 인증이나 보안등이 실행될 수 없다는 점을 주의하라. 그것은 자신이 직접 이행해야 한다. 

동일하게, Cake 의 웹서비스 라우팅을 쓸 수 있도록 하고, 간략화할 수 있다. 컨트롤러의 액션을 웹서비스로 공개하고 싶은가? 우선, /app/config/core.php 의 WEBSERVICES 를 'on' 으로 고친다. 루트 어드민 라우팅과 같은 방식으로 자동으로 라우팅되게 된다. 단 이미 정의된 몇가지 셋팅이 있다 : 

< >rss xml rest soap xmlrpc  이것에 의해 /rss/컨트롤러명/액션명 이나, /soap/컨트롤러명/액션명 으로 사용할 수 있다. 다른 뷰를 준비할 수도 있다. 즉 두개의 뷰를 가진 하나의 액션을 만들 수 있다. 하나는 일반적인 HTML 을 보여주는 인용의 뷰, 다른 하나는 웹서비스를 이용하는 사람을 위한 뷰이다. 이렇게 하면, 애플리케이션의 많은 기능을 웹서비스로 공개할 수 있게 된다. 

 

예를 들면, 애플리케이션 중에 사무실의 누가 전화중인가를 표시하는 로직이 있다고 하자. 이 데이터를 표시하는 HTML 의 뷰는 이미 있지만, XML로도 제공할 수 있도록 데스크톱 위젯이나 PDA의 애플리케이션 등에서도 사용할 수 있도록 하고 싶다. 우선, Cake 의 웹서비스를 사용할 수 있게 한다. 

예 4.6. /app/config/core.php (일부) 

< >/**
 *  The define below is used to turn cake built webservices
 *  on or off. Default setting is off.
 */
    define('WEBSERVICES', 'on');  다음, 컨트롤러의 로직을 다음과 같이 구성한다 : 

 

예 4.7. messages_controller.php 

< ><?php
class PhonesController extends AppController{
    function doWhosOnline()    {
        // 이 액션은, 누가 전화중인가 조사하는 모든 작업을 행하는 곳...

        // Cake 의 xml 웹서비스 라우트를 통해 이 액션을 공개하고 싶은 경우
        // /app/views/posts/xml/do_whos_online.thtml 내에 뷰를 포함시킨다.
        // 주의 : 여기서 사용하는 기본 view 는 /app/views/layouts/xml/default.thtml 이다.

        // 유저가 /phones/doWhosOnline 를 요청하면, HTML 버전의 데이터를 받게 된다.
        // 유저가 /xml/phones/doWhosOnline 를 요청하면, XML 버전의 데이터를 받게 된다.
    }
}
?>  

 

 

4.5. (옵션) 커스텀 인플렉션(어형 변화) 설정#

Cake 의 네이밍 규약은 꽤 편리하다. 모델 Box (단수) 에 이름을 붙여 컨트롤러 Boxes (복수) 가 되며, 모두 잘 작동한다. 하지만, Cake 의 인플렉터 (복수형, 단수형, 낙타표기법, 언더바를 만드는 클래스) 가 자신이 원하는대로 작동하지 않는 경우 (특히 영어외의 언어를 이용하고 있는 경우) 도 있다. 만일, Foci (fish) 를 인식해 주지 않는 경우, 커스텀 인플렉션 설정 파일을 수정한다. 

/app/config/inflections.php 에는 Cake 의 클래스명에 사용된다. 수정 가능한 복수형, 단수형의 변수 목록이 있다. 또 불규칙형과 함께, 전혀 변화하지 않는 단어 (야외 스포츠 애호가인 Caker 들을 위한 Fish 나 Deer 와 같이) 도 정의된다.

 

5. 스캐폴딩 (Scaffolding)# 

5.1 Cake 의 스캐폴딩은 꽤 쿨하다#

프로덕션 애플리케이션에서도 사용하고 싶을 만큼 쿨할지 모른다. 지금, 우리도 꽤 쿨하다고 생각한다. 하지만 스캐폴딩은..그러니까...스캐폴딩(비계,임시가설물)이라는 것을 이해하기 바란다. 프로젝트의 시작시에는 정말 신속함으로 상당한 작업을 떠 맡아 주지만 완벽하게 유연하다는 의미는 아니다. 때문에 만일 로직이나 뷰를 커스터마이징하고 싶어지면, 스캐폴딩을 그만두고 여러분의 코드를 써야 한다. 

스캐폴딩은 웹애플리케이션의 개발 초기 시점에서 매우 우수한 방법이다. 초기의 데이터베이스 스키마는 자주 변경되며, 변하기 쉬운 주제다. 이것은 설계 프로세스의 초기단계에서는 지극히 정상적인 것이다. 여기에는 단점 (웹개발자는 앞으로 사용되는 일이 없는 폼을 만드는 것을 싫어 한다) 을 가지고 있다. 개발자의 이 부담을 줄이기 위해서 스캐폴딩이 Cake 에 포함되어 있다. 스캐폴딩은 데이터베이스의 테이블을 분석하고 표준 목록과 추가, 삭제, 수정 버튼, 편집 폼, 데이터베이스의 하나의 아이템을 표시하기 위한 표준 뷰 등을 만들어 낸다. 애플리케이션으로 스캐폴딩을 추가하려면, 컨트롤러내에 $scaffold 변수를 추가한다 : 

< ><?php
class CategoriesController extends AppController{
    var $scaffold;
}
?>  

 

스캐폴드에 대해서 중요한 사항이 하나 있다. 스캐폴드에서는 _id 로 끝나는 필드명은 언더바의 앞부분의 테이블명의 외부 키라고 판단한다. 예를 들어 카테고리를 만들었다면 parent_id  라는 컬럼을 갖게될 것이다. 이 릴리즈에서는 parentid 라고 부르는 것이 최선일 것이다. 또 만일 테이블에 외부키가 있는 경우 (예를 들어, titles 테이블에 있는 category_id) 가 있고, 모델이 적절하게 관련되어 있는 경우 (어소시에이션을 이해해야한다. 6.2 참조), show/edit/new 의 뷰 중에 셀렉트 박스가 표시되고, 거기에 외부 테이블 (카테고리) 의 열이 표시된다. 외부 테이블의 필드를 표시되게 설정하려면, 외부 모델의 $displayField 변수를 설정한다. 이 예제의 카테고리로 타이틀을 붙이려면 다음과 같이 한다. 

< ><?php
class Title extends AppModel{
    var $name = 'Title';

    var $displayField = 'title';
}
?>  

 

5.2 스캐폴드 뷰의 커스터마이징#

스캐폴드의 view 를 조금 변경하고 싶다면, 직접 view 를 만들 수 있다. 공개용 애플리케이션에 이 기법을 사용하는 것은 권장하지 않지만, 프로토 타입 제작을 반복할 때 이 커스터마이징은 대단히 편리하다. 

스캐폴드의 뷰를 변경하고 싶은 경우 스스로 직접 준비한다 : 

예 5.1. 단일 컨트롤러용 커스텀 스캐폴딩 뷰 

< >PostsController 용의 커스텀 스캐폴딩 뷰를 다음과 같이 저장한다 : /app/views/posts/scaffold/index.scaffold.thtml /app/views/posts/scaffold/show.scaffold.thtml /app/views/posts/scaffold/edit.scaffold.thtml /app/views/posts/scaffold/new.scaffold.thtml  예 5.2. 애플리케이션 전체용 커스텀 스캐폴딩 view 

 

< >모든 컨트롤러용 커스텀 스캐폴딩 뷰를 다음과 같이 저장한다 :
/app/views/scaffold/index.scaffold.thtml
/app/views/scaffold/show.scaffold.thtml
/app/views/scaffold/edit.scaffold.thtml
/app/views/scaffold/new.scaffold.thtml  컨트롤러의 로직을 이 시점에서 변경하고 싶다면, 스캐폴딩을 애플리케이션에서 제외하고 로직을 만들기 시작한다.

 

Cake 의 코드 생성기, Bake 도 편리하게 쓸만한 기능중 하나다. Bake 는 스캐폴딩된 코드를 생성하고, 자신의 애플리케이션의 필요에 따라 수정, 커스터마이징할 수 있게 한다.

 

6. 모델 (Models)# 

6.1. 모델이란?#

모델은 어떤 일을 하는가? 도메인 로직을 표시 부분에서 분리하고, 애플리케이션의 로직만을 분리한다. 

모델이란 일반적으로 데이터베이스를 나타낸다. 더 구체적으로 데이터베이스내의 특정 테이블을 나타낸다. 기본적으로 각각의 모델은 복수형의 이름이 붙은 테이블에 대응하는 단수형의 클래스가 된다. 예를 들면, 'User' 모델은 'Users' 테이블을 사용한다. 모델에는 또 데이터 검증 (validation) 을 위한 룰, 관련 (association) 정보, 테이블 특유의 메소드 등을 포함시킬 수 있다. 다음은 간단한 User 모델이 Cake 내에서 어떻게 되는지 보여준다. 

예 6.1. User 모델의 예, /app/models/user.php 에 저장 

<?php
//AppModel 에서는 Cake 의 모델의 기능을 전부 제공하고 있다
class User extends AppModel{
    // 이 변수를 포함시는 것은 항상 좋은 습관이다
    var $name = 'User';

    // 이것은 검증 (validation) 에 사용된다, "자료 검증 (Data Validation)" 장을 보라.
    var $validate = array();

    // 관련 (association) 을 정의할 수 이다.
    // 6.3 섹션에 자세히 나온다.
    var $hasMany = array('Image' =>
                   array('className' => 'Image')
                   );
    // 사용자 함수를 포함시킬 수 있다:
    function makeInactive($uid)    {
        // 자신 로직을 여기에...
    }
}

?>

 

6.2. 모델 함수#

PHP 에서 보면, 모델은 AppModel 클래스를 확장 (extend) 한 클래스이다. 원래의 AppModel 클래스는 cake/ 디레토리에 선언되어 있지만, 직접 다시 만들 경우  app/app_model.php 에 둘 수 있다. 이 안에는 여러 모델을 공유하는 메소드를 넣는다. 이 클래스는 cake/libs/model/model.php 내에 선언되어 있는 표준 Cake 라이브러리의 하나인 모델 (Model) 클래스를 확장한 것이다. 

이 섹션에서는 Cake 모델에 관해 자주 사용되는 함수에 대해 다루지만, 전체 레퍼런스는 http://api.cakephp.org 에 있는 것을 기억해 둬야 한다. 

6.2.1. 사용자 함수#

모델내에 테이블 특유의 메소드를 쓰는 예로, 블로그의 포스트를 감추고/보이는 한쌍의 메소드를 보여준다 

예 6.2. 모델 함수의 예 

< ><?php
class Post extends AppModel {
   var $name = 'Post';

   function hide ($id=null)   {
      if ($id) {
          $this->id = $id;
          $this->saveField('hidden', '1');
      }
   }

   function unhide ($id=null) {
      if ($id) {
          $this->id = $id;
          $this->saveField('hidden', '0');
      }
   }
}
?> #

 

다음은 모델을 이용해 데이터를 추출하는 몇가지 표준적인 방법이다. 

< >findAll string $conditions array $fields string $order int $limit int $page int $recursive  find string $conditions array $fields string $order int $recursive  findAllBy<fieldName> string $value  $this->Post->findByTitle('My First Blog Post');
$this->Author->findByLastName('Rogers');
$this->Property->findAllByState('AZ');
$this->Specimen->findAllByKingdom('Animalia');  findNeighboursstring $conditions array $field string $value  class ImagesController extends AppController {
    function view($id) {
        // 이미지를 표시하고 싶다고 말한다...
        $this->set('image', $this->Image->find("id = $id");

        // 하지만, '이전'과 '다음' 이미지도 필요한 경우에는..
        $this->set('neighbours', $this->Image->findNeighbours(null, 'id', $id);    }
}  

 

이와 같이 하면, $ image['Image'] 배열 전체와, $neighbours['prev']['Image']['id'] 와 $ neighbours['next']['Image']['id'] 를 view 에서 사용할 수 있다. 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

< >field string $name string $conditions string $order  findCount string $conditions  generateList string $conditions string $order int $limit string $keyPath string $valuePath  $this->set(
    'Roles',
    $this->Role->generateList(null, 'role_name ASC', null, '{n}.Role.id', '{n}.Role.role_name')
);

// 이와 같이 반환될 것이다.
array(
    '1' => 'Account Manager',
    '2' => 'Account Viewer',
    '3' => 'System Manager',
    '4' => 'Site Visitor'
);  readstring $fields string $id  query string $query  execute string $query  <?php

 

class Post extends AppModel {

    var $name = 'Post';

    function posterFirstName() {

        $ret = $this->query("SELECT first_name FROM posters_table

                                 WHERE poster_id = 1");

        $firstName = $ret[0]['first_name'];

        return $firstName;

    }

}

?>

6.2.3. 복합 조건 검색 (배열 이용)#

대부분의 모델의 find 호출은 하나 또는 다른 조건 전달을 수반한다. 이것의 가장 간단한 접근은 SQL 에 WHERE 절을 사용하는 것이지만, 더 많은 조작이 필요하다면, 배열을 사용할 수 있다. 배열을 사용하면 더욱 읽기 쉽고, 깔끔하며 게다가 쿼리 작성이 쉬워진다. 이 문법은 신중하고 잘 다룰 수 있는 부분 속으로 쿼리의 요소 (필드, 값, 조작자, 등) 를 분리해 준다. 이것은 Cake 가 매우 효율적인 쿼리를 생성할 수 있도록 허락하고, 올바른 SQL 문법을 보장하며, 쿼리의 개별적 부분을 올바르게 뽑는다. 

매우 기본적으로, 배열 기반의 쿼리는 다음과 같이 보여진다 :

 

예 6.4. 기본적인 find 조건 배열 사용예 : 

< >$conditions = array("Post.title" => "This is a post");

//모델과 함께 사용한 예:
$this->Post->find($conditions);  array("Post.title" => "<> This is a post")  array("Post.title" => array("First post", "Second post", "Third post"))  array(
    "Post.title"   => array("First post", "Second post", "Third post"),
    "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks"))
)  array
("or" =>
    array
    (
        "Post.title" => array("First post", "Second post", "Third post"),
        "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks"))
    )
)  array
("Author.name" => "Bob", "or" => array
    (
        "Post.title" => "LIKE %magic%",
        "Post.created" => "> " . date('Y-m-d', strtotime("-2 weeks")
    )
) 6.2.4. 데이터 저장#

 

모델에 데이터를 저장하려면, 저장하고 싶은 데이터를 준비한다. save() 메소드로 전달받은 데이터는 다음과 같은 형식으로 다뤄진다 : 

< >Array
(
    [ModelName] => Array
        (
            [fieldname1] => 'value'
            [fieldname2] => 'value'
        )
)  function edit($id){
   // 주의 : 속성 모델은 $this->Property 에 자동으로 불러낸다

   // 폼데이터가 존재하는지 검사...
   if (empty($this->data)) {
        $this->Property->id = $id;
        $this->data = $this->Property->read();// 현재 지정된 열의 데이터를 폼 필드에 넣을 수 있다
   } else {
      // 데이터를 저장하는 부분이다. 자동으로 자료 검증(validation)을 한다.
      if ($this->Property->save($this->data['Property'])) {
         // 메시지를 표시(flash)하거나 리다이렉트한다.
         $this->flash('Your information has been saved.',
                     '/properties/view/'.$this->data['Property']['id'], 2);
      }
      // 만일 잘못된 필드가 존재하거나 저장이 실패한 경우 이 형식이 표시된다
   }
}  

 

save 동작이 조건문 안에 위치하는 것에 주의한다. 모델에 데이타를 저장하려고 하는 경우, Cake 는 지정 되어 있는 룰에 기초하여 자동적으로 데이타가 올바른지 체크한다. 자료 검증과 관련된 상세 정보는 "12. 자료 검증(validation)"을 참조한다. save() 에 자료 검증을 할 필요가 없는 경우에는 save($data, false) 를 사용한다. 

기타 유용한 함수 : 

< >del string $id boolean $cascade  saveField string $name string $value  getLastInsertId  #

모델의 동작 전후에 로직을 넣어을 때, 몇 모델에 콜백이 추가되었다. 애플리케이션 내에서 이 기능을 사용하려면 지정된 파라미터를 사용하고 Cake 의 모델의 이러한 함수를 오버라이드(override)한다.

 

< >beforeFind string $conditions afterFind array $results beforeValidate beforeSave // HTML 헬퍼로 작성한 date/time :
// 이 코드는 view 에 있다.

$html->dayOptionTag('Event/start');
$html->monthOptionTag('Event/start');
$html->yearOptionTag('Event/start');
$html->hourOptionTag('Event/start');
$html->minuteOptionTag('Event/start'); // 모델 콜백 함수는 날짜 데이터를 연결해 모두 저장한다
// 이 코드는 그 이벤트 모델에 있다 :

function beforeSave()
{
    $this->data['Event']['start'] = $this->_getDate('Event', 'start');

    return true;
}

function _getDate($model, $field)
{
    return date('Y-m-d H:i:s', mktime(
        intval($this->data[$model][$field . '_hour']),
        intval($this->data[$model][$field . '_min']),
        null,
        intval($this->data[$model][$field . '_month']),
        intval($this->data[$model][$field . '_day']),
        intval($this->data[$model][$field . '_year'])));
} afterSave beforeDelete afterDelete #

모델을 작성할 때, 특별한 몇가지 변수를 설정하는 것으로 Cake 의 기능을 이용할 수 있다.

 

$primaryKey

 

모델이 데이터베이스의 테이블에 관련되어 있는 경우, 테이블의 primary key 명이 'id' 가 아닌 경우, 이 변수를 사용하여 어느 필드가 primary key 인지를 Cake 에 알린다.

 

$recursive

 

find() 와 findAll() 의 동작중에, 관련되어 있는 모델의 데이터를 몇 레벨까지 불러(fetch) 올 것인지를 설정한다.

Groups (그룹) 이 있고, 이 그룹에 Users (유저) 가 있고, 각 유저가 많은 Articles (게시물) 을 갖고 있다고 가정하자.

 

테이블 6.1. Model::recursive 옵션

$recursive = 0

Cake 는 Group 데이터를 불러 온다.

$recursive = 1

Cake 는 Group 과 관련된 Users 를 불러 온다.

$recursive = 2

Cake 는 Group 과 관련된 Users 와 그 User 애 관련된 Articels 를 불러온다

$transactional

이 모델로 트랜잭션 가능한지 아닌지 Cake 에 지시합니다 (begin/commit/rollback). boolean 값으로 설정한다. 트랜잭션을 지원하고 있는 데이터베이스만 사용할 수 있다.

 

$useTable

 

사용하고 싶은 테이블이 모델명의 복수형이 되어 있지 않은 경우 (그리고, 테이블명을 변경하기 싫은 경우), 이 변수로 사용하고 싶은데 테이블명을 설정한다.

 

$validate

 

이 모델에 전달받은 데이터를 발리 자료 검증하는 데 사용되는 배열이다. 상세한 것은 "자료 검증" 장을 참조한다.

 

$useDbConfig

 

데이터베이스의 설정은, /app/config/database.php 에서 설정하는 것을 기억는가? 그것을 바꾸기 위해서 이 변수를 사용한다. 작성한 데이터베이스 설정 파일에 있는 사용 가능한 데이타베이스 접속명을 쓴다. 기본값은, 'default' 이다.

 

6.4. 연관 (association)#

6.4.1. 소개#

CakePHP 대단히 강력한 기능중 하나는 모델에 의한 관계 매핑(relational mapping) 이다. CakePHP 에서는, 테이블의 관계를 연관(association)을 통해 다룬다. 연관은 논리적으로 관련되어 있는 유닛을 연결하는 접착제이다.

 

CakePHP 에는 네종류의 연관이 있다

< >hasOnehasManybelongsTohasAndBelongsToMany외부키 : [모델명의 단수형]_id. 예를 들어, "authors" 테이블내의 외부키가 Post 일 경우, Author 에 속한 것은 "post_id" 가 된다. 테이블명 : [객체명의 복수형]. 블로그의 포스트(post)와 작성자(author)의 정보를 저장하고 싶기 때문에, 테이블 명은 각각, "posts" 와, "authors" 가 된다. 모델명 : [낙타표기법의 테이블 단수형]. "posts" 테이블에 대한 모델은 "Post", 그리고 "authors" 테이블에는 "Author". #

이 연관을 설정하기 위해, 이미 User 와 Profile 모델은 작성되어 있어야 한다. 이 두개 사이에 hasOne 연관을 정의하려면, 모델에 하나의 배열을 추가하고 Cake 에 관련 방법을 전달한다.

다음과 같이하면 된다.

 

예 6.4. /app/models/user.php hasOne

 

< ><?php
class User extends AppModel
{
    var $name = 'User';
    var $hasOne = array('Profile' =>
                        array('className'    => 'Profile',
                              'conditions'   => '',
                              'order'        => '',
                              'dependent'    =>  true,
                              'foreignKey'   => 'user_id'
                        )
                  );
}
?> className (필수): 연관짓고 싶은 모델의 클래스명위 예제에서는, 'Profile' 모델의 클래스명을 지정하고 있다.

 

< >conditions: 관계를 정의한 SQL 조건의 일부필요하면 녹색의 헤더가 붙은 프로필만 관련 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "Profile.header_color = 'green'".

 

< >order: 연관된 모델의 데이터 정렬연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "Profile.name ASC".

 

< >dependent: true 로 설정하면, 이 모델의 데이터 삭제시에 연관되어 있는 모델 측의 데이터도 삭제된다.예를 들면, 프로필 "Cool Blue" 가 "Bob" 에 연관되어 있는 경우, "Bob" 라는 유저를 삭제하고, 프로필 "Cool Blue" 도 삭제된다.

 

< >foreignKey: 연관되어 있는 모델을 가리키고 있는 외부키의 이름Cake 의 네이밍 규약에 따라서 없는 데이터베이스를 사용하고 있는 경우에 여기서 지정할 수 있다.

 

 

이제, User 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 Profile 모델도 함께 볼 수 있다.

 

< >$user = $this->User->read(null, '25');
print_r($user);

// 출력:

Array
(
    [User] => Array
        (
            [id] => 25
            [first_name] => John
            [last_name] => Anderson
            [username] => psychic
            [password] => c4k3roxx
        )

    [Profile] => Array
        (
            [id] => 4
            [name] => Cool Blue
            [header_color] => aquamarine
            [user_id] = 25
        )
) #

이제 User 는 Profile 을 볼 수 있다. 이번에는 Profile 이 User 를 보이도록 한다. Cake 에서는 belongsTo 연관을 사용하는 것으로 가능하게 된다. Profile 모델 내에서 다음과 같이 한다 :

 

예 6.5. /app/models/profile.php belongsTo

 

< ><?php
class Profile extends AppModel
{
    var $name = 'Profile';
    var $belongsTo = array('User' =>
                           array('className'  => 'User',
                                 'conditions' => '',
                                 'order'      => '',
                                 'foreignKey' => 'user_id'
                           )
                     );
}
?> className (필수): 연관짓고 싶은 모델의 클래스명위 예제에서는, 'User' 모델의 클래스명을 지정하고 있다.

 

< >conditions: 관계를 정의한 SQL 조건의 일부active 상태의 User 만을 연관 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "User.active = '1'" 등.

 

< >order: 연관된 모델의 데이터 정렬연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "User.last_name ASC".

 

< >foreignKey: 연관되어 있는 모델을 가리키고 있는 외부키의 이름Cake 의 네이밍 규약에 따라서 없는 데이터베이스를 사용하고 있는 경우에 여기서 지정할 수 있다.

 

 

이제, Profile 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 User 모델도 함께 볼 수 이다 :

 

< >$profile = $this->Profile->read(null, '4');
print_r($profile);

// 출력:

Array
(

    [Profile] => Array
        (
            [id] => 4
            [name] => Cool Blue
            [header_color] => aquamarine
            [user_id] = 25
        )

    [User] => Array
        (
            [id] => 25
            [first_name] => John
            [last_name] => Anderson
            [username] => psychic
            [password] => c4k3roxx
        )
) #

User 모델과 Profile 모델이 연관되고, 올바르게 작동하게 되었기 때문에, User 레코드를 Comment 레코드와 연관시켜 보도록 한다. 이것은, User 모델을 다음과 같이 하는 것으로 가능하다 :

 

예 6.6. /app/models/user.php hasMany

 

< ><?php
class User extends AppModel
{
    var $name = 'User';
    var $hasMany = array('Comment' =>
                         array('className'     => 'Comment',
                               'conditions'    => 'Comment.moderated = 1',
                               'order'         => 'Comment.created DESC',
                               'limit'         => '5',
                               'foreignKey'    => 'user_id',
                               'dependent'     => true,
                               'exclusive'     => false,
                               'finderQuery'   => ''
                         )
                  );

    // 방금전에 정의했던 hasOne 의 관계..
    var $hasOne = array('Profile' =>
                        array('className'    => 'Profile',
                              'conditions'   => '',
                              'order'        => '',
                              'dependent'    =>  true,
                              'foreignKey'   => 'user_id'
                        )
                  );
}
?> className (필수): 연관짓고 싶은 모델의 클래스명위 예제에서는, 'Comment' 모델의 클래스명을 지정하고 있다.

 

< >conditions: 관계를 정의한 SQL 조건의 일부조정된(moderated) Comment 만을 연관 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "Comment.moderated = 1" 등.

 

< >order: 연관된 모델의 데이터 정렬연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "Comment.created DESC" 등.

 

< >limit: Cake 가 불러오는 관련 모델의 데이터의 최대 갯수위 예에서는, 유저의 Comment 를 전부 불러오지 않고 5개만 불러온다.

 

< >foreignKey: 연관되어 있는 모델을 가리키고 있는 외부키의 이름Cake 의 네이밍 규약에 따라서 없는 데이터베이스를 사용하고 있는 경우에 여기서 지정할 수 있다.

 

< >dependent: true 로 설정하면, 이 모델의 데이터 삭제시에 연관되어 있는 모델 측의 데이터도 삭제된다. 예를 들면, 프로필 "Cool Blue" 가 "Bob" 에 연관되어 있는 경우, "Bob" 라는 유저를 삭제하고, 프로필 "Cool Blue" 도 삭제된다.

 

< >exclusive: true 로 설정하면, 연관된 모든 객체가 하나의 SQL 구문의로 삭제된다. beforeDelete 콜백은 실행되지 않는다.빠르게 작동하기 때문에 간단한 연관에서 활용할 수 있다.

 

< >finderQuery: 연관을 불러오기 위해 완전한 SQL 구문을 지정한다.여러 테이블에 의존하는 복잡한 연관의 경우에 활용할 수 있다. 만일 Cake 의 자동 연관을 사용할 수 없을 경우에, 이것으로 커스터마이징이 가능하다.

 

 

이제, User 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 Comment 모델도 함께 볼 수 있다 :

 

< >$user = $this->User->read(null, '25');
print_r($user);

//output:

Array
(
    [User] => Array
        (
            [id] => 25
            [first_name] => John
            [last_name] => Anderson
            [username] => psychic
            [password] => c4k3roxx
        )

    [Profile] => Array
        (
            [id] => 4
            [name] => Cool Blue
            [header_color] => aquamarine
            [user_id] = 25
        )

    [Comment] => Array
        (
            [0] => Array
                (
                    [id] => 247
                    [user_id] => 25
                    [body] => The hasMany assocation is nice to have.
                )

            [1] => Array
                (
                    [id] => 256
                    [user_id] => 25
                    [body] => The hasMany assocation is really nice to have.
                )

            [2] => Array
                (
                    [id] => 269
                    [user_id] => 25
                    [body] => The hasMany assocation is really, really nice to have.
                )

            [3] => Array
                (
                    [id] => 285
                    [user_id] => 25
                    [body] => The hasMany assocation is extremely nice to have.
                )

            [4] => Array
                (
                    [id] => 286
                    [user_id] => 25
                    [body] => The hasMany assocation is super nice to have.
                )

        )
) #

간단한 연관에 관해서는 이것으로 마스터 가능하다. 다음으로는, 마지막 연관 : hasAndBelongsToMany (또는 HABTM) 으로 이동하자. 이것은 간단히 이해되지는 않겠지만, 가장 유용한 것중 하나이다. HABTM 연관은, 두개의 테이블이 있고, 그 두개를 조인 테이블로 연결되어 때 유용하다. 조인 테이블은 다른 것과 관련하고 있는 개별적인 열의 정보를 갖는다.

 

hasMany 와 hasAndBelongsToMany 의 차이는, hasMany 의 경우, 관련되어 있는 모델의 데이타를 공유할 수 없다는 것이다. 만일 User hasMany Comments (User 가 여러 Comment 를 갖고 있다) 라면, Comment 와 관련되어 있는 것은, User *뿐*이다. HABTM 는, 관련된 모델 데이타를 공유할 수 있다. 이것은 다음 경우에 매우 탁월하다 : Post 모델을 Tag 모델에 연관시킬 때. Tag 는 Post 에 belongs to(속할) 의 관계이지만, 소모해 버리는 것은 바람직하지 않다, Tag 는 계속해서 다른 Post 부터도 연관시키고 싶기 때문이다.

 

그러기 위해서는, 이 연관를 위해서 테이블을 바르게 설정할 필요가 있다. 물론, Tag 모델을 위한 "tags" 테이블, 그리고 Post 모델을 위한 "posts" 테이블이 필요합니다. 그리고, 연관을 위해서, 새로 조인 테이블을 생성할 필요도 있다. HABTM 조인 테이블 네이밍 규약은 [복수형 모델명1]_[복수형 모델명2] 이다. 모델명은 알파벳 순서대로 정렬한다 :

 

예 6.7. HABTM 조인 테이블 : 샘플 모델과 조인 테이블명

< >Posts 와 Tags: posts_tagsMonkeys 와 ceCubes: ice_cubes_monkeysCategories 와 Articles: articles_categories--
-- Table structure for table `posts`
--

CREATE TABLE `posts` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `user_id` int(10) default NULL,
  `title` varchar(50) default NULL,
  `body` text,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  `status` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) TYPE=MyISAM;

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

--
-- Table structure for table `posts_tags`
--

CREATE TABLE `posts_tags` (
  `post_id` int(10) unsigned NOT NULL default '0',
  `tag_id` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`post_id`,`tag_id`)
) TYPE=MyISAM;

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

--
-- Table structure for table `tags`
--

CREATE TABLE `tags` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `tag` varchar(100) default NULL,
  PRIMARY KEY  (`id`)
) TYPE=MyISAM; <?php
class Post extends AppModel
{
    var $name = 'Post';
    var $hasAndBelongsToMany = array('Tag' =>
                               array('className'    => 'Tag',
                                     'joinTable'    => 'posts_tags',
                                     'foreignKey'   => 'post_id',
                                     'associationForeignKey'=> 'tag_id',
                                     'conditions'   => '',
                                     'order'        => '',
                                     'limit'        => '',
                                     'unique'       => true,
                                     'finderQuery'  => '',
                                     'deleteQuery'  => '',
                               )
                               );
}
?> className (필수): 연관짓고 싶은 모델의 클래스명위 예제에서는, 'Tag' 모델의 클래스명을 지정하고 있다.

 

< >joinTable: Cake 의 네이밍 규약에 따라서 없는 데이터베이스의 경우는 여기에서 설정한다. [복수형 모델1]_[복수형 모델2] 의 사전적인 순서이 되어 있지 않은 경우에는, 테이블명은 여기에서 지정한다.foreignKey: 현재의 모델을 가리키는 조인 테이블 내의 외부 키의 이름.Cake 의 네이밍 규약에 따라서 없는 데이터베이스의 경우는 여기에서 설정한다.

 

< >associationForeignKey: 연관되어 있는 모델을 가리키는 외부 키의 이름.conditions: 관계를 정의한 SQL 조건의 일부입증된(approved) Tag 만을 연관 짓도록 Cake 에 명령할때, 다음과 같이 키를 설정하면 가능하다 : "Tag.approved = 1" 등

 

< >order: 연관된 모델의 데이터 정렬연관된 모델을 특정 순서로 정렬하고 싶은 경우, 이 키로 SQL 의 order 방법으로 값을 설정한다, 예를 들면 : "Tag.tag DESC DESC" 등.

 

< >limit: Cake 가 불러오는 관련 모델의 데이터의 최대 갯수불러올 연관된 Tags 의 갯수를 한정할 때 사용한다.

 

< >unique: true 로 설정하면, 액세스와 쿼리 메소드에서, 관련된 객체가 중복되는 경우에는 무시한다.기본적으로, 관계가 별개로 되어 있는 경우에는, true 로 설정한다. 그렇다면, "Awesomeness" 이라는 tag는, Post 의 "Cake Model Associations" 에 한 번만 분배되고, 결과 배열 중에은, 한 번밖에 나타나지 않는다.

 

< >finderQuery: 연관을 불러오기 위해 완전한 SQL 구문을 지정한다.여러 테이블에 의존하는 복잡한 연관의 경우에 활용할 수 있다. 만일 Cake 의 자동 연관을 사용할 수 없을 경우에, 이것으로 커스터마이징이 가능하다.

 

< >deleteQuery: HABTM 모델간의 연관 데이터를 없애는 완전한 SQL 구문이다.Cake 의 삭제 방법이 바람직하지 않거나, 설정이 커스터마이징 되어 있는 경우에, 자신의 쿼리를 여기에 설정하여 삭제 동작 방법을 변경할 수 있다.

 

 

이제, Post 모델로 find() 또는 findAll() 을 호출하면, 연관되어 있는 Tag 모델도 함께 볼 수 있다 :

 

< >$post = $this->Post->read(null, '2');
print_r($post);

//output:

Array
(
    [Post] => Array
        (
            [id] => 2
            [user_id] => 25
            [title] => Cake Model Associations
            [body] => Time saving, easy, and powerful.
            [created] => 2006-04-15 09:33:24
            [modified] => 2006-04-15 09:33:24
            [status] => 1
        )

    [Tag] => Array
        (
            [0] => Array
                (
                    [id] => 247
                    [tag] => CakePHP
                )

            [1] => Array
                (
                    [id] => 256
                    [tag] => Powerful Software
                )
        )
) #

관련된 모델로 작업할 때 기억해야할 중요한 주의사항 하나는, 모델 데이터의 저장은 언제나 대응하는 케이크 모델에 의해 행해져야 한다는 것이다. 만약 새로운 Post 하나와 이 Post 에 관련된 Comment 들을 저장한다면 저장 작업동안 Post 와 Comment 모두를 사용할 것이다.

 

만일 관련된 모델이 어느쪽도 아직 존재하지 않는다면 (예를 들어, 새로운 Post 와 관련된 Comment 를 동시에 저장하고 싶다), 먼저 주가되거나 부모의 모델을 먼저 저장할 필요가 있을 것이다. 이것이 어떻게 작동하는지 아이딩어를 얻으려면, 새로운 Post 와 관련된 Comment 의 저장을 다루는 PostsController 내의 액션을 갖고 있다고 상상하자. 아래 예로 든 액션은 하나의 Post 와 하나의 Comment 를 작성했다고 가정한다.

 

예 6.4.5 /app/controllers/posts_controller.php (일부)

 

< >function add()
{
    if (!empty($this->data))
    {
        //Post 데이터를 저장할 수 있다:
        //이것은 $this->data['Post'] 속에 있을 것이다
      
        $this->Post->save($this->data);

        //자, Comment 데이터를 저장할 필요가 있다.
        //하지만 먼저, 방금 저장한 Post 의 ID 를 알아 내야 한다...

        $post_id = $this->Post->getLastInsertId();

        //이제 데이터를 저장하고 comment 를 저장하기 위한 이 정보를 추가한다.

        $this->data['Comment']['post_id'] = $post_id;

        //Post hasMany Comments 관련 때문에
        //Post 모델을 통해 Comment 모델에 접근할 수 있다 :

        $this->Post->Comment->save($this->data);

    }
} //이곳에서 URL 파라미터가 어떻게 사용되는지 볼 수 있다...
function addComment($post_id)
{
    if (!empty($this->data))
    {
        //$post_id 를 더욱 안전하게 만들어 싶었을 지 모른다,
        //하지만 이 작동 예제에서는 이것으로 족하다..

        $this->data['Comment']['post_id'] = $post_id;

        //Post hasMany Comments 관련 때문에
        //Post 모델을 통해 Comment 모델에 접근할 수 있다 :

        $this->Post->Comment->save($this->data);
    }
} 만약 Post 의 ID 가 $post['Post']['id'] 에 있다면...

<?php echo $html->hidden('Comment/post_id', array('value' => $post['Post']['id'])); ?> #

hasOne, belongsTo, hasMany 로 연관되는 모델을 저장하는 것은 대단히 간단하다. 관련되는 모델의 ID 와, 외부 키의 필드를 설정하면 된다. 그 후 모델의 save() 메소드를 호출하면, 연결된 모든 것들이 바르게 조합된다.

 

hasAndBelongsToMany 는 좀더 막연하지만, 가능한 간단하게 해 보자. 예를 보는 동안, Tags 는 Posts 에 연관되어 있는 폼을 작성할 필요가 있다. posts 를 작성하는 폼을 작성하고, 이미 있는 Tags 의 목록과 연관시켜 본다.

 

실제로는 새로운 태그를 작성하고 그 자리에서 포스트와 연관짓게 하고 싶을지도 모른다. 그러나 이번에는 간단하게 하기위해, 어떻게 연관 짓고 불로내는 지 정도만 나타낸다.

 

Cake 에서 자신의 모델을 저장하고 싶은 경우, (HtmlHelper 를 사용하고 있으며) 태그명은 '모델/필드_이름' 과 같이 된다. 포스트를 작성하는 폼을 우선 만든다:

 

예 6.9. posts 작성을 위한 /app/views/posts/add.thtml 형식

 

<h1>Write a New Post</h1>

<table>   

    <tr>   

        <td>Title:</td> 

        <td><?php echo $html->input('Post/title')?></td>

    </tr>

    <tr>       

        <td>Body:<td>

        <td><?php echo $html->textarea('Post/body')?></td>

    </tr>

    <tr>

        <td colspan="2">

            <?php echo $html->hidden('Post/user_id', array('value'=>$this->controller->Session->read('User.id')))?>

            <?php echo $html->hidden('Post/status' , array('value'=>'0'))?>

            <?php echo $html->submit('Save Post')?>

        </td>

    </tr>

</table>

이 폼은 Post 레코드를 작성할 수 있게 한다. 이번에는 하나 이상의 태그를 Post 에 지속시킬 수 있게 한다 :

 

예 6.10. /app/views/posts/add.thtml (tag 연관 코드를 추가)

 

< ><h1>Write a New Post</h1>
<table>
    <tr>
        <td>Title:</td>
        <td><?php echo $html->input('Post/title')?></td>
    </tr>
    <tr>
        <td>Body:</td>
        <td><?php echo $html->textarea('Post/body')?></td>
    </tr>
    <tr>
        <td>Related Tags:</td>
        <td><?php echo $html->selectTag('Tag/Tag', $tags, null, array('multiple' => 'multiple')) ?>
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <?php echo $html->hidden('Post/user_id', array('value'=>$this->controller->Session->read('User.id')))?>
            <?php echo $html->hidden('Post/status' , array('value'=>'0'))?>
            <?php echo $html->submit('Save Post')?>
        </td>
    </tr>
</table> #

애플리케이션을 구축할 때 이따금 예외적인 상황을 위해 모델의 관련을 변경하고 싶을 수 있다. 모델 파일의 관련 설정이 너무 많은 (또는 충분하지 않은) 정보를 주고 있다면, 다음의 find 작업전, 묶기 (bind) 와 풀기 (unbind) 이 두개의 모델 함수를 이용할 수 있다.

 

어떻게 bindModel() 과 unbindModel() 이 작동하는지 보기 위해 몇개의 모델을 설정해보자. 다음과 같이 두개의 모델로 시작할 것이다 :

 

6.14. leader.php 와 follower.php

 

< ><?php
class Leader extends AppModel
{
    var $name = 'Leader';
    var $hasMany = array(
        'Follower' => array(
            'className' => 'Follower',
            'order'     => 'Follower.rank'
        )
    );
}
?>
<?php
class Follower extends AppModel
{
    var $name = 'Follower';
}
?> function someAction()
{
    //Leaders 와, 관련된 Followers 를 불러온다.     $this->Leader->findAll();

    //hasMany 관련을 없애보자...
    $this->Leader->unbindModel(array('hasMany' => array('Follower')));
   
    //자 find 함수를 이용하면 Follower 없이 Leader 를 불러올 것이다.     $this->Leader->findAll();

    //주의 : unbindModel 은 오직 바로 다음의 find 함수에만 유효하다.
    //추가적인 find 함수 호출은 설정된 관련 정보를 이용하게된다.

    //이미 unbindModel() 후에 findAll() 을 사용하였기 때문에,     //Leaders 와, 관련된 Followers 를 다시 불러온다...
    $this->Leader->findAll();
} $this->Model->unbindModel(array('associationType' => array('associatedModelClassName'))); funciton anotherAction()
{
    //leader.php 모델 파일에는 Leader 에 Principle 이 hasMany 되어 있지 않다.
    //find 하면 Leader 만을 불러온다.
    $this->Leader->findAll();

    //bindModel() 를 사용하여 Principle 에 새로운 관련을 추가하자 :
    $this->Leader->bindModel(
        array('hasMany' => array(
                'Principle' => array(
                    'className' => 'Principle'
                )
            )
        )
    );

    //자 이제 정확하게 관련지어 졌다.     //하나의 find 함수를 사용하여 Principle 과 관련지어진 Leader 를 불러 올 수 있다:
    $this->Leader->findAll();
} $this->Model->bindModel(
        array('associationName' => array(
                'associatedModelClassName' => array(
                    // 일반적인 관련 키값은 여기에...
                )
            )
        )
    );  

 

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
69 [함수] SQLite 와 php 의 연동 졸리운_곰 2017.04.26 58
68 2.워드프레스 소스코드 분석(wp-header.php) 졸리운_곰 2017.04.23 120
67 1.워드프레스 소스 분석(index.php) 졸리운_곰 2017.04.23 263
66 WAMP 설치파일 bitnami bitnami-wampstack-5.6.30-2-windows- file 졸리운_곰 2017.04.15 79
65 rbjn.kr 로봇저널리즘 소스코드 자료 file 졸리운_곰 2017.03.14 61
64 워드프레스 데이터베이스 들여다보기. file 졸리운_곰 2017.02.27 55
63 워드프레스 페이지 분석 file 졸리운_곰 2017.02.27 144
62 워드프레스 템플릿 계층 구조 쉽게 이해하기!(What is Template Hierarchy!?) file 졸리운_곰 2017.02.27 245
61 워드프레스 테마 구조 file 졸리운_곰 2017.02.27 57
60 기본적으로 알아야할 워드프레스 파일 구조 및 디렉터리 구조 file 졸리운_곰 2017.02.27 60
59 워드프레스 웹페이지 구조와 구성요소인 템플릿 파일 이해하기. file 졸리운_곰 2017.02.27 148
58 워드프레스의 기본 구조에 대해 알아보자 file 졸리운_곰 2017.02.27 35
57 워드프레스 DB 쿼리 사용법 총정리 졸리운_곰 2017.02.25 63
56 wordpress Database Description file 졸리운_곰 2017.02.25 49
55 Tour of the WordPress Database file 졸리운_곰 2017.02.25 48
54 Beginner’s Guide to WordPress Database Management with phpMyAdmin file 졸리운_곰 2017.02.25 330
53 Wordpress DB table 파헤치기 file 졸리운_곰 2017.02.09 46
52 워드프레스 영문판 설치 후 한글화 하려면? 졸리운_곰 2017.02.08 33
51 fuelphp 도입부터 scaffolding 사용까지 졸리운_곰 2017.02.06 98
» cake php 사용법 file 졸리운_곰 2017.01.15 2436
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED