wtorek, 2 czerwca 2015

[PHP][Symfony2] Instalacja i pierwsze uruchomienie Symfony2 krok po kroku

TRUE
821936260844612134
Framework Symfony to jeden z najpotężniejszych frameworków napisanych dla PHP. Jest to też zarazem jeden z najpopularniejszych frameworków na świecie, warto byłoby zatem znać choćby jego podstawy. Nie jest to jednak framework łatwy w nauce, a na początku jego ogrom może nieco przytłaczać. Wszystko jednak można opanować i w cyklu artykułów tutaj postaramy się nauczyć pracy z Symfony krok po kroku. Będziemy używać wersji z gałęzi 2.x.x, gdyż wprowadza ona niesamowicie dużą ilość ilość zmian w stosunku do swoich starszych wersji, tj. wersji Legacy z gałęzi 1.x.x.

Zasadniczą różnicą powiędzy wersjami 1 i 2 jest wprowadzenie zupełnie innej architektury w tej drugiej, opartej na mechaniźmie tzw. komponentów, o których oczywiście nauczymy się tutaj. Zacznijmy zatem pracę z Symfony2 i na początek pobiermy, zainstalujmy, uruchomijmy i skonfigurujmy swoje pierwsze środowisko oparte na Symfony2. Opiszę procedurę dla systemów z rodziny Windows, zakładając, że mamy zainstalowany i działający serwer Apache. Pierwsze uruchomienie Symfony dla osób nieznających tego frameworka jest nieco problematyczne, więc opiszę wszystko dokładnie krok po kroku.

Przygodę rozpoczynamy od oficjalnej strony frameworka, która znajduje się pod adresem: http://www.symfony.com. Znajdziemy tutaj informacje o najnowszej wersji, przejrzymy bazę komponentów i uzyskamy dostęp do całej dokumentacji, a ta jest naprawdę obszerna. Istnieje również polska wersja dokumentacji, dostępna pod adresem: http://symfony-docs.pl/.

Instalacja Symfony2

Stwórzmy więc sobie katalog na naszą instalację Symfony, np.:
[code]C:/www/symfony[/code]
(będę tutaj używał takiego katalogu dla przykładu, na screenach będzie to u mnie c:/www.wamp/www/symfony)

Wejdźmy teraz do naszego utworzonego katalogu z poziomu konsoli i pobierzmy małą aplikację dla Symfony, która będzie nam służyła do zarządzania projektem, wpiszmy w konsoli:
[code]$ php -r "readfile('http://symfony.com/installer');" > symfony[/code]
W tym miejscu do naszego katalogu powinien pobrać się plik symfony, którego teraz użyjemy do inicjalizacji pierwszego projektu:
[code]$ php symfony new myApp[/code]
Pobierze nam to teraz cały pakiet Symfony2 i zainicjuje nasz projekt o nazwie myApp.


Dla naszej aplikacji został utworzony katalog /myApp, a w nim następująca struktura folderów:



Teraz musimy się na chwilę zatrzymać i omówić sobie strukturę katalogów w symfony.
Po pierwsze - głównym folderem dostępnym przez WWW (document rootem naszej aplikacji) będzie:
[code]/web[/code]
Do naszej aplikacji będziemy więc dostawać się tak:
[code]http://localhost/symfony/myApp/web[/code]
jednakże tutaj pojawia się mała sprawa, gdyż jedynie ten folder powinien być dostępny publicznie, wszelkie pozostałe katalogi powinny być z poziomu WWW niedostępne.
Uczynić to możemy za pomocą ustawienia sobie v-hosta kierującego na katalog /web z naszym projektem. O tym jak utworzyć v-hosta w Apache'u pisałem tutaj. Stwórzmy więc v-hosta o nazwie np.:
[code]symfony.localhost[/code]
i kierującego na:
[code]C:/www/symfony/myApp/web[/code]
tak abyśmy po wpisaniu:
[code]http://symfony.localhost/[/code]
byli kierowani wprost do tego folderu. Oczywiście jeśli tego nie zrobimy, to dostawać się do naszej aplikacji będziemy poprzez:
[code]http://localhost/symfony/myApp/web/[/code]
Polecam jednak sposób z v-hostem, gdyż pozwoli nam to na zrozumienie pewnej koncepcji, która zakłada, iż powinniśmy zawsze wydzielać dostępny publicznie katalog webowy od całej reszty kodu, do której nie powinno być żadnego dostępu z zewnątrz. To jedna sprawa, druga to taka, że metoda z wirtualnym hostem jest zwyczajnie wygodniejsza podczas pracy.

