Development

Documentation/pl_PL/my_first_project/trunk

You must first sign up to be able to contribute.

Version 5 (modified by Bart, 9 years ago)
Poprawione kalki językowe / A bit of loan translation corrected

Tekst oryginału: http://www.symfony-project.com/tutorial/my_first_project.html

Mój pierwszy projekt Symfony

Ten tutorial wprowadzi Cię w świat Symfony - wspólnie, w godzinę zbudujemy blog. Jedyne wymagania to zainstalowany serwer Apache i PHP w wersji 5.

Instalacja Symfony i inicjacja projektu

Aby szybko rozpocząć, użyjemy Symfony Sandbox, czyli w pełni już skonfigurowanej wersji Symfony, do której wszystkie potrzebne biblioteki zostały już dołączone.

Sandbox pobieramy stąd: sf_sandbox.tgz i rozpakowywujemy go do katalogu głównego (root/www).

Przeczytaj plik ReadMe? jeśli chcesz uzyskać więcej informacji.

W rezultacie uzyskasz strukturę plików która wygląda tak:

www/
  sf_sandbox/
    apps/
      frontend/
    batch/
    cache/
    config/
    data/
      sql/
    doc/
      api/
    lib/
      model/
    log/
    test/
    web/
      css/
      images/
      js/
      uploads/

Pokazuje to sf_sandbox. projekt wraz z frontendem. Przetestuj Symfony przez wywołanie następującego URL-a:

http://localhost/sf_sandbox/web/index.php/

Powinieneś zobaczyć stronę z gratulacjami:

http://www.symfony-project.com/images/tutorials/first_congrats.gif

Jezeli jej nie widzisz, sprawdź plik php.ini, opcja magic_quotes_gpc musi być wyłączona.

Więcej pomocy uzyskasz na forum Symfony.

Możesz także zainstalować Symfony w dowolnym folderze i ustawić Virtual Host bądź Alias, więcej informacji o tym znajdziesz w dokumentacji Symfony: instalacja, tworzenie projektu oraz struktura plików.

Inicjalizacja modelu danych

Blog będzie przechowywał posty, które użytkownicy będą mogli komentować. Zmodyfikuj plik sf_sandbox/config/schema.yml i wstaw następującą konfigurację:

propel:
  weblog_post:
    _attributes: { phpName: Post }
    id:
    title:       varchar(255)
    excerpt:     longvarchar
    body:        longvarchar
    created_at:
  weblog_comment:
    _attributes: { phpName: Comment }
    id:
    post_id:
    author:      varchar(255)
    email:       varchar(255)
    body:        longvarchar
    created_at:

Ten kod w YAML opisuje dwie tabele: Post i Comment. Zapisz go i otwórz linię poleceń, wejdź do katalogu sf_sandbox/ i wykonaj polecenie: YAML jest nie trudne i podobne do XML i zrobione ze by bycz naj czytlny dla czlowieka.

$ php symfony.php propel-build-model

Jeżeli używasz Linuksa możesz użyć komend ./symfony (albo ./symfony.sh) zamiast php symfony.php

Generator wygeneruje klasy znajdujące się w katalogu sf_sandbox/lib/model/. Są to klasy object-relational mapping (mapowanie relacyjno-obiektowe), które pozwalają na dostęp do relacyjnej bazy danych przy użyciu obiektów, a bez pisania nawet jednej linii kodu SQL. Symfony używa do tego biblioteki Propel. Będziemy nazywali te obiekty modelami (więcej informacji znajdziesz w dokumentacji Symfony: modele )

Teraz wykonaj w linii komend następujące polecenie:

$ php symfony.php propel-build-sql

Symfony stworzy plik schema.sql w katalogu sf_sandbox/data/sql/. Ten plik może służyć do inicjacji bazy danych strukturą tabel, możesz teraz stworzyć bazę danych w MySQL. Symfony Sandbox jest standardowo skonfigurowane, aby pracować z bazą SQLite, więc nie musisz teraz nic tworzyć. Symfony użyje bazy danych sandbox.db znajdującej się w katalogu sf_sandbox/data/. Aby zbudować strukturę bazy dla naszej aplikacji, bazującą na naszym schema.sql wystarczy wydać polecenie:

$ php symfony.php propel-insert-sql

