본문 바로가기

프로그래밍/Framewrok

symfony(심포니)

출처 : http://sunhwan.tistory.com/7

PHP 웹 프레임워크인 Symfony1 를 이용하여 AJAX 기반의 어플리케이션을 만들어보겠습니다. 그 중에서도 특히 Script.aculo.us2 의 draggable_element 와 droppable_element 를 활용하여 Post-It 스타일의 메모장을 만들어볼 계획입니다.

1. 먼저 symfony 명령을 활용하여 프로젝트를 준비합니다. 프로젝트명은 note, 어플리케이션 이름도 note 로 하겠습니다.
# mkdir note
# cd note
# symfony init-project note
# symfony init-app note

2. 아파치 설정을 변경하시거나 해당 디렉토리를 웹이 접근가능한 폴더로 변경합니다. 그리고 테스트를 하시면 'Symfony Project Created' 페이지를 만나실 수 있습니다. 참고로 제 웹 설정을 올려보겠습니다.
# /etc/httpd/users/sunhwan.conf
<Directory "/usr/local/lib/php/data/symfony/web/sf">
    AllowOverride All
    Allow from all
</Directory>

<VirtualHost *:80>
    ServerName note
    DocumentRoot "/Users/sunhwan/working/note/web"
    DirectoryIndex index.php
    Alias /sf /usr/local/lib/php/data/symfony/web/sf

    <Directory "/Users/sunhwan/working/note/web">
        AllowOverride All
        Allow from all
    </Directory>
</VirtualHost>
사용자 삽입 이미지

좀 더 상세한 프로젝트 생성방법은 심포니 홈페이지3 을 참고하시면 됩니다.

3. 이제 우리가 사용할 어플리케이션이 사용할 데이터베이스를 설정합니다. 지금 우리가 만들 어플리케이션은 규모도 크지 않고 다른 어플리케이션들과의 연동도 별로 없기때문에 XML 이나 다른 파일 형태로 저장하는 것도 나쁘지 않을 것 같았지만, 사실 Symfony 에서 이를 어떻게 구현할지 익숙하지 않아서 일단 데이터베이스를 사용하기로 했습니다.

note/config 디렉토리에 있는 database.yml, propel.ini, schema.yml 파일을 수정합니다.
# database.yml
all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://root:@localhost/Note

# propel.ini
propel.database.url        = mysql://root@localhost/note

# schema.yml
propel:
  note:
    _attributes: { phpName: Note }
    id:
    title:    varchar(255)
    contents: longvarchar
    x:        smallint
    y:        smallint
    z:        tinyint
    width:    smallint
    height:   smallint
사실 이러면 안 되지만, 저는 방화벽이 설치된 로컬에서 MySQL 을 돌리는 관계로, root 비밀번호가 없습니다. database.yml 이나 propel.ini 파일의 아이디 뒷부분에 자신에 해당하는 비밀번호를 입력하면 됩니다.

4. 이제 데이터베이스를 생성합니다. Symfony 는 schema.yml 에 입력된 정보를 바탕으로 데이터베이스 구조를 생성할 수 있습니다.
symfony propel-build-model
symfony propel-build-sql
mysqladmin -u root create database note
symfony propel-insert-sql
데이터베이스에 접속해보시면 note 테이블이 생성된 것을 확인하실 수 있습니다. 또한 데이터베이스 자료와 PHP 자료형을 연결시켜주는 역할을 하는 모델들이 note/lib/model 디렉토리에 생긴것을 확인하실 수 있습니다.

5. 이제 생성된 모델을 이용해서 기본적인 데이터 입력, 호출, 수정, 그리고 삭제 (CRUD - Create, read, update, and delete) 를 하는 모듈을 만들어 보겠습니다. 모델명은.. 역시 note 입니다.
symfony propel-generate-crud note note Note
참고로 앞에서부터 어플리케이션, 모듈, 그리고 데이터모델 순서입니다. 즉, 만약 blog 라는 어플리케이션을 만들고, 그 아래 Article 이라는 데이터모델을 이용하여 post 라는 모듈을 만든다면 'symfony propel-generate-crud blog post Article' 이 되는 것입니다.
 
