# Migracja z poprzednich wersji

API komponentów MVC zmieniało się z biegiem czasu. Jeśli zacząłeś używać Zend Framework we wczesnej wersji, postępuj według poniższych wskazówek aby przeprowadzić migrację swoich skryptów aby używały nowej architektury.

## Migracja z wersji 1.5.x do 1.6.0 lub nowszej

### Zmiany w interfejsie obiektu uruchamiającego

Użytkownicy zwrócili naszą uwagę na fakt, że klasy `Zend_Controller_Front` oraz `Zend_Controller_Router_Route_Module` używały metod obiektu uruchamiającego, które nie były zdefiniowane w interfejsie tego obiektu. Dodaliśmy teraz do interfejsu poniższe trzy metody aby upewnić się, że własne obiekty uruchamiające będą poprawnie działać:

- `getDefaultModule()`: metoda powinna zwracać nazwę domyślnego modułu.

- `getDefaultControllerName()`: metoda powinna zwracać nazwę domyślnego kontrolera.

- `getDefaultAction()`: metoda powinna zwracać nazwę domyślnej akcji.

## Migracja z wersji 1.0.x do 1.5.0 lub nowszej

O ile większość z podstawowych funkcjonalności i cała udokumentowana funkcjonalność pozostały te same, to nastąpiła jedna istotna zmiana w jednej nieudokumentowanej funkcjonalności.

Udokumentowanym sposobem tworzenia adresów URL w postaci camelCased jest użycie znaku separatora w nazwie akcji; domyślnie separatorem mogą być znaki '.' lub '-', jednak może to być skonfigurowane w obiekcie uruchamiającym. Obiekt uruchamiający zmienia litery w nazwie akcji na małe i używa separatorów aby otrzymać nazwę metody akcji w postaci camelCasing. Jednak z tego powodu, że funkcje PHP nie są wrażliwe na wielkość liter, mogłeś wciąż tworzyć adresy w postaci camelCasing, a obiekt uruchamiający wciąż otrzymywał na ich podstawie nazwę tej samej akcji. Na przykład adres 'camel-cased' zostałby zamieniony przez obiekt uruchamiający na 'camelCasedAction', a adres 'camelCased' na 'camelcasedAction'; z tego powodu że PHP nie jest wrażliwe na wielkość liter, w obu przypadkach zostanie uruchomiona ta sama metoda.

Powoduje to problemy w klasie ViewRenderer gdy szuka ona skryptów widoku. Podstawowym udokumentowanym sposobem jest zastępowanie wszystkich separatorów wyrazów znakiem podkreślenia oraz zmiana liter na małe. Wprowadza to niezgodność semantyczną pomiędzy akcjami a skryptami widoków, a regulacja tego pozwoli na znajdowanie skryptów widoków w każdej sytuacji. Teraz jeśli wywołamy metodę 'camelCased', separator wyrazów nie będzie już znajdować się w nazwie i ViewRenderer spróbuje uruchomić inny plik -- 'camelcased.phtml' zamiast 'camel-cased.phtml'.

Niektórzy programiści polegali na tej "funkcjonalności", która nigdy nie była zamierzona. Wiele zmian w wersji 1.5.0 spowodowało, że klasa ViewRenderer nie znajduje już plików widoków w taki sposób; semnatyczna zgodność jest teraz wymuszona. Po pierwsze, obiekt uruchamiający wymusza teraz wrażliwość na wielkość liter w nazwach akcji. Oznacza to, że odwoływanie się do akcji używając w adresie formy camelCasing nie będzie już dłużej prowadzić do tej samej metody, do której prowadziło odwołanie za pomocą separatorów wyrazów (np., 'camel-casing'). Teraz klasa ViewRenderer podczas szukania skryptów widoku akceptuje jedynie formę z separatorami wyrazów.

Jeśli okazało się, że polegałeś na tej "funkcjonalności", masz kilka rozwiązań:

- Najlepsza opcja: zmień nazwy skwoich skryptów wiodku. Plus: kompatybilność wsteczna. Minus: jeśli masz dużo skryptów widoku, które polegają na tym niezamierzonym zachowaniu, możesz mieć dużo plików do zmiany.