Nie przejmuj się, jeżeli zobaczysz jakieś ostrzeżenia. Polecenie insert-sql usuwa najpierw stare tabele, zanim doda nowe, a w tej chwili nie ma jeszcze w bazie nic.

Tworzenie szkieletu aplikacji (application scaffolding)

Na początku dla naszych tabel Post i Comment potrzebujemy prostych operacji: dodaj, edytuj, uaktualnij i usuń (Create, Retrieve, Update and Delete (CRUD)). Nie musisz tworzyć tego kodu ręcznie - Symfony wykona to za ciebie. Framework potrafi interpretować model tak, aby wygenerować akcję CRUD automatycznie.

Wykonaj dwa polecenia:

$ php symfony.php propel-generate-crud frontend post Post
$ php symfony.php propel-generate-crud frontend comment Comment

Upewnij się, że jesteś w głównym katalogu twojego projektu (sf_sandbox/), kiedy wywołujesz Symfony.

Posiadasz juz dwa moduły twojej aplikacji (Post i Comment), które pozwalają ci na manipulację danymi z tabel Post i Comment w bazie danych (atrybut phpName z pliku schema.xml jest użyty jako nazwy tabel). Moduł zazwyczaj reprezentuję stronę lub grupę stron z podobna tematyką. Twoje nowe moduły znajdują się w katalogu sf_sandbox/apps/frontend/modules/ i można się do nich odwołać w następujący sposób:

http://localhost/sf_sandbox/web/frontend_dev.php/post
http://localhost/sf_sandbox/web/frontend_dev.php/comment

Stwórz kilka postów aby twój blog nie był pusty:

http://www.symfony-project.com/images/tutorials/first_crud.gif

Więcej o budowaniu szkieletów znajdziesz tutaj, a wyjaśnienie struktury projektu Symfony tutaj

W URL-ach powyżej nazwa głównego skryptu nazywanego sterownikiem fasady (ang. front controller) w Symfony została zmieniona z index.php na frontend_dev.php. Te dwa skrypty dają dostęp do tej samej aplikacji, ale w różnych środowiskach. Przez frontend_dev.php masz dostęp do aplikacji w środowisku development environment który posiada użyteczne narzędzia jak debug toolbar w prawym górnym rogu ekranu i silnik konfiguracyjny w czasie rzeczywistym. Dlatego wyświetlenie strony zajmuje dłużej niż poprzez index.php, który z kolei jest sterownikiem fasady w środowisku produkcyjnym (production environment), zoptymalizowanym pod względem szybkości działania. Jeżeli chcesz używać środowiska produkcyjnego zamień frontend_dev.php na index.php w URL-ach powyżej. Ale jednocześnie musisz pamiętać, aby wyczyścić cache zanim obejrzysz zmiany na stronie.

$ php symfony.php clear-cache

http://localhost/sf_sandbox/web/index.php/

Więcej informacji na temat środowisk: znajdziesz tutaj.

Modyfikacja wyglądu aplikacji

Aby nawigować pomiędzy dwoma modułami, blog musi mieć jakąś globalną nawigację (menu).

Zmodyfikuj szablon globalny sf_sandbox/apps/frontend/templates/layout.php i zamień zawartość tagu <body> na

<div id="container" style="width:600px;margin:0 auto;border:1px solid grey;padding:10px">
  <div id="navigation" style="display:inline;float:right">
    <ul>
      <li><?php echo link_to('List of posts', 'post/list') ?></li>
      <li><?php echo link_to('List of comments', 'comment/list') ?></li>
    </ul>
  </div>
  <div id="title">
    <h1><?php echo link_to('My first symfony project', 'default/index') ?></h1>
  </div>
 
  <div id="content" style="clear:right">
    <?php echo $content ?>
  </div>
</div>

Proszę, wybaczcie skromny design, ale jedna godzina to zbyt krótki czas, aby wykombinować coś lepszego ;)

http://www.symfony-project.com/images/tutorials/first_crud_layout.gif

Kiedy jesteś w tym miejscu, możesz zmienić tytuł twojej strony. Edytuj plik konfiguracyjny sf_sandbox/apps/frontend/config/view.yml, zlokalizuj linię z kluczem title i zmień ja na:

default:
  http_metas:
    content-type: text/html; charset=utf-8

  metas:
    title:        The best weblog ever
    robots:       index, follow
    description:  symfony project
    keywords:     symfony, project
    language:     en

