Development

Documentation/ko_KR/summary/The_Definitive_Guide_to_symfony

You must first sign up to be able to contribute.

Version 12 (modified by withrain, 9 years ago)
--

The Definitive Guide to symfony 서머리

이 문서는 "The Definitive Guide to symfony" 의 내용 중 일부를 서머리하여 정리한 것이다.

심포니는 PHP5 를 이용한 웹 어플리케이션 프레임워크이다. 심포니는 PHP5 클래스로 이루어져 있어 전반적으로 OOP 방식을 사용한다. 데이터베이스 레이어는 Propel 같은 서드파티 라이브러리를 활용함으로써 ORM 기능을 프레임워크 내부에서 지원하도록 하였다. rails-like 한 프레임워크로서 conventoion-over-configuration 모토를 따르고 있어 심포니로 구축된 어플리케이션은 다른 사람이 보더라도 쉽게 이해하고 공유할 수 있다.

MVC 프레임워크

전통적인 php 코드는 하나의 php 파일에서 데이터베이스 커넥션을 맺어 데이터를 가져와서 일정한 로직을 수행한 후에 화면에 뿌려질 html을 생성하는 방식이었다. 웹개발 전반에 Model-View-Controller 방식이 도입되면서 고전적인 구조를 탈피하는데 프레임워크가 MVC 기능을 지원하도록 구성되는 경우가 많다. MVC 방식은 크게 데이터베이스, HTML, 비즈니스로직을 나누어 코딩하고 이 세 파트를 프레임워크에서 조립해 주는 형태를 띄는 것이 보통이다. 심포니에서는 Propel 등이 Model을 담당하고있고 템플릿,레이아웃 등의 View, 콘트롤러와 액션이 비즈니스로직을 담당하고 있다.

프레임워크 구조

심포니 프레임워크의 구조는 크게 프로젝트 > 어플리케이션 > 모듈 > 액션 으로 구성된다. 하나의 프로젝트는 여러개의 어플리케이션을 가질 수 있으며 그 하위도 마찬가지 구조를 가진다. 따라서 하나의 프로젝트는 심포니 프레임워크의 최상위 디렉토리를 구성하게 된다. 아래는 심포니 프로젝트의 디렉토리 구조이다.

apps/
  frontend/
  backend/
cache/
config/
data/
  sql/
doc/
lib/
  model/
log/
plugins/
test/
  bootstrap/
  unit/
  functional/
web/
  css/
  images/
  js/
  uploads/

apps : 프로젝트의 어플리케이션, 모듈, 액션 코드가 위치한다.
cache : 환경설정 파일, 액션 코드, 템플리 코드등을 캐시하여 놓는 위치이다.
config : 프로젝트 전반에 걸친 환경설정 파일이 위치한다.
data : 데이터베이스 스키마, 테이블 생성 sql 파일 등이 위치한다.
doc : 프로젝트의 문서가 위치하는 곳이다.
lib : 외부 클래스나 라이브러리를 놓는다. 이곳은 모든 어플리케이션이 공유하는 곳이며 model 서브 디렉토리에는 데이터베이스 모델이 위치한다.
log : 심포니에서 생성된 로그파일이 존재한다.
plugins : 서드파티 플러그인이 설치되는 곳이다.
test : functional test 와 unit test 코드가 있다.
web : 웹 루트 디렉토리이다. php 코드 이외의 다른 파일들이 위치하는 곳이다.

프로젝트 생성

PEAR 로 심포니를 설치했다면 아래 명령으로 프로젝트를 생성한다.

> mkdir ~/myproject
> cd ~/myproject
> symfony generate:project myproject

어플리케이션을 생성한다.

php symfony generate:app frontend

이 명령은 app 디렉토리 밑에 frontend 서브 디렉토리를 생성한고 필요한 파일들을 생성한다. 또한 web 디렉토리 밑에 아래와 같은 파일을 생성한다.

apps/
  frontend/
    config/
    i18n/
    lib/
    modules/
    templates/
...
web/
  index.php
  frontend_dev.php

index.php 는 프로덕션 컨트롤러 이다. 첫 어플리케이션이기 때문에 index.php 란 이름이 붙었으며 만약 기존에 index.php 란 컨트롤러가 있었다면 frontend.php 라고 파일이 생성된다. 개발환경에서는 심포니 프레임워크에서 생성되는 다양한 정보를 확인할 수 있는데 이때 사용하는 컨트롤러가 frontend_dev.php 이다. 콘트롤러가 동작하기 위해서는 웹서버의 도큐먼트 경로를 심포니의 web 디렉토리로 변경한다.

모듈 생성