Pierwsze uruchomienie

Symfony mamy już zainstalowane, zobaczmy teraz jak to działa.
Po wpisaniu w przeglądarkę adresu:
[code]http://symfony.localhost[/code]
lub jeśli nie utworzyliśmy vhosta:
[code]http://localhost/symfony/myApp/web/[/code]
który to adres prowadzi tak naprawdę do front-controllera:
[code]c:/www/symfony/myApp/web/app.php[/code]
zostaniemy na starcie przywitani brakiem dostępu.


Dzieje się tak dlatego, gdyż domyślnie pracujemy na środowisku developerskim i dostęp do środowiska produkcyjnego jest zablokowany. Na starcie mamy dostęp jedynie do środowiska developerskiego, do którego wchodzimy poprzez:
[code]http://symfony.localhost/app_dev.php[/code]


Tu wyświetli nam się błąd routingu, ale o tym za chwilę.

Symfony oczywiście pozwala na konfigurację środowiska w jakim obecnie się znajdujemy, dostępne są 3 środowiska:

  • dev - środowisko developerskie
  • prod - środowisko produkcyjne
  • tests - środowisko testowe


Aby móc teraz dostać się do naszego środowiska produkcyjnego, musimy w pliku:
[code]/web/app.php[/code]
zmienić linijkę:
[code]$kernel = new AppKernel('prod', false);[/code]
na
[code]$kernel = new AppKernel('prod', true);[/code]
Od tej chwili mamy dostęp do wersji produkcyjnej pod adresem:
[code]http://symfony.localhost/[/code]
a dokładnie do:
[code]c:/www/symfony/myApp/web/app.php[/code]
do którego to pliku prowadzą wszystkie requesty, co zdefiniowane jest w pliku /web/.htaccess:
[code]RewriteRule .? %{ENV:BASE}/app.php [L][/code]

Spróbujmy teraz wejść w adres:
[code]http://symfony.localhost[/code]
Na starcie zostaniemy przywitani błędem:
[code]No route found for "GET /"[/code]


Wyjątek ten mówi nam o braku definicji dla routingu domyślnego /, czyli dla ścieżki głównej naszej aplikacji.

Kontrolery i akcje

Aby przejść dalej i rozwiązać powyższy problem musimy nauczyć się kilku podstawowych pojęć. Otóż Symfony działa w pełnym modelu MVC, a więc jego struktura jest podzielona na warstwy modelu, kontrolera i widoku.
Do plików z definicjami naszych kontrolerów dostaniemy się w katalogu:
[code]/src/AppBundle/Controller/[/code]
Do plików widoku natomiast tutaj:
[code]/app/Resources/views/[/code]

Otwórzmy sobie dostępny domyślnie przykładowy plik controllera:
[code]/src/AppBundle/Controllers/DefaultController.php[/code]
Jego zawartość powinna wyglądać następująco:
[code]
<?php
namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    /**
     * @Route("/app/example", name="homepage")
     */
    public function indexAction()
    {
        return $this->render('default/index.html.twig');
    }
}[/code]
Jak widać mamy tutaj definicję klasy kontrolera o nazwie DefaultController.
Trzeba tutaj zrozumieć w jaki sposób działają kontrolery i routing w Symfony.
Otóż kontroler to jakaś sekcja naszej aplikacji, np. jeden kontroler może odpowiadać za obsługę kont użytkowników, inny za obsługę newsów na stronie, jeszcze inny za wyświetlanie i edycję komentarzy.

Każdy taki kontroler jest podzielony na jakieś akcje, np. kontroler do obsługi użytkowników może być podzielony na akcje takie jak:

  • dodawanie użytkownika, 
  • edycja użytkownika, 
  • wyświetlanie profilu, 
  • itp.