- Druga najlepsza opcja: klasa ViewRenderer teraz określa nazwę skryptu widoku za pomocą klasy `Zend_Filter_Inflector`; możesz zmodyfikować reguły określania nazwy, aby nie używać separatorów wyrazów w nazwach akcji.

      $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
      $inflector = $viewRenderer->getInflector();
      $inflector->setFilterRule(':action', array(
          new Zend_Filter_PregReplace(
              '#[^a-z0-9' . preg_quote(DIRECTORY_SEPARATOR, '#') . ']+#i',
              ''
          ),
          'StringToLower'
      ));

  Powyższy kod zmieni sposób określania nazwy skryptu widoku, aby nie oddzielał słów za pomocą znaku podkreślenia; możesz także usunać filtr 'StringToLower' jeśli chcesz używać nazw skryptów widoku w postaci camelCased.

  Jeśli zmiana nazw skryptów widoku zajmie zbyt dużo czasu, najlepszym sposobem będzie tymczasowe użycie powyższego kodu.

- Najgorsza opcja: Możesz spowodować aby obiekt uruchamiający uruchamiał akcje w postaci camelCased za pomocą nowej flagi kontrolera frontowego, 'useCaseSensitiveActions':

      $front->setParam('useCaseSensitiveActions', true);

  Pozwoli ci to wciąż używać formy camelCasing w adresach URL i taie wywołanie będzie uruchamiać tę samą akcję jak podczas użycia separatorów wyrazów. Jednak oznacza to, że oryginalny błąd będzie wciąż występował; jeśli nie chcesz aby wystąpiły problemy, użyj przynajmniej drugiej z przedstawionych opcji.

  Zauważ też, że użycie tej flagi spowoduje wyświetlenie informacji o tym, że jej użycie jest przestarzałe.

## Migracja z wersji 0.9.3 do 1.0.0RC1 lub nowszej

Głównymi zmianami, jakie pojawiły się w wersji 1.0.0RC1 jest dodanie i domyśle włączenie wtyczki ErrorHandler oraz pomocniczej klasy akcji ViewRenderer. Proszę przeczytaj uważnie dokumentację obu komponentów aby dowiedzieć się jak one działają i jakie efekty mogą one mieć w twoich aplikacjach.

Wtyczka `ErrorHandler` jest uruchamiana jako metoda `postDispatch()` w celu sprawdzenia czy wyrzucone zostały wyjątki i ewentualnego przeniesienia żądania do określonego kontrolera obsługi błędów. Powinieneś mieć taki kontroler w swojej aplikacji. Możesz jednak wyłączyć taką obsługę błędów ustawiając w kontrolerze frontowym parametr `noErrorHandler`:

    $front->setParam('noErrorHandler', true);

Pomocnicza klasa akcji `ViewRenderer` automatyzuje przekazywanie widoków do kontrolerów akcji oraz automatycznie renderuje skrypty widoku oparte na nazwie danej akcji. Głównym problemem jaki możesz napotkać są akcje, które nie renderują skryptów widoków, nie przekierowują i nie przenoszą żądania, z tego względu, że klasa `ViewRenderer` będzie próbować renderować skrypt widoku oparty na nazwie akcji.

Jest kilka strategii które możesz podjąc aby zaktualizować swój kod. Krótkoterminowo możesz globalnie wyłączyć użycie klasy `ViewRenderer` w kontrolerze frontowym w pliku uruchamiającym przed uruchomieniem żądania:

    // Zakładając, że $front jest instancją klasy Zend_Controller_Front
    $front->setParam('noViewRenderer', true);

Jednak długoterminowo nie jest to dobra strategia, ponieważ będziesz musiał pisać więcej kodu.

Kiedy będziesz gotowy do użycia funkcjonalności klasy `ViewRenderer`, będzie kilka rzeczy które będziesz musiał sprawdzić w kodzie swoich kontrolerów.

Wpierw spójrz na metody akcji (metody kończące się na 'Action') i sprawdź co one robią. Będziesz musiał wprowadzić zmiany, jeśli w metodzie nie jest przeprowadzana żadna z poniższych czynności:

- Wywołanie metody `$this->render()`

- Wywołanie metody `$this->_forward()`

- Wywołanie metody `$this->_redirect()`