심포니는 액션의 그룹으로 모듈을 생성해야 한다. 즉 하나의 액션을 가진 어플리케이션이더라도 모듈을 먼저 생성해야 하는 것이다. 모듈을 생성하면 자동으로 기본 액션, 템플릿 스켈톤 코드를 생성해 준다.

> php symfony generate:module frontend content

>> dir+      ~/myproject/apps/frontend/modules/content/actions
>> file+     ~/myproject/apps/frontend/modules/content/actions/actions.class.php
>> dir+      ~/myproject/apps/frontend/modules/content/templates
>> file+     ~/myproject/apps/frontend/modules/content/templates/indexSuccess.php
>> file+     ~/myproject/test/functional/frontend/contentActionsTest.php
>> tokens    ~/myproject/test/functional/frontend/contentActionsTest.php
>> tokens    ~/myproject/apps/frontend/modules/content/actions/actions.class.php
>> tokens    ~/myproject/apps/frontend/modules/content/templates/indexSuccess.php

actions.class.php 파일을 열어 보자

<?php
 
class contentActions extends sfActions
{
  public function executeIndex()
  {
    $this->forward('default', 'module');
  }
}

sfActions 클래스를 상속받는 contentActions(모듈 이름을 따른다) 클래스에 만들고자 하는 액션 함수를 추가해 주면 된다. 액션은 관례에 따라 executeAaaaa 로 적는다. $this->forward('default', 'module'); 은 모듈 초기 페이지로 포워딩한다는 의미이다. 웹 브라우저로

http://localhost/frontend_dev.php/content/index

에 접속해 보자

http://www.symfony-project.org/images/book/1_1/F0401.jpg

액션 추가

Hello World 페이지를 작성해 보자. 먼저 위에서 만든 액션 클래스에 Show 액션을 추가하고

<?php
 
class contentActions extends sfActions
{
  public function executeShow()
  {
  }
}

content/templates/showSuccess.php 템플릿을 만든다. 템플릿 파일 이름도 관례를 따라 ttttSuccess.php 로 짓는다.

<p>Hello, world!</p>

템플릿에 변수 전달

액션에서 비즈니스 로직을 수행한 결과를 템플릿으로 넘기기 위해서는 액션 클래스의 속성을 생성해 주면 된다. 즉 액션 클래스 내에서 $this->someVariable 에 값을 할당하면 템플릿에서 $someVariable 로 값을 참조할 수 있다. 예제를 확인해 보자.

액션코드

<?php
 
class contentActions extends sfActions
{
  public function executeShow()
  {
    $today = getdate();
    $this->hour = $today['hours'];
  }
}

템플릿코드

<p>Hello, world!</p>
<?php if ($hour >= 18): ?>
  <p>Or should I say good evening? It is already <?php echo $hour ?>.</p>
<?php endif; ?>

다른 액션으로 링크 걸기

템플릿에서 다른 액션으로 링크를 걸기 위해서는 아래와 같이 앵커태그를 이용해서 할수 있지만

<a href="/frontend_dev.php/content/update?name=anonymous">
  I never say my name
</a>

심포니에서 제공하는 헬퍼 메소드(헬퍼메소드는 클래스가 아니다)를 이용하면 좀더 편리하다. 개발환경과 상용환경의 변화에 상관없이 링크를 생성해 주기 때문이다.

<?php echo link_to('I never say my name','content/update?name=anonymous') ?>

쿼리스트링 파싱

심포니는 쿼리스트링 파싱을 자동으로 처리해서 sfWebRequest 클래스 객체를 액션 클래스에 파라메타로 전달해 준다.

<?php
 
class contentActions extends sfActions
{
  // ...
 
  public function executeUpdate($request)
  {
    $this->name = $request->getParameter('name');
  }
}

템플릿에서 쿼리스트링을 사용하고 싶을 경우에는 $sf_params 를 사용한다.

<p>Hello, <?php echo $sf_params->get('name') ?>!</p>

콘트롤러

콘트롤러는 웹 요청을 받아 처리를 담당할 액션을 호출하는 역할을 한다. 다른 프레임워크에서는 콘트롤러를 디스패처라고 부르기도 한다. 사실 콘트롤러는 액션에서 처리를 위임하기 전에 필요한 자질구레한 일들을 담당해 주는 것이다.

심포니 URL 은 콘트롤러/모듈/액션 으로 구성된다.

http://localhost/index.php/mymodule/index

위에서 잠깐 보았듯이 액션에는 sfWebRequest 객체가 파라메타로 전달되는데 이 클래스의 대표적인 메소드는 아래와 같다.

