7.13. 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.

7.13.1. 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:

<?php
$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.

There are several strategies you can take to update your code. In the short term, you can globally disable the ViewRenderer in your front controller bootstrap prior to dispatching:

<?php
// Assuming $front is an instance of Zend_Controller_Front
$front->setParam('noViewRenderer', true);

However, this is not a good long term strategy, as it means most likely you'll be writing more code.

When you're ready to start using the ViewRenderer functionality, there are several things to look for in your controller code. First, look at your action methods (the methods ending in 'Action'), and determine what each is doing. If none of the following is happening, you'll need to make changes:

  • Calls to $this->render()

  • Calls to $this->_forward()

  • Calls to $this->_redirect()

  • Calls to the Redirector action helper

The easiest change is to disable auto rendering for that method:

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

If you find that none of your action methods are rendering, forwarding, or redirecting, you will likely want to put the above line in your preDispatch() or init() methods:

public function preDispatch()
{
    // disable view script autorendering
    $this->_helper->viewRenderer->setNoRender()
    // .. do other things...
}

If you are calling render(), and you're using the Conventional Modular directory structure, you'll want to change your code to make use of autorendering:

  • If you're rendering multiple view scripts in a single action, you don't need to change a thing.

  • If you're simply calling render() with no arguments, you can remove such lines.

  • If you're calling render() with arguments, and not doing any processing afterwards or rendering multiple view scripts, you can change these calls to read $this->_helper->viewRenderer().

If you're not using the conventional modular directory structure, there are a variety of methods for setting the view base path and script path specifications so that you can make use of the ViewRenderer. Please read the ViewRenderer documentation for information on these methods.

If you're using a view object from the registry, or customizing your view object, or using a different view implementation, you'll want to inject the ViewRenderer with this object. This can be done easily at any time.

  • Prior to first instantiating a front controller instance:

    <?php
    // Assuming $view has already been defined
    $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
    Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
    
  • Po odebraniu instancji kontrolera frontowego:

    <?php
    $viewRenderer = Zend_Controller_Action_HelperBroker::getExistingHelper('viewRenderer');
    $viewRenderer->setView($view);
    

There are many ways to modify the ViewRenderer, including setting a different view script to render, specifying replacements for all replaceable elements of a view script path (including the suffix), choosing a response named segment to utilize, and more. If you aren't using the conventional modular directory structure, you can even associate different path specifications with the 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.

7.13.2. 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ń).

7.13.3. 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:

require_once 'Zend/Controller/Front.php';
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.

7.13.4. 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:

require_once 'Zend/Controller/Front.php';
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();

Jakkolwiek, po dodaniu obiektu ???, będziesz potrzebował zmienić ostatnią linię z tego przykładu na:

echo $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 Sekcja 7.4, „The Request Object”.

  • Zend_Controller_Router_Interface::route() przyjmuje i zwraca obiekt Sekcja 7.4, „The Request Object” 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 Sekcja 7.4, „The Request Object” zamiast tokena dispatchera.