- Wywołanie pomocniczej klasy akcji `Redirector`

Najprostszym sposobem jest wyłączenie automatycznego renderowania dla tej metody:

    $this->_helper->viewRenderer->setNoRender();

Jeśli żadna z twoich akcji nie renderuje, nie przenosi i nie przekierowuje, możesz powyższą linię umieścić w metodzie `preDispatch()` lub `init()`:

    public function preDispatch()
    {
        // wyłączamy automatyczne renderowanie skryptu widoku
        $this->_helper->viewRenderer->setNoRender()
        // .. robimy coś dalej...
    }

Jeśli wywołujesz metodę `render()`, i używasz klasycznej modularnej struktury katalogów, możesz potrzebować zaktualizować swój kod aby używał automatycznego renderowania:

- Jeśli renderujesz wiele skryptów widoków w jednej akcji, nie musisz nic zmieniać w tej kwestii.

- Jeśli wywołujesz metodę `render()` bez argumentów, możesz po prostu usunąć te wywołania.

- Jeśli wywołujesz metodę `render()` używając argumentów i nie wykonujesz później innego kodu ani nie renderujesz kolejnych skryptów widoku, możesz zmienić wywołania aby korzystały z metody o tej samej nazwie, obiektu `$this->_helper->viewRenderer()`.

Jeśli nie używasz klasycznej modularnej struktury katalogów, jest wiele sposobów ustawienia bazowej ścieżki widoków i specyfikacji ścieżek skryptów, do czego możesz użyć klasy `ViewRenderer`. Proszę przeczytaj dokumentację klasy ViewRenderer aby uzyskać więcej informacji na temat tych metod.

Jeśli używasz obiektu widoku z rejestru, konfigurujesz swój własny obiekt lub używasz innej implementacji widoku, możesz przekazać ten obiekt do obiektu `ViewRenderer`. Możesz to łatwo zrobić w dowolnym momencie.

- Przed uruchomieniem kontrolera frontowego:

      // Zakładając, że obiekt $view został już zdefiniowany
      $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
      Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

- W dowolnej chwili podczas procesu ładowania:

      $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
      $viewRenderer->setView($view);

Jest wiele sposobów na zmodyfikowanie obiektu `ViewRenderer`, włączając w to ustawienie innego skryptu widoku do renderowania, zastąpienie wszystkich części ścieżki skrytu widoku (także przyrostka), wybranie segmentu obiektu odpowiedzi w którym ma być zrenderowany i kilka innych. Jeśli nie chcesz używać klasycznej modularnej struktury katalogów, możesz określić inne specyfikacje ścieżek za pomocą klasy `ViewRenderer`.

Zalecamy zaadaptowanie w swoim kodzie użycia wtyczki `ErrorHandler` oraz pomocniczej klasy akcji `ViewRenderer` z tego względu, że te funkcjonalności są teraz składnikiem jądra.

## Migracja z wersji 0.9.2 do 0.9.3 lub nowszej

W wersji 0.9.3 pojawiają się klasy pomocnicze akcji. W związku z tym, poniższe metody zostały usunięte, z tego względu, że teraz są one zawarte w przekierowującej pomocniczej klasie akcji:

- `setRedirectCode()`; użyj `Zend_Controller_Action_Helper_Redirector::setCode()`.

- `setRedirectPrependBase()`; użyj `Zend_Controller_Action_Helper_Redirector::setPrependBase()`.

- `setRedirectExit()`; użyj `Zend_Controller_Action_Helper_Redirector::setExit()`.

Przeczytaj dokumentację pomocniczych klas akcji aby uzyskać więcej informacji o tym jak można pobrać obiekty pomocnicze i jak nimi manipulować, oraz dokumentację przekierowującej pomocniczej klasy akcji w celu uzyskania informacji o ustawianiu opcji przekierowania (a także o innych metodach dla przekierowań).

## Migracja z wersji 0.6.0 do 0.8.0 lub nowszej

Od czasu poprzednich zmian, najbardziej podstawowe użycie komponentów MVC pozostaje takie same:

    Zend_Controller_Front::run('/path/to/controllers');

Jakkolwiek, struktura katalogów została przebudowana, kilka komponentów usunięto, kilku innym zmieniono nazwy, a także kilka dodano. Zmiany to:

- Klasa `Zend_Controller_Router` została usunięta na rzecz rewrite routera.

- Nazwa klasy `Zend_Controller_RewriteRouter` została zmieniona na `Zend_Controller_Router_Rewrite` i awansowała ona na standardowy router dostarczany z frameworkiem; `Zend_Controller_Front` użyje go domyślnie, jeśli żaden inny router nie zostanie ustawiony.

- Nowa klasa trasy doa użycia z rewrite routerem została przedstawiona, jest to `Zend_Controller_Router_Route_Module`; kryje ona w sobie domyślną trasę używaną przez MVC i wspiera moduły kontrolerów.

- Nazwa klasy `Zend_Controller_Router_StaticRoute` została zmieniona na `Zend_Controller_Router_Route_Static`.

- Nazwa klasy `Zend_Controller_Dispatcher` została zmieniona na `Zend_Controller_Dispatcher_Standard`.

- Zmieniły się argumenty metody `Zend_Controller_Action::_forward()`. Sygnatura wygląda teraz następująco:

      final protected function _forward($action, $controller = null, $module = null, array $params = null);

  Parametr `$action` jest zawsze wymagany; jeśli kontroler nie jest określony, to brana pod uwagę jest akcja z obecnego kontrolera. Parametr `$module` jest zawsze ignorowany, o ile parametr `$controller` nie jest określony. Ostatecznie każdy z parametrów w tablicy `$params` będzie dołączony do obiektu żądania. Jeśli nie potrzebujesz określić kontrolera lub modułu, ale potrzebujesz przekazać parametry, po prostu określ te wartości jako null.

## Migracja z wersji 0.2.0 lub z poprzednich do 0.6.0

Podstawowy sposób korzystania z komponentów MVC nie zmienił się; nadal możesz użyć poniższego kodu:

    Zend_Controller_Front::run('/path/to/controllers');

    /* -- utwórz router -- */
    $router = new Zend_Controller_RewriteRouter();
    $router->addRoute('user', 'user/:username', array('controller' => 'user',
    'action' => 'info'));

    /* -- ustawić go w kontrolerze -- */
    $ctrl = Zend_Controller_Front::getInstance();
    $ctrl->setRouter($router);

    /* -- ustawić katalog kontrolerów i uruchomić -- */
    $ctrl->setControllerDirectory('/path/to/controllers');
    $ctrl->dispatch();

Zalecamy użycie obiektu odpowiedzi (Response) do łączenia zawartości i nagłówków. To pozwala na bardziej elastyczne zmiany formatu danych wyjściowych (na przykład JSON lub XML zamiast XHTML) w twoich aplikacjach. Domyślnie metoda `dispatch()` zrenderuje całą odpowiedź, wyśle nagłówki i całą zawartość. Możesz także użyć kontrolera frontowego aby zwrócił zawartość za pomocą metody `returnResponse()`, a potem zrenderować odpowiedź używając twojej własnej logiki. Przyszłe wersje kontrolera frontowego mogą forsować użycie obiektu odpowiedzi przez wyświetlenie danych wyjściowych.

Jest wiele dodatkowych funkcjonalności, które rozszerzają istniejące API i są one opisane w dokumentacji.

Główne zmiany, na które musisz uważać, nastąpiły przy tworzeniu klas pochodnych komponentów. Te zmiany to:

- `Zend_Controller_Front::dispatch()` domyślnie łapie wyjątki w obiekcie odpowiedzi i nie renderuje ich aby zapobiec wyświetlaniu ważnych informacji systemowych. Możesz zmienić to zachowanie na kilka sposobów:

  - Ustaw `throwExceptions()` w kontrolerze frontowym:

        $front->throwExceptions(true);

  - Ustaw `renderExceptions()` w obiekcie odpowiedzi:

        $response->renderExceptions(true);
        $front->setResponse($response);
        $front->dispatch();

        // lub:
        $front->returnResponse(true);
        $response = $front->dispatch();
        $response->renderExceptions(true);
        echo $response;

- `Zend_Controller_Dispatcher_Interface::dispatch()` zamiast tokena dispatchera przyjmuje i zwraca teraz obiekt .