NameFunctionSample Output
Request Information
isMethod($method)Is it a post or a get?true or false
getMethod()Request methodReturns sfRequest::GET or sfRequest::POST constants
getMethodName()Request method name'POST'
getHttpHeader('Server')Value of a given HTTP header'Apache/2.0.59 (Unix) DAV/2 PHP/5.1.6'
getCookie('foo')Value of a named cookie'bar'
isXmlHttpRequest()*Is it an Ajax request?true
isSecure()Is it an SSL request?true
Request Parameters
hasParameter('foo')Is a parameter present in the request?true
getParameter('foo')Value of a named parameter'bar'
getParameterHolder()->getAll()Array of all request parameters
URI-Related Information
getUri()Full URI'http://localhost/frontend_dev.php/mymodule/myaction'
getPathInfo()Path info'/mymodule/myaction'
getReferer()**Referrer'http://localhost/frontend_dev.php/'
getHost()Host name'localhost'
getScriptName()Front controller path and name'frontend_dev.php'
Client Browser Information
getLanguages()Array of accepted languagesArray( [0] => fr [1] => fr_FR [2] => en_US [3] => en )
getCharsets()Array of accepted charsetsArray( [0] => ISO-8859-1 [1] => UTF-8 [2] => * )
getAcceptableContentTypes()Array of accepted content typesArray( [0] => text/xml [1] => text/html

헬퍼 메소드

헬퍼 메소드는 클래스가 아니라 PHP 함수이다. 헬퍼 메소드가 템플릿에서 사용되기 때문에 심포니 내장 헬퍼 메소드는 대부분 HTML 코드를 생성해 주는 것이지만 사용자 정의 헬퍼 메소드를 만들수도 있다. 위에서 보았던 link_to 헬퍼 메소드는 실제로 아래와 같은 html 을 리턴해 준다.

<?php echo input_tag('nickname') ?>
 => <input type="text" name="nickname" id="nickname" value="" />

이 헬퍼 메소드는 아래와 같이 구현되어 있다.

function input_tag($name, $value = null)
{
  return '<input type="text" name="'.$name.'" id="'.$name.'"value="'.$value.'" />';
}

헬퍼 메소드는 관련된 것들끼리 그룹핑되어 있다. 자동으로 로딩되는 헬퍼를 제외하고는 use_helper 메소드를 이용하여 명시적으로 로딩을 해주어야 한다. use_helper 또한 헬퍼 메소드이다.

<?php use_helper('Text') ?>
...
<h1>Description</h1>
<p><?php echo auto_link_text($description) ?></p>

여러개의 헬퍼 메소드를 로딩할 때에는 <?php use_helper('Text', 'Javascript') ?> 와 같이 사용할 수도 있다. 자동으로 로딩되는 헬퍼 메소드는 아래와 같다.

  • Helper: 헬퍼 메소드를 로딩하기 위한 헬퍼 (use_helper)
  • Tag: 태그 생성 헬퍼
  • Url: URL 링크 헬퍼
  • Asset: images, JavaScript, and style sheet 태그 헬퍼
  • Partial: 템플릿 관련 헬퍼
  • Cache: 캐시 관련 헬퍼
  • Form: 폼 태그 관련 헬퍼

자주 사용되는 헬퍼의 사용예를 들어 보았다. => 다음에 나오는 내용은 해당 헬퍼 메소드가 생성하는 실제 html 코드를 나타낸다.

// Helper group
<?php use_helper('HelperName') ?>
<?php use_helper('HelperName1', 'HelperName2', 'HelperName3') ?>
 
// Tag group
<?php echo tag('input', array('name' => 'foo', 'type' => 'text')) ?>
<?php echo tag('input', 'name=foo type=text') ?>  // Alternative options syntax
 => <input name="foo" type="text" />
<?php echo content_tag('textarea', 'dummy content', 'name=foo') ?>
 => <textarea name="foo">dummy content</textarea>
 
// Url group
<?php echo link_to('click me', 'mymodule/myaction') ?>
=> <a href="/route/to/myaction">click me</a>  // Depends on the routing settings
 
// Asset group
<?php echo image_tag('myimage', 'alt=foo size=200x100') ?>
 => <img src="/images/myimage.png" alt="foo" width="200" height="100"/>
<?php echo javascript_include_tag('myscript') ?>
 => <script language="JavaScript" type="text/javascript" src="/js/myscript.js"></script>
<?php echo stylesheet_tag('style') ?>
 => <link href="/stylesheets/style.css" media="screen" rel="stylesheet"type="text/css" />

페이지 레이아웃

액션에 대응하는 템플릿에는 <html>, <body> 같은 태그가 빠져있다. 이는 레이아웃이라고 불리우는 별도의 파일에서 불러오기 때문이다. 이 파일에서 전체 사이트에 반복되는 템플릿을 저장하여 놓고 사용할 수 있다. 어플리케이션의 레이아웃은 기본적으로 ./apps/frontend/templates/layout.php 에 위치해 있다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <?php include_http_metas() ?>
    <?php include_metas() ?>
    <?php include_title() ?>
    <link rel="shortcut icon" href="/favicon.ico" />
  </head>
  <body>
    <?php echo $sf_content ?>
  </body>
</html>

재사용 가능한 코드 조각을 파셜(Partials)이라는 단위로 관리할 수 있다. 예를 들면 리스트화면과 디테일 페이지에서 각각 사용되는 메뉴, 헤더, 푸터 등을 따로 저장할 수 있다. 템플릿과 마찬가지로 templates/ 디렉토리에 위치해 있으며 파일명은 항상 밑줄(_)로 시작해야 한다. 파셜 코드를 불러올때는 include_partial('modulename/partialname') 헬퍼 메소드를 사용한다.

// frontend/modules/mymodule/templates/_mypartial1.php
// 템플릿과 파셜이 같은 모듈내에 있을 경우에는 모듈이름을 뺄수 있다.
<?php include_partial('mypartial1') ?>
 
// frontend/modules/foobar/templates/_mypartial2.php
// 템플릿과 다른 모듈에 있는 파셜을 인클루드 할때에는 모듈이름을 포함해야 한다.
<?php include_partial('foobar/mypartial2') ?>
 
// frontend/templates/_mypartial3.php
// global 은 최상위 템플릿 밑의 파셜을 인클루드 한다.
<?php include_partial('global/mypartial3') ?>

심포니 데이터베이스 스키마

사용하고자 하는 데이터베이스가 어떤 것이든 심포니에서 사용할 오브젝트 모델로 바꾸어 주어야만 한다. ORM 툴은 관계형 모델을 매핑하기 위한 정보가 필요하며 이를 스키마라고 한다. 스키마는 테이블과 테이블간의 관계, 컬럼속성등이 포함된다. 심포니는 스키마를 표현하기 위해 YML 신택스를 사용한다. 심포니에서 사용하는 스키마파일 schema.yml 은 최상위 config/ 디렉토리에 위치해야만 한다. 아래는 두개의 테이블이 정의되어 있는 샘플 스키마 파일이다.

propel:
  blog_article:
    _attributes: { phpName: Article }
    id:
    title:       varchar(255)
    content:     longvarchar
    created_at:
  blog_comment:
    _attributes: { phpName: Comment }
    id:
    article_id:
    author:      varchar(255)
    content:     longvarchar
    created_at:

YML 신택스

스키마 파일에서 첫번째 키는 데이터베이스 커넥션 이름이다.(위 예제에서는 propel) 하나의 커넥션은 여러개의 테이블을 가질수 있고 테이블은 여러개의 컬럼을 가질수 있다. 키는 :(콜론)으로 끝나며 구조는 하나 또는 그 이상의 들여쓰기로 이루어 진다(탭이 아니라 공백이어야 한다). 테이블 이름은 camelCase 형식을 따른다. 즉 blog_article 의 실제 테이블명은 BlogArticle? 이 된다. id 필드는 자동으로 PK 로 인식되며 created_at 필드는 자동으로 등록일로 판단하여 레코드가 인서트될때 자동으로 채워지게 된다.

모델 클래스

모델 클래스를 만들기 위해 스키마 파일을 사용한다. 커맨드 라인에서 스키마파일을 가지고 모델 클래스를 자동으로 생성해 준다.

> php symfony propel:build-model

위 명령으로 lib/model/om/ 디렉토리에 아래 파일들이 생성된다.

그리고 lib/model 디렉토리에는 아래 파일들이 생성된다.

lib/model 에 있는 클래스는 lib/model/om 에 있는 클래스를 상속받은 클래스이다. 만약 어떤 클래스에 자신만의 메소드를 추가하고 싶다면 lib/model 클래스에 추가하여야 한다. 심포니의 build-model 명령은 lib/model/om 에 있는 클래스 파일을 덮어 쓰기 때문이다. 하지만 lib/model 에 있는 클래스는 덮어쓰지 않는다. 이 모델 클래스에는 해당 테이블에 데이터를 추가,삭제,수정할 수 있는 모든 메소드들을 포함하고 있으며 테이블의 레코드를 객체로 추출하여 핸들링할 수 있는 메소드를 포함하고 있다.