Domyślną akcją dla kontrolera jest zawsze akcja o nazwie:
[code]index[/code]
Poszczególne akcje definiujemy w klasie naszego kontrolera stosując się do składni:
[code]nazwaAction()[/code]
czyli po nazwie akcji (pisanej zawsze małymi literami, np. edit, add, profile dodajemy suffix Action.

Przykładowy kontroler do obsługi użytkowników definiujacy trzy akcje może wyglądać np. tak:
[code]
class UsersController extends Controller
{
 
    public function addAction()
    {
        // [...]
    }
 
    public function editAction()
    {
        // [...]
    }
 
    public function profileAction()
    {
        // [...]
    }
}[/code]

Do danej akcji musimy się jednak jakoś dostać z poziomu aplikacji, np.:
[code]http://aplikacja.com/users/add[/code]
lub
[code]http://aplikacja.com/users/profile[/code]
I tutaj do akcji wkracza tzw. routing

Routing

Konfiguracja routingu dla kontrolerów i akcji to bardzo obszerny temat i tutaj liźniemy tylko zasadę jego działania na bazie naszego przykładowego projektu. Wróćmy do naszego domyślnego kontrolera i zobaczmy, że przed definicją metody z akcją index znajduje się adnotacja blokowa o treści:
[code]
/**
* @Route("/app/example", name="homepage")
*/[/code]
Określa ona trasę routingu dla akcji po tej definicji występującej.
W tym przypadku dla akcji index definiowany jest routing o ścieżce /app/example.
Oznacza to, iż do definiowanej tutaj akcji dostaniemy się po wpisaniu w przeglądarce adresu:
[code]http://symfony.localhost/app/example[/code]

Dalsza część kodu, czyli definicja akcji index:
[code]
public function indexAction()
{
    return $this->render('default/index.html.twig');
}[/code]
w tym przypadku zwraca nam do wyświetlenia widok wczytywany z pliku:
[code]/app/Resources/views/default/index.html.twig[/code]
którego treść wygląda tak:
[code]
{% extends 'base.html.twig' %}

{% block body %}
    Homepage.
{% endblock %}[/code]
Temat widoków to również bardzo obszerny temat, więc na razie wystarczy abyśmy wiedzieli jedynie jak to mniej więcej działa.

Wpiszmy teraz w przeglądarce:
[code]http://symfony.localhost/app/example[/code]
Jak widzimy, tym razem nie pojawił nam się już błąd związany z brakiem zdefiniowanego routingu, a wyświetlił nam się szablon zwrócony przez akcję index z naszego kontrolera:



Stwórzmy sobie teraz dla testu nowy plik widoku o nazwie:
[code]/app/Resources/views/default/hello.html.twig[/code]
i wpiszmy do niego:
[code]
{% extends 'base.html.twig' %}

{% block body %}
    Hello World!
{% endblock %}[/code]
Następnie utwórzmy nową akcję i routing do niej w pliku:
[code]/src/AppBundle/Controllers/DefaultController.php[/code]
dopisując ją do klasy kontrolera:
[code]
<?php
namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    /**
     * @Route("/app/example", name="homepage")
     */
    public function indexAction()
    {
        return $this->render('default/index.html.twig');
    }
 
    // nasza nowa akcja
     /**
     * @Route("/app/hello", name="hello")
     */
    public function helloAction()
    {
        return $this->render('default/hello.html.twig');
    }
}[/code]

Dodaliśmy nową akcję, do której dostaniemy się po wpisaniu:
[code]http://symfony.localhost/app/hello[/code]
Zróbmy więc to i zobaczmy co się stanie:


Coś jest nie tak. Ale co? Otóż wszystko jest w jak najlepszym porządku, zapomnieliśmy jedynie o jednej małej rzeczy - o cache'u.

cache:clear

Symfony parsuje i cache'uje wiele elementów, aby generowały się one szybciej. W naszym powyższym przypadku dokonaliśmy zmian w strukturze szablonów dodając nowy element dla akcji hello.