- `Zend_Controller_Router_Interface::route()` przyjmuje i zwraca obiekt zamiast tokena dispatchera.

- Zmiany w `Zend_Controller_Action` to:

  - Kontruktor teraz przyjmuje dokładnie trzy argumenty, `Zend_Controller_Request_Abstract $request`, `Zend_Controller_Response_Abstract $response`, oraz `array $params (opcjonalny)`. `Zend_Controller_Action::__construct()` używa ich aby ustawić żądanie, odpowiedź, i właściwości invokeArgs obiektu i jeśli nadpisujesz konstruktor, powinieneś je także ustawić. Lepiej jednak użyj metody `init()` aby skonfigurować instancję, ponieważ ta metoda jest wywoływana jako ostatnia akcja konstruktora.

  - Metoda `run()` nie jest już zdefiniowana jako finalna, ale nie jest też już używana przez kontroler frontowy; Jej jedynym celem jest użycie klasy jako kontrolera strony. Przyjmuje ona teraz dwa opcjonalne argumenty, `Zend_Controller_Request_Abstract $request` oraz `Zend_Controller_Response_Abstract $response`.

  - Akcja `indexAction()` nie musi być już zdefiniowana, ale jest zalecana jako domyślna akcja. To pozwala routerowi RewriteRouter oraz kontrolerom akcji na określenie innych domyślnych metod akcji.

  - Metoda `__call()` powinna być nadpisana aby obsłużyć automatycznie niezdefiniowane akcje.

  - Metoda `_redirect()` przyjmuje teraz opcjonalny drugi argument, kod HTTP, który ma być zwrócony z przekierowaniem oraz opcjonalny trzeci argument, `$prependBase`, który może zdecydować czy bazowy adres URL zarejestrowany w obiekcie żądania ma być dodany do adresu URL.

  - Właściwość `_action` nie jest już zdefiniowana. Ta właściwość była obiektem `Zend_Controller_Dispatcher_Token`, który nie istnieje już w aktualnej wersji. Jedynym zastosowaniem tokena było przechowanie informacji o zażądanym kontrolerze, akcji i parametrach URL. Te informacje są teraz dostępne w obiekcie żądania w taki sposób:

        // Pobierz nazwę kontrolera z żądania
        // Dotychczas dostęp do niej był za pomocą: $this->_action->getControllerName().
        // Poniższy przykład używa metody getRequest(), ale możesz także bezpośrednio
        // użyć właściwości $_request; użycie getRequest() jest zalecane ponieważ klasa
        // rodzica może nadpisać dostęp do obiektu żądania.
        $controller = $this->getRequest()->getControllerName();

        // Pobierz nazwę akcji z żądania
        // Dotychczas dostęp do niej był za pomocą: $this->_action->getActionName().
        $action = $this->getRequest()->getActionName();

        // Pobierz parametry z żądania
        // To się nie zmieniło; metody _getParams() oraz _getParam() teraz w prosty
        // sposób wskazują na obiekt żądania.
        $params = $this->_getParams();
        $foo = $this->_getParam('foo', 'default'); // pobierz parametr 'foo', używając
                                                   // wartości 'default' jako domyślnej

  - Metoda `noRouteAction()` została usunięta. Aby w poprawny sposób obsługiwać nieistniejące metody akcji powinieneś przekierować je do domyślnej akcji używając metody `__call()`:

        public function __call($method, $args)
        {
            // Jeśli została zażądania nieistniejąca metoda 'Action', żądanie zostanie
            // przekazane do domyślnej metody akcji:
            if ('Action' == substr($method, -6)) {
                return $this->defaultAction();
            }

            throw new Zend_Controller_Exception('Nieprawdiłowa metoda');
        }

- Akcja `Zend_Controller_RewriteRouter::setRewriteBase()` została usunięta. W zamian użyj `Zend_Controller_Front::setBaseUrl()` (lub Zend_Controller_Request_Http::setBaseUrl(), jeśli używasz tej klasy).

- Interfejs `Zend_Controller_Plugin_Interface` został zamieniony na `Zend_Controller_Plugin_Abstract`. Wszystkie metody przyjmują i zwracają obiekt zamiast tokena dispatchera.