Ten plik konfiguracyjny używa składni YAML. Jest to to bardzo prosty język, który ma strukturę drzewiastą (jak XML) i prostą prezentację. Co więcej, jest łatwiejszy i szybszy do czytania i pisania. Jedynie wcięcia mają znaczenie: tabulacje są zabronione, więc pamiętaj by używać spacji do robienia wcięć. Więcej informacji o YAML i konfiguracji Symfony znajdziesz tutaj.

Strona domowa też musi być zmieniona. Używa ona domyślnego szablonu w domyślnym module, który jest przechowywany we frameworku, a nie w katalogu aplikacji. Aby go nadpisać musisz stworzyć swój domyślny moduł.

$ cd apps/frontend/modules
$ mkdir default
$ cd default
$ mkdir templates
$ cd templates

Utwórz tam plik indexSuccess.php i wstaw do niego ładną wiadomość powitalną:

<h1>Welcome to my swell weblog</h1>
<p>You are the <?php echo rand(1000,5000) ?>th visitor today.</p>

Sprawdź rezultat, odświeżając stronę domową:

http://localhost/sf_sandbox/web/frontend_dev.php/

http://www.symfony-project.com/images/tutorials/first_welcome.gif

Blog już działa. Dodaj nowe posty i komentarze do nich.

Więcej informacji o szablonach znajdziesz tutaj, a tutaj poczytasz o konfiguracji widoków.

Przekazywanie danych z akcji do szablonu

Poszło szybko i prosto, prawda? Nadszedł czas na połączenie modułu Comment z modułem Post tak, aby komentarze były wyświetlane pod postem którego dotyczą. Najpierw musisz sprawić, żeby komentarze były dostępne dla szablonu wyświetlającego wpis. W Symfony ten rodzaj logiki jest przechowywany w akcjach. Edytuj plik akcji sf_sandbox/apps/frontend/modules/post/actions/actions.class.php i zmień metodę executeShow() przez dodanie czterech środkowych linii:

public function executeShow ()
{
  $this->post = PostPeer::retrieveByPk($this->getRequestParameter('id'));
 
  $c = new Criteria();
  $c->add(CommentPeer::POST_ID, $this->getRequestParameter('id'));
  $c->addAscendingOrderByColumn(CommentPeer::CREATED_AT);
  $this->comments = CommentPeer::doSelect($c);
 
  $this->forward404Unless($this->post instanceof Post);
}

Obiekty Criteria i Peer są częścią propelowskiego mapowania obiektowo-relacyjnego. Najprościej mówiąc, te cztery linie wykonują zapytanie SQL dla tabeli comment, aby pobrać komentarze powiązane z konkretnym postem (przekazywanym w parametrze URL nazwanym 'id'). Linia $this->comments wewnątrz akcji daję dostęp do zmiennej $comments wewnątrz szablonu. Teraz zmień szablon wyświetlający Post sf_sandbox/apps/frontend/modules/post/templates/showSuccess.php przez dodanie na końcu:

...
<?php use_helper('Text') ?>
<?php use_helper('Date') ?>
 
<hr />
<?php if($comments) : ?>
  <p><?php echo count($comments) ?> comment<?php if(count($comments)>1) : ?>s<?php endif ?> to this post.</p>
  <?php foreach ($comments as $comment): ?>
    <p><em>posted by <?php echo $comment->getAuthor() ?> on <?php echo format_date($comment->getCreatedAt()) ?></em></p>
    <div class="comment" style="margin-bottom:10px;">
      <?php echo simple_format_text($comment->getBody()) ?>
    </div>    
  <?php endforeach ?>
<?php endif ?>

Ta strona używa nowych funkcji (format_date() i simple_format_text()) dostarczanych przez Symfony i nazywanymi 'helperami' (pomocnikami), ponieważ wykonują one dla ciebie niektóre zadania, które normalnie potrzebowały by więcej kodu i czasu. Dodaj nowy komentarz do pierwszego postu, potem znowu spójrz na swój post poprzez kliknięcie na jego numer na liście albo po prostu napisz:

http://localhost/sf_sandbox/web/frontend_dev.php/post/show?id=1

http://www.symfony-project.com/images/tutorials/first_comments_under_post.gif

Zobacz więcej o naming conventions powiązaniu akcji z szablonami, oraz z text i date helpers

Dodawanie rekordów odpowiadających innej tabeli