Poprzedni cache jednak tego nie uzwględnia, musimy więc wyczyścić stary cache, aby utworzyć nowy. Służy do tego skrypt:
[code]app/console[/code]
który znajdziemy w katalogu z naszą aplikacją.
Console to tak naprawdę narzędzie, którego będziemy używać często, a jego możliwości nie ograniczają się jedynie do czyszczenia cache'u.
Wejdźmy teraz w terminalu do katalogu z naszą aplikacją, czyli do:
[code]C:/www/symfony/myApp/[/code]
i z jej poziomu wywołajmy:
[code]$ php app/console cache:clear[/code]
Polecenie to wyczyści nam cache, ale uwaga - jedynie dla środowiska developerskiego.
Jeśli chcemy wyczyścić cache dla innego środowiska, np. produkcyjnego, to podajemy jego nazwę:
[code]$ php app/console cache:clear --env=prod[/code]


Po wykonaniu powyższego, czyli wyczyszczeniu folderu cache wejdźmy ponownie na:
[code]http://symfony.localhost/app/hello[/code]
Voila! Nasza dodana akcja wyświetliła się prawidłowo:


Problem z początku

Jak teraz rozwiązać problem z początku - błąd No route found for "GET /"?



Błąd ten otrzymujemy po wejściu na główną ścieżkę naszej aplikacji, czyli:
[code]http://symfony.localhost/[/code]
Otóż dokonamy małych zmian w routingu akcji index.
Otwórzmy plik z kontrolerem:
[code]/src/AppBundle/Controllers/DefaultController.php[/code]
i dla akcji index zamieńmy ścieżkę routingu z:
[code]
/**
* @Route("/app/example", name="homepage")
*/[/code]
na:
[code]
/**
* @Route("/", name="homepage")
*/[/code]
Zapiszmy plik i wejdźmy ponownie na:
[code]http://symfony.localhost/[/code]
Jak widzimy - problem rozwiązany i akcja index wyświetliła nam się domyślnie bez podawania żadnej dodatkowej ścieżki.
Wejście tutaj poprzez środowisko developerskie da nam ponadto kilka ciekawych informacji w pasku debuggera dołączanego na dole strony:

[code]http://symfony.localhost/app_dev.php[/code]



Jak widzimy, mamy podane tutaj w jakim aktualnie kontrolerze się znajdujemy i w jakiej akcji, a także całą masę innych informacji i parametrów.



Z debuggera tego korzystać będziemy często podczas naszej pracy, podobnie jak ze skryptu console i czyszczenia katalogu cache, radzę się więc już na to mentalnie przygotować ;)

Podsumowanie

No i to tyle tytułem wstępu, umiemy już uruchomić Symfony i wiemy jak to wszystko mniej więcej działa. W kolejnych artykułach zaczniemy już normalną pracę z Symfony i poznamy ten framework krok po kroku. Mam nadzieję, że artykuł okazał się pomocny, gdyż szczerze mówiąc instalacja i pierwsze uruchomienie może być naprawdę problematyczne dla osoby, która z Symfony ma styczność po raz pierwszy.

Dokumentacja dostępna na stronie projektu pomija kilka kluczowych rzeczy, w związku z czym początkujący użytkownik może mieć problemy już na samym starcie, mimo iż robi wszystko tak jak zostało to opisane w dokumentacji. Tutaj opisałem to absolutnie krok po kroku i pokazałem rozwiązanie, którego w takiej formie nie znajdziecie w dokumentacji. Do następnego!

4 komentarze:

  1. kiedy kolejna część kursu?

    OdpowiedzUsuń
  2. Nie wiem jak ci mam dziękować. Przestudiowałem wszystkie możliwe tutki, a ten ze strony Symfony2.com chyba ze 6 razy i głupi byłem jak but z lewej nogi. Dzięki tobie, w końcu przeskoczyłem tą "magiczną barierę" by zacząć małymi krokami rozumieć o co chodzi. Dzięki i oby więcej taki rzeczowych tutoriali!! :)

    OdpowiedzUsuń
    Odpowiedzi
    1. Cieszy mnie to :) Za około tydzień lecę z kolejnymi częściami kursu.

      Usuń

Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)

webmaester.pl - profesjonalne projektowanie WWW i webaplikacji
webmaester.pl - profesjonalne projektowanie WWW i webaplikacji