사용자 삽입 이미지

CRUD - List


사용자 삽입 이미지

CRUD - Show


사용자 삽입 이미지

CRUD - Create/Edit


6. 이제 템플릿을 수정할 차례입니다. 다른 부분이야 그대로 두고, note/list 액션의 템플릿을 바꿔서 노트형식으로 보이도록 할 계획입니다. 또한 이부분 draggable/dropperable element 들을 설정하여 만약 개별 노트의 위치가 변경되는 경우에 데이터베이스를 변경하도록 할 것입니다.

먼저 note/apps/note/modules/note/templates/listSuccess.php 파일을 수정합니다.
<div id='notepad' class='notepad' style='position: absolute; top: 5px; left: 5px;'>

<h1>note</h1>

<?php foreach ($notes as $note): ?>

  <div id='note_<?php echo $note->getId() ?>' class='note' style="
    position: absolute;
    left: <?php echo $note->getX() ?>px;
    top: <?php echo $note->getY() ?>px; ">
    <h2><?php echo link_to($note->getTitle(), 'note/show?id='.$note->getId()) ?></h2>
   
    <?php echo $note->getContents() ?>
  </div>
 
<?php endforeach; ?>

<?php echo link_to ('create', 'note/create') ?>

</div>
note/web/main.css 에 아래 내용을 추가합니다.
.note
{
  background-color: #FFFFCC;
  width: 200px;
  height: 200px;
}
그리고 테스트를 해보신다면 아래와 같은 화면을 보실 수 있습니다. 각각의 노트는 데이터베이스에 있는 X, Y 값을 사용하여 위치가 결정될 것입니다.
사용자 삽입 이미지

Post It!?


7. 이제 마지막으로 AJAX 액션을 추가할 차례입니다. Symfony 에는 Prototype 과 Script.aclo.us 가 기본적으로 내장되어 있기 때문에 따로 설치할 필요는 없습니다. 개체를 드래그 앤 드랍이 가능하도록 만들어주는 명령은 draggable_element 입니다. 또한 어떠한 개체가 자신의 위에 드랍되었을때 특정한 액션을 일으킬 수 있도록 하기 위해서 drop_receiving_element 를 사용합니다.

apps/note/modules/note/templates/listSuccess.php 를 여시고, 다음 내용을 맨 위쪽에 입력합니다.
<?php echo use_helper('Javascript') ?>
아래 내용은 'endforeach' 위에 입력합니다.
<?php echo draggable_element('note_'.$note->getId(), array()) ?>
그리고 아래내용은 파일의 제일 아래쪽에 입력합니다.
<?php echo drop_receiving_element('notepad', array(
  'url' => 'note/translate',
  'with' => "'id='+encodeURIComponent(element.id)+'&x='+element.style.left+'&y='+element.style.top")
) ?>
파일 전체를 다시 살펴보시려면 클릭하십시오.

more..


7. 마지막으로 apps/note/modules/actions/action.class.php 에 'executeTranslate' 을 추가하면 끝입니다.
  public function executeTranslate ()
  {
    $tmp = split('_', $this->getRequestParameter('id', ''));
    $note_id = $tmp[1];
   
    $note = NotePeer::retrieveByPk($note_id);
    $this->forward404Unless($note);

    $note->setId($note_id);
    $note->setX($this->getRequestParameter('x', 0));
    $note->setY($this->getRequestParameter('y', 0));
    $note->setZ($this->getRequestParameter('z', 0));

    $note->save();

    return true;
  }


  1. http://www.symfony-project.com [본문으로]
  2. http://script.aculo.us [본문으로]
  3. http://www.symfony-project.com/book/trunk/project_creation [본문으로]