0 follower

Kontroler

Kontroler jest instancją klasy CController lub jej klas potomnych. Jest on tworzony przez aplikację kiedy użytkownik zażąda tego. Kiedy kontroler jest uruchomiony, wykonuje żądaną akcję, która zazwyczaj wprowadza wymagane modele oraz generuje odpowiedni widok. Akcja, w jej najprostszej formie, jest metodą klasy kontrolera, której nazwa rozpoczyna się od słowa action.

Kontroler posiada domyślną akcję. Kiedy żądanie użytkownika nie określa która akcja powinna zostać wykonana, domyślna akcja jest wykonywana. Domyślnie, domyślna akcja nosi nazwę index. Może ona zostać zmieniona poprzez ustawienie CController::defaultAction.

Poniżej znajduje się minimalny kod wymagany przez klasę kontrolera. Ponieważ kontroler nie definiuje żadnej, jeśli zażądamy jakiejś akcji, akcji zostanie rzucony wyjątek.

class SiteController extends CController
{
}

1. Trasa (ang. route)

Kontrolery i akcje są definiowane poprzez ich ID. ID kontrolera posiada format ścieżka/do/xyz która odpowiada plikowi klasy kontrolera protected/controllers/path/to/XyzController.php, gdzie ciąg xyz powinien zostać zastąpiony przez aktualną nazwę (np. post odpowiada protected/controllers/PostController.php). ID akcji jest nazwą metody akcji bez prefiksu action. Na przykład, jeśli klasa kontrolera zawiera metodę nazwaną actionEdit, ID odpowiadającej jej akcji to edit.

Uwaga: Przed wersją 1.0.3, formatem ID kontrolera był ciąg path.to.xyz zamiast path/to/xyz.

Użytkownicy żądają poszczególnych kontrolerów oraz akcji za pomocą trasy. Trasę tworzy połączenie ID kontrolera oraz ID akcji rozdzielone za pomocą ukośnika. Na przykład, trasa post/edit odpowiada kontrolerowi PostController oraz jego akcji edit. Domyślnie, adres URL http://hostname/index.php?r=post/edit będzie żądał tego kontrolera oraz tą akcję.

Uwaga: Domyślnie, trasy rozróżniają wielkość liter. Od wersji 1.0.1, możliwe jest wyłączenie rozróżnienia wielkości liter poprzez ustawienie właściwości CUrlManager::caseSensitive jako false w konfiguracji aplikacji. Będąc w trybie rozróżniania wielkości liter, upewnij się, że używasz konwencji mówiącej, że nazwy folderów zawierające pliki klas kontrolerów zapisane są małymi literami a zarówno mapa kontrolerów oraz mapa akcji używają kluczy zapisanych małymi literami.

Od wersji 1.0.3, aplikacja może posiadać moduły. Trasa dla akcji kontrolera wewnątrz modułu posiada format IDmodułu/IDkontrolera/IDakcji. Aby uzyskać więcej szczegółów zobacz sekcję dotyczącą modułów.

2. Tworzenie instancji kontrolerów (ang. Controller Instantiation)

Instancja kontrolera jest tworzona podczas przetwarzania przez CWebApplication przychodzących żądań. Podając ID kontrolera, aplikacja będzie używała następujących reguł aby zdeterminować, która to klasa kontrolera oraz gdzie plik tej klasy się znajduje.

  • Jeśli CWebApplication::catchAllRequest jest określona, kontroler będzie utworzony bazując na tej właściwości a określone przez użytkownika ID kontrolera będzie ignorowane. Jest to używane głównie do uruchomienia aplikacji w trybie zarządzania i wyświetlania statycznej strony z wiadomością.

  • Jeśli ID zostanie znalezione w CWebApplication::controllerMap odpowiadająca konfiguracja kontrolera będzie użyta do utworzenia instancji kontrolera.

  • Jeśli ID posiada format 'ścieżka/do/xyz', zakłada się, że klasa kontrolera będzie nazywała się XyzController a odpowiadający plik klasy to protected/controllers/path/to/XyzController.php. Na przykład, ID kontrolera admin/user będzie rozszyfrowane jako klasa kontrolera UserController oraz nazwą pliku klasy będzie protected/controllers/admin/UserController.php. Jeśli plik klasy nie istnieje wywoła to błąd 404 CHttpException.

W przypadku gdy używane są moduły (dostępne od wersji 1.0.3), powyższy proces będzie trochę inny. W szczególności, aplikacja sprawdzi czy ID odpowiada kontrolerowi wewnątrz modułu, jeśli tak, instancja modułu zostanie utworzona najpierw poprzedzona przez instancję kontrolera.

3. Akcja