Kiedy dodajesz komentarz musisz wybrać id odpowiadającego postu. To nie jest zbyt user-firendly. Zmieńmy to i upewnijmy się że użytkownik powróci do posta po jego skomentowaniu.

Najpierw w pliku szablonu modules/post/templates/showSuccess.php dodaj linię na końcu:

<?php echo link_to('Add a comment','comment/create?post_id='.$post->getId()) ?>

Helper link_to() dodaje link do akcji edit w module comment więc możesz teraz dodać komentarz bezpośrednio ze strony wyświetlającej post. Następnie edytuj szablon modules/comment/templates/editSuccess.php i zamień następujące linie:

<tr>
  <th>Post*:</th>
  <td><?php echo object_select_tag($comment, 'getPostId', array (
  'related_class' => 'Post',
)) ?></td>
</tr>

Przez:

<?php if ($sf_request->hasParameter('post_id')): ?>
  <?php echo input_hidden_tag('post_id',$sf_request->getParameter('post_id')) ?> 
<?php else: ?>
  <tr>
    <th>Post*:</th>
    <td><?php echo object_select_tag($comment, 'getPostId', array (
    'related_class' => 'Post',
    )) ?></td>
  </tr>
<?php endif ?>

Formularz na stronie comment/edit wywołuje akcję comment/update która przekierowuje na stronę comment/show (to jest domyślne ustawienie generowanych CRUD). W naszej aplikacji znaczy to że jeżeli dodamy komentarz do postu to zobaczymy ten komentarz. Lepszym rozwiązaniem jest wyświetlenie postu z listą komentarzy pod spodem. Więc edytuj plik modules/comment/actions/actions.class.php i znajdź metodę executeUpdate(). Zobacz że pole created_at nie jest zdefiniowane w akcji, symfony wie że pole nazwane created_at ma być ustawione na datę systemową kiedy tworzony jest rekord. Przekierowanie musi być zmienione aby pokazywało na post a nie na comment (zmień linie redirect):

public function executeUpdate ()
{
  $comment = $this->getCommentOrCreate();
 
  $comment->setId($this->getRequestParameter('id'));
  $comment->setPostId($this->getRequestParameter('post_id'));
  $comment->setAuthor($this->getRequestParameter('author'));
  $comment->setEmail($this->getRequestParameter('email'));
  $comment->setBody($this->getRequestParameter('body'));
 
  $comment->save();
 
  return $this->redirect('post/show?id='.$comment->getPostId());
}

Użytkownicy mogą teraz bezpośrednio dodawać komentarze do postów i wracać do nich po dodaniu komentarza. Chciałeś webloga i masz webloga.

Walidacja formularzy

Użytkownicy mogą dodawać komentarze, ale co jeśli wyślą formularz bez żadnych danych? Będziesz miał pustą bazę danych. Aby temu zapobiec dodaj plik update.yml w katalogu sf_sandbox/apps/frontend/modules/comment/validate/ (musisz też dodać katalog) i napisz w nim:

methods:
  post:           [author, email, body]
  get:            [author, email, body]

names:
  author:
    required:     Yes
    required_msg: The name field cannot be left blank

  email:  
    required:     No
    validators:   emailValidator

  body:
    required:     Yes
    required_msg: The text field cannot be left blank

emailValidator:
  class:          sfEmailValidator
  param:
    email_error:  The email address is not valid.

Pamiętaj jakie zasady są w YAML, tylko spację są akceptowane plik też musi się zaczynać od 'methods'.

Kontroler przekieruje użytkownika do szablonu updateError.php jeżeli błąd zostanie wykryty. Będzie lepiej gdy wyświetlimy formularz ponownie z odpowiednim komunikatem błędu. Aby to zrobić dodaj metodę handleError do klasy modules/comment/actions/actions.class.php:

public function handleError()
{
  $this->forward('comment', 'edit');
}

aby zakończyć otwórz jeszcze raz modules/comment/templates/editSuccess.php i wstaw na początku:

<?php if ($sf_request->hasErrors()): ?>  
  <div id="errors" style="padding:10px;">
    Please correct the following errors and resubmit:
    <ul>
    <?php foreach($sf_request->getErrors() as $error): ?>
      <li><?php echo $error ?></li>
    <?php endforeach ?>
    </ul>
  </div>
<?php endif ?>

Teraz masz silny formularz:

http://www.symfony-project.com/images/tutorials/first_form_validation.gif

Czytaj więcej o form validation

Zmiana sposobu wyświetlania URL-i

Zauważyłeś jak są wyświetlane URLe. Możesz je zrobić trochę bardziej user i search-engine frendly. Użyjmy tytułu postu jako URLa do niego.

Problemem jest to że tytuł może mieć znaki specjalne jak spację. Jeżeli po prostu opuścisz je URL może pokazywać brzydki znaki jak %20, lepiej będzie jeżeli rozszerzymy model o nowe metody pobierające czyste tytuły postów. Aby to zrobić edytuj plik Post.php w katalogu sf_sandbox/lib/model/ i dodaj takie metody:

public function getStrippedTitle()
{
  $result = strtolower($this->getTitle());
 
  // strip all non word chars
  $result = preg_replace('/\W/', ' ', $result);
 
  // replace all white space sections with a dash
  $result = preg_replace('/\ +/', '-', $result);
 
  // trim dashes
  $result = preg_replace('/\-$/', '', $result);
  $result = preg_replace('/^\-/', '', $result);
 
  return $result;
}

Teraz możesz dodać akcję permalink do modułu post:

public function executePermalink()
{
  $posts = PostPeer::doSelect(new Criteria());
  $title = $this->getRequestParameter('title');
  foreach ($posts as $post)
  {
    if ($post->getStrippedTitle() == $title)
    {
      break;
    }
  }
  $this->forward404Unless($post);
 
  $this->getRequest()->setParameter('id', $post->getId());
 
  $this->forward('post', 'show');
}

W pliku modules/post/templates/listSuccess.php usuń komórkę id z tabeli i zmień komórke title z :

<td><?php echo $post->getTitle() ?></td>

na:

<td><?php echo link_to($post->getTitle(), '/'.$sf_last_module.'/permalink?title='.$post->getStrippedTitle()) ?></td>

Jeszcze jeden krok edytuj plik routing.yml w katalogu sf_sandbox/apps/frontend/config/ i dodaj te reguły na górze:

list_of_posts:
  url:   /latest_posts
  param: { module: post, action: list }

post:
  url:   /weblog/:title
  param: { module: post, action: permalink }

Teraz zobacz jeszcze raz swoją aplikację i sprawdź URLe:

http://www.symfony-project.com/images/tutorials/first_routing.gif

Czytaj więcej o smart URLs

Porządki w frontend

Więc jeśli to jest weblog to każdy ma prawo do pisania postów. To nie jest to o co nam chodziło do końca. Wyczyśćmy nasze szablony troszeczkę. W szablonie modules/post/templates/showSuccess.php usuń link do akcji edit:

<?php echo link_to('edit', 'post/edit?id='.$post->getId()) ?>

To samo zrób w szablonie modules/post/templates/listSuccess.php :

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

Jeszcze usuń następujące metody w klasie modules/post/actions/actions.class.php:

* executeEdit
* executeUpdate
* executeDelete
* getPostOrCreate

Ok. czytający nie będą teraz mogli dodawać postów nigdy więcej.

Generowanie Bekend-u

Abyś mógł dodawać posty wygenerujmy dla ciebie aplikację beckend. Przez linie komend wykonaj polecenia (pamiętaj abyś był w katalogu sf_sandbox):

$ php symfony.php init-app backend
$ php symfony.php propel-init-admin backend post Post
$ php symfony.php propel-init-admin backend comment Comment

Tym razem użyjemy admin-generator oferuję on dużo więcej możliwości niż prosy CRUD generator.

Tak jak to robiłeś dla frontend edytuj plik apps/backend/template/layout.php aby ustawić globalna nawigację.

<div id="navigation">
  <ul style="list-style:none;">
    <li><?php echo link_to('Manage posts', 'post/list') ?></li>
    <li><?php echo link_to('Manage comments', 'comment/list') ?></li>
  </ul>
</div>      
<div id="content">
  <?php echo $content ?>
</div>

Ponieważ używasz sf_sandbox musisz skopiować jeszcze katalog sf_sandbox/web/sf/images/sf_admin/ do sf/images/sf_admin/ w katalogu główny serwera www, tak są ustawione ścieżki do ikonek i plików css.

Możesz teraz zobaczyć twoją aplikacje administracyjną przez adres:

http://localhost/sf_sandbox/web/backend_dev.php/post

http://www.symfony-project.com/images/tutorials/first_basic_admin.gif

Możesz w prosty sposób zarządzać twoim modułem administracyjnym z poziomu jednego pliku. Edytuj plik backend/modules/post/config/generator.yml i wstaw tam :

generator: 
  class: sfPropelAdminGenerator
  param:
    model_class:      Post
    theme:            default
    fields:
      title:          { name: Title }
      excerpt:        { name: Exerpt }
      body:           { name: Body }
      nb_comments:    { name: Comments }
      created_at:     { name: Creation date }
    list:
      title:          Post list
      layout:         tabular
      display:        [=title, excerpt, nb_comments, created_at]
      object_actions:
        _edit:        -
        _delete:      -
      max_per_page:   5
      filters:        [title, created_at]
    edit:  
      title:          Post detail        
      fields:
        title:          { type: input_tag, params: size=53 }
        excerpt:        { type: textarea_tag, params: size=50x2 }
        body:           { type: textarea_tag, params: size=50x10 }
        created_at:     { type: input_date_tag, params: rich=on }

Pomiędzy kolumnami tabeli Post admin generator szuka nb_comments. Nie jest to nigdzie jeszcze napisane. Ale łatwo jest dodać tą funkcjonalność. Po prostu dodaj do sf_sandbox/lib/model/Post.php:

public function getNbComments()
{
  return count($this->getComments()); 
}

Teraz odśwież administrację postami i zobacz zmiany:

http://www.symfony-project.com/images/tutorials/first_custom_admin.gif

Blokada dostępu do Beckendu

Beckend może być odwiedzany przez wszystkich. Dodaj logowanie do zablokowania nieupoważnionym dostępu.

W katalogu apps/backend/modules/post/config/ dodaj plik security.yml z następującym kodem:

all:
  is_secure: on

Powtórz tą operację dla modułu Comment. Teraz nie możesz się dostać do tych modułów dopóki sie nie zalogujesz. Ale akcja logowania jeszcze nie istnieje więc dodaj teraz nowy moduł security:

$ php symfony.php init-module backend security

Nowy moduł będzie użyty do logowania użytkowników. Edytuj apps/backend/modules/security/templates/indexSuccess.php aby stworzyć formularz logowania:

<h2>Authentication</h2>
 
<?php if ($sf_request->hasErrors()): ?>
  Identification failed - please try again
<?php endif ?>
 
<?php echo form_tag('security/login') ?>
  <label for="login">login:</label>
  <?php echo input_tag('login', $sf_params->get('login')) ?>
 
  <label for="password">password:</label>
  <?php echo input_password_tag('password') ?>
 
  <?php echo submit_tag('submit', 'class=default') ?>
</form>

Dodaj akcję login którą wywołuje formularz w klasie apps/backend/modules/security/actions/actions.class.php

public function executeLogin()
{
  if ($this->getRequestParameter('login') == 'admin' && $this->getRequestParameter('password') == 'password')
  {
    $this->getUser()->setAuthenticated(true);
    return $this->redirect('default/index');
  }
  else
  {
    $this->getRequest()->setError('login', 'incorrect entry');
    return $this->forward('security', 'index');
  }
}

Ostatnia rzeczą do zrobienia jest ustawienie modułu security jako domyślnego modułu do przechwytywania akcji logowania. Aby to zrobić otwórz apps/backend/config/settings.yml i dodaj:

all:
  .actions:
    login_module:           security
    login_action:           index

Od tego czasu będziesz proszony o podanie loginu i hasła

http://www.symfony-project.com/images/tutorials/first_login.gif

Czytaj więcej o security

Podsumowanie

Ok godzina minęła. Udało ci się. teraz możesz używać obu aplikacji w środowisku produkcyjnym:

frontend:   http://localhost/sf_sandbox/web/index.php/
backend:    http://localhost/sf_sandbox/web/backend.php/

Jeżeli zobaczysz błędy w tym momencie musisz wyczyścić cache, nie jest on używany w środowisku development. Poprostu wywołaj z linii komend:

$ php symfony.php cc

Jak widać, aplikacja działa szybko i sprawnie. Teraz możesz śmiało przeglądać kod, dodawać nowe moduły i modyfikować wygląd stron.

Pochwal się też swoją aplikacją na symfony Wiki!