Jak wspomniano wyżej akcja może zostać zdefiniowana jako metoda, której nazwa rozpoczyna się słowem action. Bardziej zaawansowanym sposobem jest zdefiniowanie klasy akcji i poproszenie kontrolera o utworzenie jej instancji na żądanie. To pozwala akcjom być używanym ponownie a to wprowadza możliwość ponownego użycia.

Aby zdefiniować nową klasę akcji, robimy co następuje:

class UpdateAction extends CAction
{
    public function run()
    {
        // umieść logikę akcji
    }
}

W celu poinformowania kontrolera o tej akcji, nadpisujemy metodę actions() naszej klasy kontrolera:

class PostController extends CController
{
    public function actions()
    {
        return array(
            'edit'=>'application.controllers.post.UpdateAction',
        );
    }
}

Powyżej, użyliśmy aliasu ścieżki application.controllers.post.UpdateAction aby określić, że plik klasy akcji to protected/controllers/post/UpdateAction.php.

Pisząc akcje przy użyciu klas, możemy zorganizować aplikację w bardziej zmodularyzowany sposób. Na przykład, następująca struktura katalogu może zostać użyta do zorganizowania kodu dla kontrolerów:

protected/
    controllers/
        PostController.php
        UserController.php
        post/
            CreateAction.php
            ReadAction.php
            UpdateAction.php
        user/
            CreateAction.php
            ListAction.php
            ProfileAction.php
            UpdateAction.php

4. Filtry

Filtr jest częścią kodu, który jest skonfigurowany tak, aby być wywołanym przed i/lub po wywołaniu akcji kontrolera. Na przykład, filtr kontroli dostępu może być wywołany przed wywołaniem żądanej akcji aby upewnić się, że użytkownik jest uwierzytelniony; filtr wydajności może zostać użyty do mierzenia czasu wykonania akcji.

Akcja może posiadać wiele filtrów. Filtry są wykonywane w kolejności pojawiania się na liście folderów. Filtr może zabronić wywołania akcji oraz pozostałych niewykonanych filtrów.

Filtr może zostać zdefiniowany jako metoda kontrolera klasy. Nazwa metody musi rozpoczynać się słowem filter. Na przykład, istnienie metody filterAccessControl definiuje filtr nazwany accessControl. Metoda filtra musi posiadać następującą składnię:

public function filterAccessControl($filterChain)
{
    // wywołaj $filterChain->run() aby kontynuować filtrowanie oraz wykonywanie akcji
}

gdzie $filterChain jest instancją klasy CFilterChain, która reprezentuje listę filtrów powiązanych z żądaną akcją. Wewnątrz metody filtra możemy wywołać $filterChain->run() aby kontynuować filtrowanie oraz wykonywanie akcji.

Filtr może być instancją klasy CFilter lub jej klas pochodnych. Następujący kod definiuje nową klasę filtra:

class PerformanceFilter extends CFilter
{
    protected function preFilter($filterChain)
    {
        // logika która zostanie zastosowana zanim akcja zostanie wywołana
        return true; // false jeśli akcja nie powinna zostać wywołana
    }
 
    protected function postFilter($filterChain)
    {
        // logika, która będzie zastosowana po wywołaniu akcji
    }
}

Aby zastosować filtry do akcji musimy nadpisać metodę CController::filters(). Metoda ta powinna zwrócić tablicę konfiguracji filtrów. Na przykład:

class PostController extends CController
{
    ......
    public function filters()
    {
        return array(
            'postOnly + edit, create',
            array(
                'application.filters.PerformanceFilter - edit, create',
                'unit'=>'second',
            ),
        );
    }
}

Powyższy kod definiuje dwa filtry: postOnly praz PerformanceFilter. Filtr postOnly jest filtrem opartym na metodzie (odpowiadająca filtrowi metoda jest już zdefiniowana w klasie CController); zaś filtr PerformanceFilter jest filtrem opartym na obiekcie. Alias ścieżki application.filters.PerformanceFilter określa, iż plikiem klasy filtru jest protected/filters/PerformanceFilter. W celu skonfigurowania filtru PerformanceFilter używamy tablicy, tak, że może ona zostać użyta do zainicjalizowania wartości właściwości obiektu filtru. Tutaj właściwość unit klasy PerformanceFilter będzie zainicjowana wartością 'second'. Używając operatora plusa oraz minusa, możemy określić dla których akcji filtr powinien a dla których nie powinien mieć zastosowania. W powyższym kodzie filtr postOnly powinien zostać zastosowany dla akcji edit oraz create, zaś filtr PerformanceFilter powinien zostać zastosowany do wszystkich akcji ZA WYJĄTKIEM edit oraz create. Jeśli żaden z operatorów plus lub minus nie pojawia się w konfiguracji filtra, filtr będzie zastosowany do wszystkich akcji.